ExampleLink::ExampleLink( string const & recordName, string providerName, string channelName, PVStructurePtr const & pvStructure) : PVRecord(recordName,pvStructure), providerName(providerName), channelName(channelName), convert(getConvert()) { }
namespace epics { namespace pvaClient { typedef std::tr1::shared_ptr<PVArray> PVArrayPtr; static ConvertPtr convert = getConvert(); static string noStructure("no pvStructure "); static string noValue("no value field"); static string noScalar("value is not a scalar"); static string noArray("value is not an array"); static string noScalarArray("value is not a scalarArray"); static string noAlarm("no alarm"); static string noTimeStamp("no timeStamp"); PvaClientDataPtr PvaClientData::create(StructureConstPtr const & structure) { if(PvaClient::getDebug()) cout << "PvaClientData::create\n"; PvaClientDataPtr epv(new PvaClientData(structure)); return epv; } PvaClientData::PvaClientData(StructureConstPtr const & structure) : structure(structure) { } void PvaClientData::checkValue() { if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n"; if(pvValue) return; throw std::runtime_error(messagePrefix + noValue); } void PvaClientData::setMessagePrefix(std::string const & value) { messagePrefix = value + " "; } StructureConstPtr PvaClientData::getStructure() { return structure; } PVStructurePtr PvaClientData::getPVStructure() { if(pvStructure) return pvStructure; throw std::runtime_error(messagePrefix + noStructure); } BitSetPtr PvaClientData::getChangedBitSet() { if(bitSet)return bitSet; throw std::runtime_error(messagePrefix + noStructure); } std::ostream & PvaClientData::showChanged(std::ostream & out) { if(!bitSet) throw std::runtime_error(messagePrefix + noStructure); size_t nextSet = bitSet->nextSetBit(0); PVFieldPtr pvField; while(nextSet!=string::npos) { if(nextSet==0) { pvField = pvStructure; } else { pvField = pvStructure->getSubField(nextSet); } string name = pvField->getFullName(); out << name << " = " << pvField << endl; nextSet = bitSet->nextSetBit(nextSet+1); } return out; } void PvaClientData::setData( PVStructurePtr const & pvStructureFrom, BitSetPtr const & bitSetFrom) { if(PvaClient::getDebug()) cout << "PvaClientData::setData\n"; pvStructure = pvStructureFrom; bitSet = bitSetFrom; pvValue = pvStructure->getSubField("value"); } bool PvaClientData::hasValue() { if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n"; if(!pvValue) return false; return true; } bool PvaClientData::isValueScalar() { if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalar\n"; if(!pvValue) return false; if(pvValue->getField()->getType()==scalar) return true; return false; } bool PvaClientData::isValueScalarArray() { if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalarArray\n"; if(!pvValue) return false; if(pvValue->getField()->getType()==scalarArray) return true; return false; } PVFieldPtr PvaClientData::getValue() { if(PvaClient::getDebug()) cout << "PvaClientData::getValue\n"; checkValue(); return pvValue; } PVScalarPtr PvaClientData::getScalarValue() { if(PvaClient::getDebug()) cout << "PvaClientData::getScalarValue\n"; checkValue(); if(pvValue->getField()->getType()!=scalar) { throw std::runtime_error(messagePrefix + noScalar); } return pvStructure->getSubField<PVScalar>("value"); } PVArrayPtr PvaClientData::getArrayValue() { if(PvaClient::getDebug()) cout << "PvaClientData::getArrayValue\n"; checkValue(); Type type = pvValue->getField()->getType(); if(type!=scalarArray && type!=structureArray && type!=unionArray) { throw std::runtime_error(messagePrefix + noArray); } return pvStructure->getSubField<PVArray>("value"); } PVScalarArrayPtr PvaClientData::getScalarArrayValue() { if(PvaClient::getDebug()) cout << "PvaClientData::getScalarArrayValue\n"; checkValue(); Type type = pvValue->getField()->getType(); if(type!=scalarArray) { throw std::runtime_error(messagePrefix + noScalarArray); } return pvStructure->getSubField<PVScalarArray>("value"); } double PvaClientData::getDouble() { if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n"; PVScalarPtr pvScalar; PVStructurePtr pvStructure = getPVStructure(); PVFieldPtr pvValue = pvStructure->getSubField("value"); if(pvValue) { Type type = pvValue->getField()->getType(); if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue); } if(!pvScalar) { while(true) { const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); if(fieldPtrArray.size()!=1) { throw std::logic_error( "PvaClientData::getDouble() pvRequest for multiple fields"); } PVFieldPtr pvField(fieldPtrArray[0]); Type type = pvField->getField()->getType(); if(type==scalar) { pvScalar = static_pointer_cast<PVScalar>(pvField); break; } if(pvField->getField()->getType()!=epics::pvData::structure) break; pvStructure = static_pointer_cast<PVStructure>(pvField); } } if(!pvScalar) { throw std::logic_error( "PvaClientData::getDouble() did not find a scalar field"); } ScalarType scalarType = pvScalar->getScalar()->getScalarType(); if(scalarType==pvDouble) { PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar); return pvDouble->get(); } if(!ScalarTypeFunc::isNumeric(scalarType)) { throw std::logic_error( "PvaClientData::getDouble() did not find a numeric scalar field"); } return convert->toDouble(pvScalar); } string PvaClientData::getString() { if(PvaClient::getDebug()) cout << "PvaClientData::getString\n"; PVScalarPtr pvScalar; PVStructurePtr pvStructure = getPVStructure(); PVFieldPtr pvValue = pvStructure->getSubField("value"); if(pvValue) { Type type = pvValue->getField()->getType(); if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue); } if(!pvScalar) { while(true) { const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); if(fieldPtrArray.size()!=1) { throw std::logic_error( "PvaClientData::getString() pvRequest for multiple fields"); } PVFieldPtr pvField(fieldPtrArray[0]); Type type = pvField->getField()->getType(); if(type==scalar) { pvScalar = static_pointer_cast<PVScalar>(pvField); break; } if(pvField->getField()->getType()!=epics::pvData::structure) break; pvStructure = static_pointer_cast<PVStructure>(pvField); } } if(!pvScalar) { throw std::logic_error( "PvaClientData::getString() did not find a scalar field"); } return convert->toString(pvScalar); } shared_vector<const double> PvaClientData::getDoubleArray() { if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n"; PVScalarArrayPtr pvScalarArray; PVStructurePtr pvStructure = getPVStructure(); PVFieldPtr pvValue = pvStructure->getSubField("value"); if(pvValue) { Type type = pvValue->getField()->getType(); if(type==scalarArray) { pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue); } } if(!pvScalarArray) { while(true) { const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); if(fieldPtrArray.size()!=1) { throw std::logic_error( "PvaClientData::getDoubleArray() pvRequest for multiple fields"); } PVFieldPtr pvField(fieldPtrArray[0]); Type type = pvField->getField()->getType(); if(type==scalarArray) { pvScalarArray = static_pointer_cast<PVScalarArray>(pvField); break; } if(pvField->getField()->getType()!=epics::pvData::structure) break; pvStructure = static_pointer_cast<PVStructure>(pvField); } } if(!pvScalarArray) { throw std::logic_error( "PvaClientData::getDoubleArray() did not find a scalarArray field"); } ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); if(!ScalarTypeFunc::isNumeric(scalarType)) { throw std::logic_error( "PvaClientData::getDoubleArray() did not find a numeric scalarArray field"); } shared_vector<const double> retValue; pvScalarArray->getAs<const double>(retValue); return retValue; } shared_vector<const string> PvaClientData::getStringArray() { if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n"; PVScalarArrayPtr pvScalarArray; PVStructurePtr pvStructure = getPVStructure(); PVFieldPtr pvValue = pvStructure->getSubField("value"); if(pvValue) { Type type = pvValue->getField()->getType(); if(type==scalarArray) { pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue); } } if(!pvScalarArray) { while(true) { const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields()); if(fieldPtrArray.size()!=1) { throw std::logic_error( "PvaClientData::getStringArray() pvRequest for multiple fields"); } PVFieldPtr pvField(fieldPtrArray[0]); Type type = pvField->getField()->getType(); if(type==scalarArray) { pvScalarArray = static_pointer_cast<PVScalarArray>(pvField); break; } if(pvField->getField()->getType()!=epics::pvData::structure) break; pvStructure = static_pointer_cast<PVStructure>(pvField); } } if(!pvScalarArray) { throw std::logic_error( "PvaClientData::getStringArray() did not find a scalarArray field"); } shared_vector<const string> retValue; pvScalarArray->getAs<const string>(retValue); return retValue; } Alarm PvaClientData::getAlarm() { if(PvaClient::getDebug()) cout << "PvaClientData::getAlarm\n"; if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure); PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm"); if(!pvs) throw std::runtime_error(messagePrefix + noAlarm); pvAlarm.attach(pvs); if(pvAlarm.isAttached()) { Alarm alarm; pvAlarm.get(alarm); pvAlarm.detach(); return alarm; } throw std::runtime_error(messagePrefix + noAlarm); } TimeStamp PvaClientData::getTimeStamp() { if(PvaClient::getDebug()) cout << "PvaClientData::getTimeStamp\n"; if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure); PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp"); if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp); pvTimeStamp.attach(pvs); if(pvTimeStamp.isAttached()) { TimeStamp timeStamp; pvTimeStamp.get(timeStamp); pvTimeStamp.detach(); return timeStamp; } throw std::runtime_error(messagePrefix + noTimeStamp); } }}
namespace epics { namespace pvaClient { static ConvertPtr convert = getConvert(); static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static StandardFieldPtr standardField = getStandardField(); PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create( PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) { PvaClientMultiMonitorDoublePtr pvaClientMultiMonitorDouble( new PvaClientMultiMonitorDouble(pvaMultiChannel,pvaClientChannelArray)); return pvaClientMultiMonitorDouble; } PvaClientMultiMonitorDouble::PvaClientMultiMonitorDouble( PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) : pvaClientMultiChannel(pvaClientMultiChannel), pvaClientChannelArray(pvaClientChannelArray), nchannel(pvaClientChannelArray.size()), doubleValue(shared_vector<double>(nchannel,epicsNAN)), pvaClientMonitor(std::vector<PvaClientMonitorPtr>(nchannel,PvaClientMonitorPtr())), isMonitorConnected(false), isDestroyed(false) { } PvaClientMultiMonitorDouble::~PvaClientMultiMonitorDouble() { destroy(); } void PvaClientMultiMonitorDouble::destroy() { { Lock xx(mutex); if(isDestroyed) return; isDestroyed = true; } pvaClientChannelArray.clear(); } void PvaClientMultiMonitorDouble::connect() { shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); string request = "value"; for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request); pvaClientMonitor[i]->issueConnect(); } } for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { Status status = pvaClientMonitor[i]->waitConnect(); if(status.isOK()) continue; string message = string("channel ") + pvaClientChannelArray[i]->getChannelName() + " PvaChannelMonitor::waitConnect " + status.getMessage(); throw std::runtime_error(message); } } for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) pvaClientMonitor[i]->start(); } isMonitorConnected = true; } bool PvaClientMultiMonitorDouble::poll() { if(!isMonitorConnected){ connect(); epicsThreadSleep(.01); } bool result = false; shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { if(pvaClientMonitor[i]->poll()) { doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble(); pvaClientMonitor[i]->releaseEvent(); result = true; } } } return result; } bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent) { if(poll()) return true; TimeStamp start; start.getCurrent(); TimeStamp now; while(true) { epicsThreadSleep(.1); if(poll()) return true; now.getCurrent(); double diff = TimeStamp::diff(now,start); if(diff>=waitForEvent) break; } return false; } epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get() { return doubleValue; } }}
bool operator==(PVField& left, PVField& right) { return getConvert()->equals(left,right); }
namespace epics { namespace pvaClient { static ConvertPtr convert = getConvert(); static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static StandardFieldPtr standardField = getStandardField(); static CreateRequest::shared_pointer createRequest = CreateRequest::create(); PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create( PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) { PvaClientMultiPutDoublePtr pvaClientMultiPutDouble( new PvaClientMultiPutDouble(pvaMultiChannel,pvaClientChannelArray)); return pvaClientMultiPutDouble; } PvaClientMultiPutDouble::PvaClientMultiPutDouble( PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientChannelArray const &pvaClientChannelArray) : pvaClientMultiChannel(pvaClientMultiChannel), pvaClientChannelArray(pvaClientChannelArray), nchannel(pvaClientChannelArray.size()), pvaClientPut(std::vector<PvaClientPutPtr>(nchannel,PvaClientPutPtr())), isPutConnected(false), isDestroyed(false) { } PvaClientMultiPutDouble::~PvaClientMultiPutDouble() { destroy(); } void PvaClientMultiPutDouble::destroy() { { Lock xx(mutex); if(isDestroyed) return; isDestroyed = true; } pvaClientChannelArray.clear(); } void PvaClientMultiPutDouble::connect() { shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { pvaClientPut[i] = pvaClientChannelArray[i]->createPut(); pvaClientPut[i]->issueConnect(); } } for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { Status status = pvaClientPut[i]->waitConnect(); if(status.isOK()) continue; string message = string("channel ") + pvaClientChannelArray[i]->getChannelName() + " PvaChannelPut::waitConnect " + status.getMessage(); throw std::runtime_error(message); } } isPutConnected = true; } void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data) { if(!isPutConnected) connect(); if(data.size()!=nchannel) { throw std::runtime_error("data has wrong size"); } shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); for(size_t i=0; i<nchannel; ++i) { if(isConnected[i]) { PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure(); PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value"); convert->fromDouble(pvValue,data[i]); pvaClientPut[i]->issuePut(); } if(isConnected[i]) { Status status = pvaClientPut[i]->waitPut(); if(status.isOK()) continue; string message = string("channel ") + pvaClientChannelArray[i]->getChannelName() + " PvaChannelPut::waitPut " + status.getMessage(); throw std::runtime_error(message); } } } }}
namespace epics { namespace pvaClient { class PvaClientPostHandlerPvt: public PostHandler { PvaClientPutData * easyData; size_t fieldNumber; public: PvaClientPostHandlerPvt(PvaClientPutData *easyData,size_t fieldNumber) : easyData(easyData),fieldNumber(fieldNumber){} void postPut() { easyData->postPut(fieldNumber);} }; typedef std::tr1::shared_ptr<PVArray> PVArrayPtr; static ConvertPtr convert = getConvert(); static string noValue("no value field"); static string notScalar("value is not a scalar"); static string notCompatibleScalar("value is not a compatible scalar"); static string notArray("value is not an array"); static string notScalarArray("value is not a scalarArray"); static string notDoubleArray("value is not a doubleArray"); static string notStringArray("value is not a stringArray"); PvaClientPutDataPtr PvaClientPutData::create(StructureConstPtr const & structure) { PvaClientPutDataPtr epv(new PvaClientPutData(structure)); return epv; } PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure) : structure(structure), pvStructure(getPVDataCreate()->createPVStructure(structure)), bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields()))) { messagePrefix = ""; size_t nfields = pvStructure->getNumberFields(); postHandler.resize(nfields); PVFieldPtr pvField; for(size_t i =0; i<nfields; ++i) { postHandler[i] = PostHandlerPtr(new PvaClientPostHandlerPvt(this, i)); if(i==0) { pvField = pvStructure; } else { pvField = pvStructure->getSubField(i); } pvField->setPostHandler(postHandler[i]); } pvValue = pvStructure->getSubField("value"); } void PvaClientPutData::checkValue() { if(pvValue) return; throw std::runtime_error(messagePrefix + noValue); } void PvaClientPutData::postPut(size_t fieldNumber) { bitSet->set(fieldNumber); } void PvaClientPutData::setMessagePrefix(std::string const & value) { messagePrefix = value + " "; } StructureConstPtr PvaClientPutData::getStructure() {return structure;} PVStructurePtr PvaClientPutData::getPVStructure() {return pvStructure;} BitSetPtr PvaClientPutData::getChangedBitSet() {return bitSet;} std::ostream & PvaClientPutData::showChanged(std::ostream & out) { size_t nextSet = bitSet->nextSetBit(0); PVFieldPtr pvField; while(nextSet!=string::npos) { if(nextSet==0) { pvField = pvStructure; } else { pvField = pvStructure->getSubField(nextSet); } string name = pvField->getFullName(); out << name << " = " << pvField << endl; nextSet = bitSet->nextSetBit(nextSet+1); } return out; } bool PvaClientPutData::hasValue() { if(!pvValue) return false; return true; } bool PvaClientPutData::isValueScalar() { if(!pvValue) return false; if(pvValue->getField()->getType()==scalar) return true; return false; } bool PvaClientPutData::isValueScalarArray() { if(!pvValue) return false; if(pvValue->getField()->getType()==scalarArray) return true; return false; } PVFieldPtr PvaClientPutData::getValue() { checkValue(); return pvValue; } PVScalarPtr PvaClientPutData::getScalarValue() { checkValue(); PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value"); if(!pv) throw std::runtime_error(messagePrefix + notScalar); return pv; } PVArrayPtr PvaClientPutData::getArrayValue() { checkValue(); PVArrayPtr pv = pvStructure->getSubField<PVArray>("value"); if(!pv) throw std::runtime_error(messagePrefix + notArray); return pv; } PVScalarArrayPtr PvaClientPutData::getScalarArrayValue() { checkValue(); PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value"); if(!pv) throw std::runtime_error(messagePrefix + notScalarArray); return pv; } double PvaClientPutData::getDouble() { PVScalarPtr pvScalar = getScalarValue(); ScalarType scalarType = pvScalar->getScalar()->getScalarType(); if(scalarType==pvDouble) { PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar); return pvDouble->get(); } if(!ScalarTypeFunc::isNumeric(scalarType)) { throw std::runtime_error(messagePrefix + notCompatibleScalar); } return convert->toDouble(pvScalar); } string PvaClientPutData::getString() { PVScalarPtr pvScalar = getScalarValue(); return convert->toString(pvScalar); } shared_vector<const double> PvaClientPutData::getDoubleArray() { checkValue(); PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value"); if(!pv) { throw std::runtime_error(messagePrefix + notDoubleArray); } return pv->view(); } shared_vector<const string> PvaClientPutData::getStringArray() { checkValue(); PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value"); if(!pv) { throw std::runtime_error(messagePrefix + notStringArray); } return pv->view(); } void PvaClientPutData::putDouble(double value) { PVScalarPtr pvScalar = getScalarValue(); ScalarType scalarType = pvScalar->getScalar()->getScalarType(); if(scalarType==pvDouble) { PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar); pvDouble->put(value); return; } if(!ScalarTypeFunc::isNumeric(scalarType)) { throw std::runtime_error(messagePrefix + notCompatibleScalar); } convert->fromDouble(pvScalar,value); } void PvaClientPutData::putString(std::string const & value) { PVScalarPtr pvScalar = getScalarValue(); convert->fromString(pvScalar,value); } void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value) { checkValue(); PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value"); if(!pv) { throw std::runtime_error(messagePrefix + notDoubleArray); } pv->replace(value); } void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value) { checkValue(); PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value"); if(!pv) { throw std::runtime_error(messagePrefix + notStringArray); } pv->replace(value); } void PvaClientPutData::putStringArray(std::vector<std::string> const & value) { checkValue(); PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value"); if(!pv) { throw std::runtime_error(messagePrefix + notScalarArray); } convert->fromStringArray(pv,0,value.size(),value,0); } }}