diff --git a/src/Makefile b/src/Makefile index c8302a9..8c2c927 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,11 +15,13 @@ INC += pv/pvDatabase.h INC += pv/traceRecord.h INC += pv/removeRecord.h INC += pv/numericRecord.h - +INC += pv/pvSupport.h +INC += pv/controlSupport.h include $(PVDATABASE_SRC)/copy/Makefile include $(PVDATABASE_SRC)/database/Makefile include $(PVDATABASE_SRC)/pvAccess/Makefile include $(PVDATABASE_SRC)/special/Makefile +include $(PVDATABASE_SRC)/support/Makefile pvDatabase_LIBS += $(EPICS_BASE_PVA_CORE_LIBS) pvDatabase_LIBS += $(EPICS_BASE_IOC_LIBS) diff --git a/src/pv/controlSupport.h b/src/pv/controlSupport.h new file mode 100644 index 0000000..ce90158 --- /dev/null +++ b/src/pv/controlSupport.h @@ -0,0 +1,82 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvData is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/** + * @author mrk + * @date 2019.06.01 + */ +#ifndef CONTROLSUPPORT_H +#define CONTROLSUPPORT_H + +#ifdef epicsExportSharedSymbols +# define pvdatabaseEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#include +#include + +#ifdef pvdatabaseEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef pvdatabaseEpicsExportSharedSymbols +#endif + +#include +#include + +namespace epics { namespace pvDatabase { + +class ControlSupport; +typedef std::tr1::shared_ptr ControlSupportPtr; + +/** + * @brief Base interface for a ControlSupport. + * + */ +class epicsShareClass ControlSupport : + PVSupport +{ +public: + POINTER_DEFINITIONS(ControlSupport); + /** + * The Destructor. + */ + virtual ~ControlSupport(); + /** + * @brief Optional initialization method. + * + * A derived method Must call initControlSupport. + * @return true for success and false for failure. + */ + virtual bool init(); + /** + * @brief Optional method for derived class. + * + * + */ + virtual void process(); + /** + * @brief Optional method for derived class. + * + */ + virtual void reset(); + static ControlSupportPtr create(PVRecordPtr const & pvRecord); +private: + ControlSupport(PVRecordPtr const & pvRecord); + PVRecordPtr pvRecord; + epics::pvData::PVScalarPtr pvValue; + epics::pvData::PVStructurePtr pvControl; + epics::pvData::PVDoublePtr pvLimitLow; + epics::pvData::PVDoublePtr pvLimitHigh; + epics::pvData::PVDoublePtr pvMinStep; + double requestedValue; + double currentValue; + bool isMinStep; +}; + +}} + +#endif /* CONTROLSUPPORT_H */ + diff --git a/src/pv/numericRecord.h b/src/pv/numericRecord.h index be3a4b9..f1f502d 100644 --- a/src/pv/numericRecord.h +++ b/src/pv/numericRecord.h @@ -14,6 +14,7 @@ #include #include +#include namespace epics { namespace pvDatabase { @@ -54,15 +55,8 @@ private: NumericRecord( std::string const & recordName, epics::pvData::PVStructurePtr const & pvStructure); - epics::pvData::PVScalarPtr pvValue; - epics::pvData::PVStructurePtr pvControl; - epics::pvData::PVStructurePtr pvValueAlarm; - epics::pvData::PVDoublePtr pvLimitLow; - epics::pvData::PVDoublePtr pvLimitHigh; - epics::pvData::PVDoublePtr pvMinStep; - double requestedValue; - double currentValue; - bool isMinStep; + ControlSupportPtr controlSupport; + epics::pvData::PVBooleanPtr pvReset; }; }} diff --git a/src/pv/pvSupport.h b/src/pv/pvSupport.h new file mode 100644 index 0000000..be17c23 --- /dev/null +++ b/src/pv/pvSupport.h @@ -0,0 +1,84 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvData is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/** + * @author mrk + * @date 2019.06.01 + */ +#ifndef PVSUPPORT_H +#define PVSUPPORT_H + +#ifdef epicsExportSharedSymbols +# define pvdatabaseEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#include +#include + +#include +#include +#include + + +#ifdef pvdatabaseEpicsExportSharedSymbols +# define epicsExportSharedSymbols +# undef pvdatabaseEpicsExportSharedSymbols +#endif + +#include +#include + +namespace epics { namespace pvDatabase { + +class PVSupport; +typedef std::tr1::shared_ptr PVSupportPtr; + +/** + * @brief Base interface for a PVSupport. + * + */ +class epicsShareClass PVSupport +{ +public: + POINTER_DEFINITIONS(PVSupport); + /** + * The Destructor. + */ + virtual ~PVSupport(){} + /** + * @brief Optional initialization method. + * + * A derived method Must call initPVSupport. + * @return true for success and false for failure. + */ + virtual bool init() {return true;} + /** + * @brief Optional method for derived class. + * + * It is called before record is added to database. + */ + virtual void start() {} + /** + * @brief Optional method for derived class. + * + * It is the method that makes a record smart. + * If it encounters errors it should raise alarms and/or + * call the message method provided by the base class. + * If the pvStructure has a top level timeStamp, + * the base class sets the timeStamp to the current time. + */ + virtual void process() = 0; + /** + * @brief Optional method for derived class. + * + */ + virtual void reset() {}; +}; + +}} + +#endif /* PVSUPPORT_H */ + diff --git a/src/special/numericRecord.cpp b/src/special/numericRecord.cpp index 9da7789..cc922a1 100644 --- a/src/special/numericRecord.cpp +++ b/src/special/numericRecord.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #define epicsExportSharedSymbols @@ -36,6 +37,7 @@ NumericRecordPtr NumericRecord::create( StandardFieldPtr standardField = getStandardField(); StructureConstPtr topStructure = fieldCreate->createFieldBuilder()-> add("value",scalarType) -> + add("reset",pvBoolean) -> add("alarm",standardField->alarm()) -> add("timeStamp",standardField->timeStamp()) -> add("display",standardField->display()) -> @@ -59,82 +61,22 @@ NumericRecord::NumericRecord( bool NumericRecord::init() { initPVRecord(); - PVStructurePtr pvStructure = getPVStructure(); - PVFieldPtr pv(pvStructure->getSubField("value")); - if(pv) { - if(pv->getField()->getType()==epics::pvData::scalar) { - ScalarConstPtr s = static_pointer_cast(pv->getField()); - if(ScalarTypeFunc::isNumeric(s->getScalarType())) { - pvValue = static_pointer_cast(pv); - } - } - } - if(!pvValue) { - cout << "create record " << getRecordName() - << " failed because not numeric scalar\n"; - return false; - } - ConvertPtr convert = getConvert(); - requestedValue = convert->toDouble(pvValue); - currentValue = requestedValue; - isMinStep = false; - pvControl = pvStructure->getSubField("control"); - pvLimitLow = pvControl->getSubField("limitLow"); - pvLimitHigh = pvControl->getSubField("limitHigh"); - pvMinStep = pvControl->getSubField("minStep"); - pvValueAlarm = pvStructure->getSubField("valueAlarm"); + PVRecordPtr pvRecord = shared_from_this(); + controlSupport = ControlSupport::create(pvRecord); + bool result = controlSupport->init(); + if(!result) return false; + pvReset = getPVStructure()->getSubField("reset"); return true; } void NumericRecord::process() { - ConvertPtr convert = getConvert(); - double value = convert->toDouble(pvValue); -cout << "value " << value -<< " requestedValue " << requestedValue -<< " currentValue " << currentValue -<< " isMinStep " << (isMinStep ? "true" : "false") -<< "\n"; - if(value==requestedValue&&value==currentValue) { - PVRecord::process(); - return; + if(pvReset->get()==true) { + pvReset->put(false); + controlSupport->reset(); + } else { + controlSupport->process(); } - if(!isMinStep) requestedValue = value; - double limitLow = pvLimitLow->get(); - double limitHigh = pvLimitHigh->get(); - double minStep = pvMinStep->get(); - if(limitHigh>limitLow) { - if(value>limitHigh) value = limitHigh; - if(valuelimitHigh) requestedValue = limitHigh; - if(requestedValue0.0) { - double diff = requestedValue - currentValue; - if(diff<0.0) { - value = currentValue - minStep; - isMinStep = true; - if(valuerequestedValue) { - value = requestedValue; - isMinStep = false; - } - } -cout << "diff " << diff -<< " value " << value -<< " isMinStep " << (isMinStep ? "true" : "false") -<< "\n"; - } - currentValue = value; - convert->fromDouble(pvValue,value); PVRecord::process(); } diff --git a/src/support/Makefile b/src/support/Makefile new file mode 100644 index 0000000..b8a9af9 --- /dev/null +++ b/src/support/Makefile @@ -0,0 +1,5 @@ +# This is a Makefile fragment, see ../Makefile + +SRC_DIRS += $(PVDATABASE_SRC)/support + +LIBSRCS += controlSupport.cpp diff --git a/src/support/controlSupport.cpp b/src/support/controlSupport.cpp new file mode 100644 index 0000000..c83c7db --- /dev/null +++ b/src/support/controlSupport.cpp @@ -0,0 +1,125 @@ +/* controlSupport.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvData is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/** + * @author mrk + * @date 2019.06.01 + */ +#include +#include +#include +#include + +#define epicsExportSharedSymbols + +#include + +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace std; + +namespace epics { namespace pvDatabase { + +ControlSupport::~ControlSupport() +{ +cout << "ControlSupport::~ControlSupport()\n"; +} + +ControlSupportPtr ControlSupport::create(PVRecordPtr const & pvRecord) +{ + ControlSupportPtr support(new ControlSupport(pvRecord)); + return support; +} + +ControlSupport::ControlSupport(PVRecordPtr const & pvRecord) + : pvRecord(pvRecord) +{} + +bool ControlSupport::init() +{ + PVStructurePtr pvStructure = pvRecord->getPVStructure(); + PVFieldPtr pv(pvStructure->getSubField("value")); + if(pv) { + if(pv->getField()->getType()==epics::pvData::scalar) { + ScalarConstPtr s = static_pointer_cast(pv->getField()); + if(ScalarTypeFunc::isNumeric(s->getScalarType())) { + pvValue = static_pointer_cast(pv); + } + } + } + if(!pvValue) { + cout << "ControlSupport for record " << pvRecord->getRecordName() + << " failed because not numeric scalar\n"; + return false; + } + ConvertPtr convert = getConvert(); + requestedValue = convert->toDouble(pvValue); + currentValue = requestedValue; + isMinStep = false; + pvControl = pvStructure->getSubField("control"); + pvLimitLow = pvControl->getSubField("limitLow"); + pvLimitHigh = pvControl->getSubField("limitHigh"); + pvMinStep = pvControl->getSubField("minStep"); + return true; +} + +void ControlSupport::process() +{ + ConvertPtr convert = getConvert(); + double value = convert->toDouble(pvValue); +cout << "value " << value +<< " requestedValue " << requestedValue +<< " currentValue " << currentValue +<< " isMinStep " << (isMinStep ? "true" : "false") +<< "\n"; + if(value==requestedValue&&value==currentValue) return; + if(!isMinStep) requestedValue = value; + double limitLow = pvLimitLow->get(); + double limitHigh = pvLimitHigh->get(); + double minStep = pvMinStep->get(); + if(limitHigh>limitLow) { + if(value>limitHigh) value = limitHigh; + if(valuelimitHigh) requestedValue = limitHigh; + if(requestedValue0.0) { + double diff = requestedValue - currentValue; + if(diff<0.0) { + value = currentValue - minStep; + isMinStep = true; + if(valuerequestedValue) { + value = requestedValue; + isMinStep = false; + } + } +cout << "diff " << diff +<< " value " << value +<< " isMinStep " << (isMinStep ? "true" : "false") +<< "\n"; + } + currentValue = value; + convert->fromDouble(pvValue,value); +} + +void ControlSupport::reset() +{ + isMinStep = false; +} + + +}} +