diff --git a/src/ca/caChannel.cpp b/src/ca/caChannel.cpp index d3baef2..6a1cf81 100644 --- a/src/ca/caChannel.cpp +++ b/src/ca/caChannel.cpp @@ -833,7 +833,8 @@ CAChannelMonitor::CAChannelMonitor( pvRequest(pvRequest), isStarted(false), monitorEventThread(MonitorEventThread::get()), - pevid(NULL) + pevid(NULL), + eventMask(DBE_VALUE | DBE_ALARM) {} CAChannelMonitor::~CAChannelMonitor() @@ -869,6 +870,15 @@ void CAChannelMonitor::activate() ss >> size; if (size > 1) queueSize = size; } + pvString = pvOptions->getSubField("DBE"); + if(pvString) { + std::string value(pvString->get()); + eventMask = 0; + if(value.find("VALUE")!=std::string::npos) eventMask|=DBE_VALUE; + if(value.find("ARCHIVE")!=std::string::npos) eventMask|=DBE_ARCHIVE; + if(value.find("ALARM")!=std::string::npos) eventMask|=DBE_ALARM; + if(value.find("PROPERTY")!=std::string::npos) eventMask|=DBE_PROPERTY; + } } notifyMonitorRequester = NotifyMonitorRequesterPtr(new NotifyMonitorRequester()); notifyMonitorRequester->setChannelMonitor(shared_from_this()); @@ -941,7 +951,7 @@ Status CAChannelMonitor::start() channel->attachContext(); int result = ca_create_subscription(dbdToPv->getRequestType(), 0, - channel->getChannelID(), DBE_VALUE, + channel->getChannelID(), eventMask, ca_subscription_handler, this, &pevid); if (result == ECA_NORMAL) diff --git a/src/ca/caChannel.h b/src/ca/caChannel.h index 46a4563..cfaf549 100644 --- a/src/ca/caChannel.h +++ b/src/ca/caChannel.h @@ -264,6 +264,7 @@ private: bool isStarted; MonitorEventThreadPtr monitorEventThread; evid pevid; + unsigned long eventMask; NotifyMonitorRequesterPtr notifyMonitorRequester; DbdToPvPtr dbdToPv; diff --git a/src/ca/dbdToPv.cpp b/src/ca/dbdToPv.cpp index 409a0ec..254ba7f 100644 --- a/src/ca/dbdToPv.cpp +++ b/src/ca/dbdToPv.cpp @@ -46,6 +46,11 @@ DbdToPvPtr DbdToPv::create( DbdToPv::DbdToPv(IOType ioType) : ioType(ioType), + dbfIsUCHAR(false), + dbfIsUSHORT(false), + dbfIsULONG(false), + dbfIsINT64(false), + dbfIsUINT64(false), valueRequested(false), alarmRequested(false), timeStampRequested(false), @@ -53,6 +58,7 @@ DbdToPv::DbdToPv(IOType ioType) controlRequested(false), valueAlarmRequested(false), isArray(false), + charArrayIsString(false), firstTime(true), caValueType(-1), caRequestType(-1), @@ -79,10 +85,15 @@ static chtype getDbrType(const ScalarType scalarType) { case pvString : return DBR_STRING; case pvByte : return DBR_CHAR; + case pvUByte : return DBR_CHAR; case pvShort : return DBR_SHORT; + case pvUShort : return DBR_SHORT; case pvInt : return DBR_LONG; + case pvUInt : return DBR_LONG; case pvFloat : return DBR_FLOAT; case pvDouble : return DBR_DOUBLE; + case pvLong : return DBR_DOUBLE; + case pvULong : return DBR_DOUBLE; default: break; } throw std::runtime_error("getDbr: illegal scalarType"); @@ -196,25 +207,72 @@ void DbdToPv::activate( return; } + ScalarType st = dbr2ST[channelType]; + PVStringPtr pvValue = fieldPVStructure->getSubField("value._options.dbtype"); + if(pvValue) + { + std::string value(pvValue->get()); + if(value.find("DBF_UCHAR")!=std::string::npos) { + if(st==pvByte) { + dbfIsUCHAR = true; + st = pvUByte; + caValueType = DBR_CHAR; + } + } else if(value.find("DBF_USHORT")!=std::string::npos) { + if(st==pvInt) { + dbfIsUSHORT = true; + st = pvUShort; + caValueType = DBR_SHORT; + } + } else if(value.find("DBF_ULONG")!=std::string::npos) { + if(st==pvDouble) { + dbfIsULONG = true; + st = pvUInt; + caValueType = DBR_LONG; + } + } else if(value.find("DBF_INT64")!=std::string::npos) { + if(st==pvDouble) { + dbfIsINT64 = true; + st = pvLong; + } + } else if(value.find("DBF_UINT64")!=std::string::npos) { + if(st==pvDouble) { + dbfIsUINT64 = true; + st = pvULong; + } + } + + } + if(st==pvString) { + displayRequested = false; + controlRequested = false; + valueAlarmRequested = false; + } maxElements = ca_element_count(channelID); if(maxElements!=1) isArray = true; if(isArray) { controlRequested = false; valueAlarmRequested = false; + if(channelType==DBR_CHAR && fieldPVStructure) + { + PVStringPtr pvValue = fieldPVStructure->getSubField("value._options.pvtype"); + if(pvValue) { + std::string value(pvValue->get()); + if(value.find("pvString")!=std::string::npos) { + charArrayIsString = true; + st = pvString; + } + } + } } - ScalarType st = dbr2ST[channelType]; - if(st==pvString) { - displayRequested = false; - controlRequested = false; - valueAlarmRequested = false; - } + if(controlRequested || displayRequested || valueAlarmRequested) timeStampRequested = false; FieldCreatePtr fieldCreate(FieldCreate::getFieldCreate()); PVDataCreatePtr pvDataCreate(PVDataCreate::getPVDataCreate()); FieldBuilderPtr fieldBuilder(fieldCreate->createFieldBuilder()); if(valueRequested) { - if(isArray) { + if(isArray && !charArrayIsString) { fieldBuilder->addArray("value",st); } else { fieldBuilder->add("value",st); @@ -228,14 +286,19 @@ void DbdToPv::activate( switch(st) { case pvByte: + case pvUByte: fieldBuilder->add("valueAlarm",standardField->byteAlarm()); break; case pvShort: + case pvUShort: fieldBuilder->add("valueAlarm",standardField->shortAlarm()); break; case pvInt: + case pvUInt: fieldBuilder->add("valueAlarm",standardField->intAlarm()); break; case pvFloat: fieldBuilder->add("valueAlarm",standardField->floatAlarm()); break; case pvDouble: + case pvLong: + case pvULong: fieldBuilder->add("valueAlarm",standardField->doubleAlarm()); break; default: throw std::runtime_error("DbDToPv::activate: bad type"); @@ -392,18 +455,51 @@ Status DbdToPv::getFromDBD( break; } case DBR_CHAR: + if(charArrayIsString) + { + const char * pchar = static_cast(value); + std::string str(pchar); + PVStringPtr pvValue(pvStructure->getSubField("value")); + pvValue->put(str); + break; + } + if(dbfIsUCHAR) + { + copy_DBRScalarArray(value,count,pvValue); + break; + } copy_DBRScalarArray(value,count,pvValue); break; case DBR_SHORT: + if(dbfIsUSHORT) + { + copy_DBRScalarArray(value,count,pvValue); + break; + } copy_DBRScalarArray(value,count,pvValue); break; case DBR_LONG: + if(dbfIsULONG) + { + copy_DBRScalarArray(value,count,pvValue); + break; + } copy_DBRScalarArray(value,count,pvValue); break; case DBR_FLOAT: copy_DBRScalarArray(value,count,pvValue); break; case DBR_DOUBLE: + if(dbfIsINT64) + { + copy_DBRScalarArray(value,count,pvValue); + break; + } + if(dbfIsUINT64) + { + copy_DBRScalarArray(value,count,pvValue); + break; + } copy_DBRScalarArray(value,count,pvValue); break; default: @@ -434,11 +530,40 @@ Status DbdToPv::getFromDBD( break; } case DBR_STRING: copy_DBRScalar(value,pvValue); break; - case DBR_CHAR: copy_DBRScalar(value,pvValue); break; - case DBR_SHORT: copy_DBRScalar(value,pvValue); break; - case DBR_LONG: copy_DBRScalar(value,pvValue); break; + case DBR_CHAR: + if(dbfIsUCHAR) + { + copy_DBRScalar(value,pvValue); + break; + } + copy_DBRScalar(value,pvValue); break; + case DBR_SHORT: + if(dbfIsUSHORT) + { + copy_DBRScalar(value,pvValue); + break; + } + copy_DBRScalar(value,pvValue); break; + case DBR_LONG: + if(dbfIsULONG) + { + copy_DBRScalar(value,pvValue); + break; + } + copy_DBRScalar(value,pvValue); break; case DBR_FLOAT: copy_DBRScalar(value,pvValue); break; - case DBR_DOUBLE: copy_DBRScalar(value,pvValue); break; + case DBR_DOUBLE: + if(dbfIsINT64) + { + copy_DBRScalar(value,pvValue); + break; + } + if(dbfIsUINT64) + { + copy_DBRScalar(value,pvValue); + break; + } + copy_DBRScalar(value,pvValue); break; default: Status errorStatus( Status::STATUSTYPE_ERROR, string("DbdToPv::getFromDBD logic error")); @@ -726,18 +851,63 @@ Status DbdToPv::putToDBD( break; } case DBR_CHAR: + if(charArrayIsString) + { + PVStringPtr pvValue(pvStructure->getSubField("value")); + const char * pchar = pvValue->get().c_str(); + pValue = pchar; + count = pvValue->get().length(); + break; + } + if(dbfIsUCHAR) + { + pValue = put_DBRScalarArray(&count,pvValue); + break; + } pValue = put_DBRScalarArray(&count,pvValue); break; case DBR_SHORT: + if(dbfIsUSHORT) + { + pValue = put_DBRScalarArray(&count,pvValue); + break; + } pValue = put_DBRScalarArray(&count,pvValue); break; case DBR_LONG: + if(dbfIsULONG) + { + pValue = put_DBRScalarArray(&count,pvValue); + break; + } pValue = put_DBRScalarArray(&count,pvValue); break; case DBR_FLOAT: pValue = put_DBRScalarArray(&count,pvValue); break; case DBR_DOUBLE: + if(dbfIsINT64) + { + PVLongArrayPtr pvValue(pvStructure->getSubField("value")); + PVLongArray::const_svector sv(pvValue->view()); + pvDoubleArray = PVDoubleArrayPtr(getPVDataCreate()->createPVScalarArray()); + pvDoubleArray->putFrom(sv); + const double * pdouble = pvDoubleArray->view().data(); + count = pvValue->getLength(); + pValue = pdouble; + break; + } + if(dbfIsUINT64) + { + PVULongArrayPtr pvValue(pvStructure->getSubField("value")); + PVULongArray::const_svector sv(pvValue->view()); + pvDoubleArray = PVDoubleArrayPtr(getPVDataCreate()->createPVScalarArray()); + pvDoubleArray->putFrom(sv); + const double * pdouble = pvDoubleArray->view().data(); + count = pvValue->getLength(); + pValue = pdouble; + break; + } pValue = put_DBRScalarArray(&count,pvValue); break; default: @@ -755,14 +925,43 @@ Status DbdToPv::putToDBD( break; } case DBR_STRING: pValue = pvStructure->getSubField("value")->get().c_str(); break; - case DBR_CHAR: pValue = put_DBRScalar(&bvalue,pvValue); break; - case DBR_SHORT: pValue = put_DBRScalar(&svalue,pvValue); break; - case DBR_LONG: pValue = put_DBRScalar(&lvalue,pvValue); break; + case DBR_CHAR: + if(dbfIsUCHAR) + { + pValue = put_DBRScalar(&bvalue,pvValue); + break; + } + pValue = put_DBRScalar(&bvalue,pvValue); break; + case DBR_SHORT: + if(dbfIsUSHORT) + { + pValue = put_DBRScalar(&svalue,pvValue); + break; + } + pValue = put_DBRScalar(&svalue,pvValue); break; + case DBR_LONG: + if(dbfIsULONG) + { + pValue = put_DBRScalar(&lvalue,pvValue); + break; + } + pValue = put_DBRScalar(&lvalue,pvValue); break; case DBR_FLOAT: pValue = put_DBRScalar(&fvalue,pvValue); break; - case DBR_DOUBLE: pValue = put_DBRScalar(&dvalue,pvValue); break; + case DBR_DOUBLE: + if(dbfIsINT64) + { + pValue = put_DBRScalar(&dvalue,pvValue); + break; + } + if(dbfIsUINT64) + { + pValue = put_DBRScalar(&dvalue,pvValue); + break; + } + pValue = put_DBRScalar(&dvalue,pvValue); break; default: Status errorStatus( - Status::STATUSTYPE_ERROR, string("DbdToPv::getFromDBD logic error")); + Status::STATUSTYPE_ERROR, string("DbdToPv::putToDBD logic error")); return errorStatus; } } diff --git a/src/ca/dbdToPv.h b/src/ca/dbdToPv.h index 7fa77d6..1c9a0fa 100644 --- a/src/ca/dbdToPv.h +++ b/src/ca/dbdToPv.h @@ -113,6 +113,11 @@ private: epics::pvData::PVStructurePtr const & pvRequest ); IOType ioType; + bool dbfIsUCHAR; + bool dbfIsUSHORT; + bool dbfIsULONG; + bool dbfIsINT64; + bool dbfIsUINT64; bool valueRequested; bool alarmRequested; bool timeStampRequested; @@ -120,6 +125,7 @@ private: bool controlRequested; bool valueAlarmRequested; bool isArray; + bool charArrayIsString; bool firstTime; chtype caValueType; chtype caRequestType; @@ -132,6 +138,7 @@ private: CaValueAlarm caValueAlarm; epics::pvData::Structure::const_shared_pointer structure; std::vector choices; + epics::pvData::PVDoubleArrayPtr pvDoubleArray; //for dbfIsINT64 and dbfIsUINT64 }; }