add scalarAlarmSupport
This commit is contained in:
@ -17,6 +17,7 @@ INC += pv/removeRecord.h
|
||||
INC += pv/numericRecord.h
|
||||
INC += pv/pvSupport.h
|
||||
INC += pv/controlSupport.h
|
||||
INC += pv/scalarAlarmSupport.h
|
||||
include $(PVDATABASE_SRC)/copy/Makefile
|
||||
include $(PVDATABASE_SRC)/database/Makefile
|
||||
include $(PVDATABASE_SRC)/pvAccess/Makefile
|
||||
|
@ -45,20 +45,22 @@ public:
|
||||
*/
|
||||
virtual ~ControlSupport();
|
||||
/**
|
||||
* @brief Optional initialization method.
|
||||
* @brief Connects to contol fields.
|
||||
*
|
||||
* A derived method <b>Must</b> call initControlSupport.
|
||||
* @param pvValue The field to support.
|
||||
* @param pvSupport Support specific fields.
|
||||
* @return <b>true</b> for success and <b>false</b> for failure.
|
||||
*/
|
||||
virtual bool init();
|
||||
virtual bool init(
|
||||
epics::pvData::PVFieldPtr const & pvValue,
|
||||
epics::pvData::PVFieldPtr const & pvSupport);
|
||||
/**
|
||||
* @brief Optional method for derived class.
|
||||
*
|
||||
* @brief Honors control fields.
|
||||
*
|
||||
*/
|
||||
virtual void process();
|
||||
/**
|
||||
* @brief Optional method for derived class.
|
||||
* @brief If implementing minSteps it sets isMinStep to false.
|
||||
*
|
||||
*/
|
||||
virtual void reset();
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include <pv/controlSupport.h>
|
||||
#include <pv/scalarAlarmSupport.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
@ -23,10 +24,10 @@ class NumericRecord;
|
||||
typedef std::tr1::shared_ptr<NumericRecord> NumericRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief support for control and valueAlarm for a numeric scalar record
|
||||
* @brief support for control and scalarAlarm for a numeric scalar record
|
||||
*
|
||||
* This is support for a record with a top level field that has type scalar.
|
||||
* It provides support for control and valueAlarm
|
||||
* It provides support for control and scalarAlarm
|
||||
*/
|
||||
class epicsShareClass NumericRecord :
|
||||
public PVRecord
|
||||
@ -56,6 +57,7 @@ private:
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
ControlSupportPtr controlSupport;
|
||||
ScalarAlarmSupportPtr scalarAlarmSupport;
|
||||
epics::pvData::PVBooleanPtr pvReset;
|
||||
};
|
||||
|
||||
|
@ -51,10 +51,15 @@ public:
|
||||
/**
|
||||
* @brief Optional initialization method.
|
||||
*
|
||||
* A derived method <b>Must</b> call initPVSupport.
|
||||
* Called after PVRecord is created but before record is installed into PVDatabase.
|
||||
*
|
||||
* @param pvValue The field to support.
|
||||
* @param pvSupport Support specific fields.
|
||||
* @return <b>true</b> for success and <b>false</b> for failure.
|
||||
*/
|
||||
virtual bool init() {return true;}
|
||||
virtual bool init(
|
||||
epics::pvData::PVFieldPtr const & pvValue,
|
||||
epics::pvData::PVFieldPtr const & pvSupport) {return true;}
|
||||
/**
|
||||
* @brief Optional method for derived class.
|
||||
*
|
||||
@ -62,13 +67,10 @@ public:
|
||||
*/
|
||||
virtual void start() {}
|
||||
/**
|
||||
* @brief Optional method for derived class.
|
||||
* @brief Virtual 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.
|
||||
* It is the method that implements support.
|
||||
* It is called each time the record is processed.
|
||||
*/
|
||||
virtual void process() = 0;
|
||||
/**
|
||||
|
107
src/pv/scalarAlarmSupport.h
Normal file
107
src/pv/scalarAlarmSupport.h
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* 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 SCALARALARMSUPPORT_H
|
||||
#define SCALARALARMSUPPORT_H
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define pvdatabaseEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvSupport.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
|
||||
#ifdef pvdatabaseEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef pvdatabaseEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class ScalarAlarmSupport;
|
||||
typedef std::tr1::shared_ptr<ScalarAlarmSupport> ScalarAlarmSupportPtr;
|
||||
|
||||
/**
|
||||
* @brief Base interface for a ScalarAlarmSupport.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass ScalarAlarmSupport :
|
||||
PVSupport
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ScalarAlarmSupport);
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
virtual ~ScalarAlarmSupport();
|
||||
/**
|
||||
* @brief Connects to contol fields.
|
||||
*
|
||||
* @param pvValue The field to support.
|
||||
* @param pvSupport Support specific fields.
|
||||
* @return <b>true</b> for success and <b>false</b> for failure.
|
||||
*/
|
||||
virtual bool init(
|
||||
epics::pvData::PVFieldPtr const & pvValue,
|
||||
epics::pvData::PVStructurePtr const & pvAlarm,
|
||||
epics::pvData::PVFieldPtr const & pvSupport);
|
||||
/**
|
||||
* @brief Honors scalarAlarm fields.
|
||||
*
|
||||
*/
|
||||
virtual void process();
|
||||
/**
|
||||
* @brief If implementing minSteps it sets isMinStep to false.
|
||||
*
|
||||
*/
|
||||
virtual void reset();
|
||||
static ScalarAlarmSupportPtr create(PVRecordPtr const & pvRecord);
|
||||
static epics::pvData::StructureConstPtr scalarAlarm();
|
||||
private:
|
||||
static epics::pvData::StructureConstPtr scalarAlarmField;
|
||||
|
||||
ScalarAlarmSupport(PVRecordPtr const & pvRecord);
|
||||
enum {
|
||||
range_Lolo = 0,
|
||||
range_Low,
|
||||
range_Normal,
|
||||
range_High,
|
||||
range_Hihi,
|
||||
range_Invalid,
|
||||
range_Undefined
|
||||
} AlarmRange;
|
||||
void setAlarm(
|
||||
epics::pvData::PVStructurePtr const & pvAlarm,
|
||||
int alarmRange);
|
||||
PVRecordPtr pvRecord;
|
||||
int prevAlarmRange;
|
||||
epics::pvData::PVScalarPtr pvValue;
|
||||
epics::pvData::PVStructurePtr pvAlarm;
|
||||
epics::pvData::PVStructurePtr pvScalarAlarm;
|
||||
epics::pvData::PVBooleanPtr pvActive;
|
||||
epics::pvData::PVDoublePtr pvLowAlarmLimit;
|
||||
epics::pvData::PVDoublePtr pvLowWarningLimit;
|
||||
epics::pvData::PVDoublePtr pvHighWarningLimit;
|
||||
epics::pvData::PVDoublePtr pvHighAlarmLimit;
|
||||
epics::pvData::PVDoublePtr pvHysteresis;
|
||||
double requestedValue;
|
||||
double currentValue;
|
||||
bool isHystersis;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* SCALARALARMSUPPORT_H */
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <pv/convert.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/controlSupport.h>
|
||||
#include <pv/scalarAlarmSupport.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
@ -42,7 +43,7 @@ NumericRecordPtr NumericRecord::create(
|
||||
add("timeStamp",standardField->timeStamp()) ->
|
||||
add("display",standardField->display()) ->
|
||||
add("control",standardField->control()) ->
|
||||
add("valueAlarm",standardField->doubleAlarm()) ->
|
||||
add("scalarAlarm",ScalarAlarmSupport::scalarAlarm()) ->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
NumericRecordPtr pvRecord(
|
||||
@ -62,8 +63,16 @@ bool NumericRecord::init()
|
||||
{
|
||||
initPVRecord();
|
||||
PVRecordPtr pvRecord = shared_from_this();
|
||||
PVStructurePtr pvStructure(getPVStructure());
|
||||
controlSupport = ControlSupport::create(pvRecord);
|
||||
bool result = controlSupport->init();
|
||||
bool result = controlSupport->init(
|
||||
pvStructure->getSubField("value"),pvStructure->getSubField("control"));
|
||||
if(!result) return false;
|
||||
scalarAlarmSupport = ScalarAlarmSupport::create(pvRecord);
|
||||
result = scalarAlarmSupport->init(
|
||||
pvStructure->getSubField("value"),
|
||||
pvStructure->getSubField<PVStructure>("alarm"),
|
||||
pvStructure->getSubField("scalarAlarm"));
|
||||
if(!result) return false;
|
||||
pvReset = getPVStructure()->getSubField<PVBoolean>("reset");
|
||||
return true;
|
||||
@ -74,8 +83,10 @@ void NumericRecord::process()
|
||||
if(pvReset->get()==true) {
|
||||
pvReset->put(false);
|
||||
controlSupport->reset();
|
||||
scalarAlarmSupport->reset();
|
||||
} else {
|
||||
controlSupport->process();
|
||||
scalarAlarmSupport->process();
|
||||
}
|
||||
PVRecord::process();
|
||||
}
|
||||
|
@ -3,3 +3,4 @@
|
||||
SRC_DIRS += $(PVDATABASE_SRC)/support
|
||||
|
||||
LIBSRCS += controlSupport.cpp
|
||||
LIBSRCS += scalarAlarmSupport.cpp
|
||||
|
@ -39,10 +39,8 @@ ControlSupport::ControlSupport(PVRecordPtr const & pvRecord)
|
||||
: pvRecord(pvRecord)
|
||||
{}
|
||||
|
||||
bool ControlSupport::init()
|
||||
bool ControlSupport::init(PVFieldPtr const & pv,PVFieldPtr const & pvsup)
|
||||
{
|
||||
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());
|
||||
@ -56,14 +54,21 @@ bool ControlSupport::init()
|
||||
<< " failed because not numeric scalar\n";
|
||||
return false;
|
||||
}
|
||||
pvControl = static_pointer_cast<PVStructure>(pvsup);
|
||||
if(pvControl) {
|
||||
pvLimitLow = pvControl->getSubField<PVDouble>("limitLow");
|
||||
pvLimitHigh = pvControl->getSubField<PVDouble>("limitHigh");
|
||||
pvMinStep = pvControl->getSubField<PVDouble>("minStep");
|
||||
}
|
||||
if(!pvControl || !pvLimitLow || !pvLimitHigh || !pvMinStep) {
|
||||
cout << "ControlSupport for record " << pvRecord->getRecordName()
|
||||
<< " failed because pvSupport not a valid control structure\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;
|
||||
}
|
||||
|
||||
@ -71,11 +76,6 @@ 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();
|
||||
|
215
src/support/scalarAlarmSupport.cpp
Normal file
215
src/support/scalarAlarmSupport.cpp
Normal file
@ -0,0 +1,215 @@
|
||||
/* scalarAlarmSupport.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>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/scalarAlarmSupport.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
ScalarAlarmSupport::~ScalarAlarmSupport()
|
||||
{
|
||||
cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n";
|
||||
}
|
||||
|
||||
|
||||
epics::pvData::StructureConstPtr ScalarAlarmSupport::scalarAlarmField =
|
||||
FieldBuilder::begin()
|
||||
->setId("scalarAlarm_t")
|
||||
->add("active", pvBoolean)
|
||||
->add("lowAlarmLimit", pvDouble)
|
||||
->add("lowWarningLimit", pvDouble)
|
||||
->add("highWarningLimit", pvDouble)
|
||||
->add("highAlarmLimit", pvDouble)
|
||||
->add("hysteresis", pvDouble)
|
||||
->createStructure();
|
||||
|
||||
epics::pvData::StructureConstPtr ScalarAlarmSupport::scalarAlarm()
|
||||
{
|
||||
return scalarAlarmField;
|
||||
}
|
||||
|
||||
ScalarAlarmSupportPtr ScalarAlarmSupport::create(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
ScalarAlarmSupportPtr support(new ScalarAlarmSupport(pvRecord));
|
||||
return support;
|
||||
}
|
||||
|
||||
ScalarAlarmSupport::ScalarAlarmSupport(PVRecordPtr const & pvRecord)
|
||||
: pvRecord(pvRecord),
|
||||
prevAlarmRange(range_Undefined)
|
||||
{}
|
||||
|
||||
|
||||
bool ScalarAlarmSupport::init(
|
||||
PVFieldPtr const & pvval,
|
||||
PVStructurePtr const & pvalarm,
|
||||
PVFieldPtr const & pvsup)
|
||||
{
|
||||
if(pvval->getField()->getType()==epics::pvData::scalar) {
|
||||
ScalarConstPtr s = static_pointer_cast<const Scalar>(pvval->getField());
|
||||
if(ScalarTypeFunc::isNumeric(s->getScalarType())) {
|
||||
pvValue = static_pointer_cast<PVScalar>(pvval);
|
||||
}
|
||||
}
|
||||
if(!pvValue) {
|
||||
cout << "ScalarAlarmSupport for record " << pvRecord->getRecordName()
|
||||
<< " failed because not numeric scalar\n";
|
||||
return false;
|
||||
}
|
||||
pvScalarAlarm = static_pointer_cast<PVStructure>(pvsup);
|
||||
if(pvScalarAlarm) {
|
||||
pvActive = pvScalarAlarm->getSubField<PVBoolean>("active");
|
||||
pvLowAlarmLimit = pvScalarAlarm->getSubField<PVDouble>("lowAlarmLimit");
|
||||
pvLowWarningLimit = pvScalarAlarm->getSubField<PVDouble>("lowWarningLimit");
|
||||
pvHighWarningLimit = pvScalarAlarm->getSubField<PVDouble>("highWarningLimit");
|
||||
pvHighAlarmLimit = pvScalarAlarm->getSubField<PVDouble>("highAlarmLimit");
|
||||
pvHysteresis = pvScalarAlarm->getSubField<PVDouble>("hysteresis");
|
||||
}
|
||||
if(!pvScalarAlarm
|
||||
|| !pvActive
|
||||
|| !pvLowAlarmLimit || !pvLowWarningLimit
|
||||
|| !pvLowWarningLimit || !pvHighAlarmLimit
|
||||
|| !pvHysteresis)
|
||||
{
|
||||
cout << "ScalarAlarmSupport for record " << pvRecord->getRecordName()
|
||||
<< " failed because pvSupport not a valid scalarAlarm structure\n";
|
||||
return false;
|
||||
}
|
||||
pvAlarm = pvalarm;
|
||||
ConvertPtr convert = getConvert();
|
||||
requestedValue = convert->toDouble(pvValue);
|
||||
currentValue = requestedValue;
|
||||
isHystersis = false;
|
||||
setAlarm(pvAlarm,range_Undefined);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScalarAlarmSupport::process()
|
||||
{
|
||||
ConvertPtr convert = getConvert();
|
||||
double value = convert->toDouble(pvValue);
|
||||
double lowAlarmLimit = pvLowAlarmLimit->get();
|
||||
double lowWarningLimit = pvLowWarningLimit->get();
|
||||
double highWarningLimit = pvHighWarningLimit->get();
|
||||
double highAlarmLimit = pvHighAlarmLimit->get();
|
||||
double hysteresis = pvHysteresis->get();
|
||||
int alarmRange = range_Normal;
|
||||
if(highAlarmLimit>lowAlarmLimit) {
|
||||
if(value>=highAlarmLimit) {
|
||||
alarmRange = range_Hihi;
|
||||
} else if(value<=lowAlarmLimit) {
|
||||
alarmRange = range_Lolo;
|
||||
}
|
||||
}
|
||||
if(alarmRange==range_Normal && (pvHighWarningLimit>pvLowWarningLimit)) {
|
||||
if(value>=highWarningLimit) {
|
||||
alarmRange = range_High;
|
||||
} else if(value<=lowWarningLimit) {
|
||||
alarmRange = range_Low;
|
||||
}
|
||||
}
|
||||
cout << "ScalarAlarmSupport::process() alarmRange " << alarmRange
|
||||
<< " prevAlarmRange " << prevAlarmRange << "\n";
|
||||
if(alarmRange!=prevAlarmRange) setAlarm(pvAlarm,alarmRange);
|
||||
prevAlarmRange = alarmRange;
|
||||
}
|
||||
|
||||
void ScalarAlarmSupport::reset()
|
||||
{
|
||||
isHystersis = false;
|
||||
}
|
||||
|
||||
void ScalarAlarmSupport::setAlarm(
|
||||
epics::pvData::PVStructurePtr const & pva,
|
||||
int alarmRange)
|
||||
{
|
||||
Alarm alarm;
|
||||
PVAlarm pvAlarm;
|
||||
if(!pvAlarm.attach(pva)) throw std::logic_error("bad alarm field");
|
||||
epics::pvData::AlarmStatus status(epics::pvData::noStatus);
|
||||
epics::pvData::AlarmSeverity severity(epics::pvData::noAlarm);
|
||||
string message;
|
||||
switch (alarmRange) {
|
||||
case range_Lolo :
|
||||
{
|
||||
severity = epics::pvData::majorAlarm;
|
||||
status = epics::pvData::recordStatus;
|
||||
message = "major low alarm";
|
||||
break;
|
||||
}
|
||||
case range_Low :
|
||||
{
|
||||
severity = epics::pvData::minorAlarm;
|
||||
status = epics::pvData::recordStatus;
|
||||
message = "minor low alarm";
|
||||
break;
|
||||
}
|
||||
case range_Normal :
|
||||
{
|
||||
break;
|
||||
}
|
||||
case range_High :
|
||||
{
|
||||
severity = epics::pvData::minorAlarm;
|
||||
status = epics::pvData::recordStatus;
|
||||
message = "minor high alarm";
|
||||
break;
|
||||
}
|
||||
case range_Hihi :
|
||||
{
|
||||
severity = epics::pvData::majorAlarm;
|
||||
status = epics::pvData::recordStatus;
|
||||
message = "major high alarm";
|
||||
break;
|
||||
}
|
||||
case range_Invalid :
|
||||
{
|
||||
severity = epics::pvData::invalidAlarm;
|
||||
status = epics::pvData::recordStatus;
|
||||
message = "invalid alarm";
|
||||
break;
|
||||
}
|
||||
case range_Undefined :
|
||||
{
|
||||
severity = epics::pvData::undefinedAlarm;
|
||||
status = epics::pvData::recordStatus;
|
||||
message = "undefined alarm";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
severity = epics::pvData::undefinedAlarm;
|
||||
status = epics::pvData::recordStatus;
|
||||
message = "bad alarm definition";
|
||||
break;
|
||||
}
|
||||
}
|
||||
alarm.setStatus(status);
|
||||
alarm.setSeverity(severity);
|
||||
alarm.setMessage(message);
|
||||
pvAlarm.set(alarm);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
Reference in New Issue
Block a user