220 lines
6.6 KiB
C++
220 lines
6.6 KiB
C++
/* 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/pvTimeStamp.h>
|
|
#include <pv/rpcService.h>
|
|
#include <pv/convert.h>
|
|
#include <pv/standardField.h>
|
|
#include <pv/alarm.h>
|
|
#include <pv/pvAlarm.h>
|
|
|
|
#define epicsExportSharedSymbols
|
|
#include "pv/pvStructureCopy.h"
|
|
#include "pv/pvSupport.h"
|
|
#include "pv/pvDatabase.h"
|
|
#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()
|
|
{
|
|
return FieldBuilder::begin()
|
|
->setId("scalarAlarm_t")
|
|
->add("lowAlarmLimit", pvDouble)
|
|
->add("lowWarningLimit", pvDouble)
|
|
->add("highWarningLimit", pvDouble)
|
|
->add("highAlarmLimit", pvDouble)
|
|
->add("hysteresis", pvDouble)
|
|
->createStructure();
|
|
}
|
|
|
|
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) {
|
|
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
|
|
|| !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;
|
|
}
|
|
|
|
bool 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
|
|
||(prevAlarmRange==range_Hihi && value>=highAlarmLimit-hysteresis)) {
|
|
alarmRange = range_Hihi;
|
|
} else if(value<=lowAlarmLimit
|
|
||(prevAlarmRange==range_Lolo && value<=lowAlarmLimit+hysteresis)) {
|
|
alarmRange = range_Lolo;
|
|
}
|
|
}
|
|
if(alarmRange==range_Normal && (highWarningLimit>lowWarningLimit)) {
|
|
if(value>=highWarningLimit
|
|
||(prevAlarmRange==range_High && value>=highWarningLimit-hysteresis)) {
|
|
alarmRange = range_High;
|
|
} else if(value<=lowWarningLimit
|
|
||(prevAlarmRange==range_Low && value<=lowWarningLimit+hysteresis)) {
|
|
alarmRange = range_Low;
|
|
}
|
|
}
|
|
bool retValue = false;
|
|
if(alarmRange!=prevAlarmRange) {
|
|
setAlarm(pvAlarm,alarmRange);
|
|
retValue = true;
|
|
}
|
|
prevAlarmRange = alarmRange;
|
|
currentValue = value;
|
|
return retValue;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
}}
|
|
|