add support

This commit is contained in:
mrkraimer
2019-06-01 12:28:21 -04:00
parent 247839b94d
commit b052e28788
7 changed files with 314 additions and 80 deletions

View File

@ -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)

82
src/pv/controlSupport.h Normal file
View File

@ -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 <pv/pvDatabase.h>
#include <pv/pvSupport.h>
#ifdef pvdatabaseEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvdatabaseEpicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvStructureCopy.h>
namespace epics { namespace pvDatabase {
class ControlSupport;
typedef std::tr1::shared_ptr<ControlSupport> 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 <b>Must</b> call initControlSupport.
* @return <b>true</b> for success and <b>false</b> 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 */

View File

@ -14,6 +14,7 @@
#include <shareLib.h>
#include <pv/channelProviderLocal.h>
#include <pv/controlSupport.h>
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;
};
}}

84
src/pv/pvSupport.h Normal file
View File

@ -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 <list>
#include <map>
#include <pv/pvData.h>
#include <pv/pvTimeStamp.h>
#include <pv/rpcService.h>
#ifdef pvdatabaseEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvdatabaseEpicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvStructureCopy.h>
namespace epics { namespace pvDatabase {
class PVSupport;
typedef std::tr1::shared_ptr<PVSupport> 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 <b>Must</b> call initPVSupport.
* @return <b>true</b> for success and <b>false</b> 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 <b>message</b> 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 */

View File

@ -11,6 +11,7 @@
#include <pv/pvDatabase.h>
#include <pv/convert.h>
#include <pv/standardField.h>
#include <pv/controlSupport.h>
#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<const Scalar>(pv->getField());
if(ScalarTypeFunc::isNumeric(s->getScalarType())) {
pvValue = static_pointer_cast<PVScalar>(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<PVStructure>("control");
pvLimitLow = pvControl->getSubField<PVDouble>("limitLow");
pvLimitHigh = pvControl->getSubField<PVDouble>("limitHigh");
pvMinStep = pvControl->getSubField<PVDouble>("minStep");
pvValueAlarm = pvStructure->getSubField<PVStructure>("valueAlarm");
PVRecordPtr pvRecord = shared_from_this();
controlSupport = ControlSupport::create(pvRecord);
bool result = controlSupport->init();
if(!result) return false;
pvReset = getPVStructure()->getSubField<PVBoolean>("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(value<limitLow) value = limitLow;
if(!isMinStep) {
if(requestedValue>limitHigh) requestedValue = limitHigh;
if(requestedValue<limitLow) requestedValue = limitLow;
}
}
if(minStep>0.0) {
double diff = requestedValue - currentValue;
if(diff<0.0) {
value = currentValue - minStep;
isMinStep = true;
if(value<requestedValue) {
value = requestedValue;
isMinStep = false;
}
} else {
value = currentValue + minStep;
isMinStep = true;
if(value>requestedValue) {
value = requestedValue;
isMinStep = false;
}
}
cout << "diff " << diff
<< " value " << value
<< " isMinStep " << (isMinStep ? "true" : "false")
<< "\n";
}
currentValue = value;
convert->fromDouble(pvValue,value);
PVRecord::process();
}

5
src/support/Makefile Normal file
View File

@ -0,0 +1,5 @@
# This is a Makefile fragment, see ../Makefile
SRC_DIRS += $(PVDATABASE_SRC)/support
LIBSRCS += controlSupport.cpp

View File

@ -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 <pv/pvDatabase.h>
#include <pv/pvSupport.h>
#include <pv/convert.h>
#include <pv/standardField.h>
#define epicsExportSharedSymbols
#include <pv/controlSupport.h>
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<const Scalar>(pv->getField());
if(ScalarTypeFunc::isNumeric(s->getScalarType())) {
pvValue = static_pointer_cast<PVScalar>(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<PVStructure>("control");
pvLimitLow = pvControl->getSubField<PVDouble>("limitLow");
pvLimitHigh = pvControl->getSubField<PVDouble>("limitHigh");
pvMinStep = pvControl->getSubField<PVDouble>("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(value<limitLow) value = limitLow;
if(!isMinStep) {
if(requestedValue>limitHigh) requestedValue = limitHigh;
if(requestedValue<limitLow) requestedValue = limitLow;
}
}
if(minStep>0.0) {
double diff = requestedValue - currentValue;
if(diff<0.0) {
value = currentValue - minStep;
isMinStep = true;
if(value<requestedValue) {
value = requestedValue;
isMinStep = false;
}
} else {
value = currentValue + minStep;
isMinStep = true;
if(value>requestedValue) {
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;
}
}}