Add AFTC flag for bi record and fix mbbi AFTC bug (#817)
* Add AFTC feature to bi record with tests. * Fix broken AFTC handling for mbbi record, also fix bug in COSV and LALM handling. * Add release notes and update record docs.
This commit is contained in:
1 parent
631c8831b9
commit
c9817fa591
9 files changed
+371
-17
No files matched your search
@@ -0,0 +1,13 @@
|
||||
### AFTC for bi record
|
||||
|
||||
The bi record now also supports the AFTC parameter.
|
||||
The AFTC field sets the time constant on a low-pass filter that delays the
|
||||
reporting of limit alarms until the signal has been within the alarm range for
|
||||
that number of seconds (the default AFTC value of zero retains the previous
|
||||
behavior). One has to make sure that the bi record is processed at a reasonably fast rate
|
||||
when using AFTC, so that the record can respond to changes in the input signal
|
||||
within the time constant.
|
||||
|
||||
### AFTC and LALM fix for mbbi record
|
||||
|
||||
Fixed two issues in the mbbi record where the AFTC and LALM fields were not operating as expected.
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "epicsMath.h"
|
||||
#include "alarm.h"
|
||||
#include "callback.h"
|
||||
#include "dbAccess.h"
|
||||
@@ -40,6 +41,9 @@
|
||||
#undef GEN_SIZE_OFFSET
|
||||
#include "epicsExport.h"
|
||||
|
||||
/* Hysteresis for alarm filtering: 1-1/e */
|
||||
#define THRESHOLD 0.6321
|
||||
|
||||
/* Create RSET - Record Support Entry Table*/
|
||||
#define report NULL
|
||||
#define initialize NULL
|
||||
@@ -80,7 +84,7 @@ rset biRSET={
|
||||
};
|
||||
epicsExportAddress(rset,biRSET);
|
||||
|
||||
static void checkAlarms(biRecord *);
|
||||
static void checkAlarms(biRecord *, epicsTimeStamp *);
|
||||
static void monitor(biRecord *);
|
||||
static long readValue(biRecord *);
|
||||
|
||||
@@ -119,6 +123,7 @@ static long process(struct dbCommon *pcommon)
|
||||
bidset *pdset = (bidset *)(prec->dset);
|
||||
long status;
|
||||
unsigned char pact=prec->pact;
|
||||
epicsTimeStamp timeLast;
|
||||
|
||||
if( (pdset==NULL) || (pdset->read_bi==NULL) ) {
|
||||
prec->pact=TRUE;
|
||||
@@ -126,6 +131,8 @@ static long process(struct dbCommon *pcommon)
|
||||
return(S_dev_missingSup);
|
||||
}
|
||||
|
||||
timeLast = prec->time;
|
||||
|
||||
status=readValue(prec); /* read the new value */
|
||||
/* check if device support set pact */
|
||||
if ( !pact && prec->pact ) return(0);
|
||||
@@ -140,7 +147,7 @@ static long process(struct dbCommon *pcommon)
|
||||
}
|
||||
else if(status==2) status=0;
|
||||
/* check for alarms */
|
||||
checkAlarms(prec);
|
||||
checkAlarms(prec, &timeLast);
|
||||
/* check event list */
|
||||
monitor(prec);
|
||||
/* process the forward scan link record */
|
||||
@@ -217,27 +224,52 @@ static long put_enum_str(const DBADDR *paddr, const char *pstring)
|
||||
}
|
||||
|
||||
|
||||
static void checkAlarms(biRecord *prec)
|
||||
static void checkAlarms(biRecord *prec, epicsTimeStamp *timeLast)
|
||||
{
|
||||
epicsEnum16 asev;
|
||||
unsigned short val = prec->val;
|
||||
|
||||
|
||||
if(prec->udf == TRUE){
|
||||
recGblSetSevr(prec,UDF_ALARM,prec->udfs);
|
||||
return;
|
||||
}
|
||||
|
||||
if(val>1)return;
|
||||
/* check for state alarm */
|
||||
if (val == 0){
|
||||
recGblSetSevr(prec,STATE_ALARM,prec->zsv);
|
||||
}else{
|
||||
recGblSetSevr(prec,STATE_ALARM,prec->osv);
|
||||
|
||||
if (val == 0) {
|
||||
asev = prec->zsv;
|
||||
} else {
|
||||
asev = prec->osv;
|
||||
}
|
||||
|
||||
/* check for cos alarm */
|
||||
unsigned short alarm = asev; /* Initialize alarm with current state severity */
|
||||
double aftc = prec->aftc;
|
||||
double afvl = 0;
|
||||
|
||||
if (aftc > 0) {
|
||||
afvl = prec->afvl;
|
||||
if (afvl == 0) {
|
||||
afvl = (double) alarm;
|
||||
} else {
|
||||
double t = epicsTimeDiffInSeconds(&prec->time, timeLast);
|
||||
double alpha = aftc / (t + aftc);
|
||||
|
||||
afvl = alpha * afvl +
|
||||
((afvl > 0) ? (1.0 - alpha) : (alpha - 1.0)) * alarm;
|
||||
if (afvl - floor(afvl) > THRESHOLD)
|
||||
afvl = -afvl;
|
||||
|
||||
alarm = abs((int)floor(afvl));
|
||||
}
|
||||
}
|
||||
prec->afvl = afvl;
|
||||
|
||||
asev = alarm;
|
||||
recGblSetSevr(prec,STATE_ALARM,asev);
|
||||
|
||||
/* check for cos alarm */
|
||||
if(val == prec->lalm) return;
|
||||
recGblSetSevr(prec,COS_ALARM,prec->cosv);
|
||||
recGblSetSevr(prec,COS_ALARM,prec->cosv);
|
||||
prec->lalm = val;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,13 +107,20 @@ C<MAJOR>. The ZSV field holds the severity for the zero state; OSV, for
|
||||
the one state. COSV causes an alarm whenever the state changes between
|
||||
0 and 1 and the severity is configured as MINOR or MAJOR.
|
||||
|
||||
Since UNRELEASED, the alarm filter time constant (AFTC) is available for the bi record.
|
||||
The AFTC field sets the time constant on a low-pass filter that delays the
|
||||
reporting of limit alarms until the signal has been within the alarm range for
|
||||
that number of seconds (the default AFTC value of zero retains the previous
|
||||
behavior). Be sure that the bi record is processed at a reasonably fast rate
|
||||
when using AFTC, so that the record can respond to changes in the input signal
|
||||
within the time constant.
|
||||
|
||||
See L<Alarm Specification|https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#alarm-specification>
|
||||
for a complete explanation of record alarms and of the standard fields.
|
||||
L<Alarm Fields|dbCommonRecord/Alarm Fields> lists other fields related
|
||||
to alarms that are common to all record types.
|
||||
|
||||
=fields ZSV, OSV, COSV
|
||||
|
||||
=fields ZSV, OSV, COSV, AFTC
|
||||
=head3 Run-time Parameters
|
||||
|
||||
These parameters are used by the run-time code for processing the binary
|
||||
@@ -220,6 +227,16 @@ is not equal to VAL.
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
field(AFTC, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Time Constant")
|
||||
promptgroup("70 - Alarm")
|
||||
interest(1)
|
||||
}
|
||||
field(AFVL, DBF_DOUBLE) {
|
||||
prompt("Alarm Filter Value")
|
||||
special(SPC_NOMOD)
|
||||
interest(3)
|
||||
}
|
||||
|
||||
=head3 Simulation Mode Parameters
|
||||
|
||||
|
||||
@@ -336,15 +336,15 @@ static void checkAlarms(mbbiRecord *prec, epicsTimeStamp *timeLast)
|
||||
alarm = abs((int)floor(afvl));
|
||||
}
|
||||
}
|
||||
prec->afvl = afvl;
|
||||
|
||||
asev = alarm;
|
||||
recGblSetSevr(prec, STATE_ALARM, asev);
|
||||
|
||||
/* Check for COS alarm */
|
||||
if (val == prec->lalm ||
|
||||
recGblSetSevr(prec, COS_ALARM, prec->cosv))
|
||||
if (val == prec->lalm)
|
||||
return;
|
||||
|
||||
recGblSetSevr(prec, COS_ALARM, prec->cosv);
|
||||
prec->lalm = val;
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +195,13 @@ testHarness_SRCS += simmTest_registerRecordDeviceDriver.cpp
|
||||
TESTFILES += $(COMMON_DIR)/simmTest.dbd $(COMMON_DIR)/simmTest.db
|
||||
TESTS += simmTest
|
||||
|
||||
TESTPROD_HOST += mbbiTest
|
||||
mbbiTest_SRCS += mbbiTest.c
|
||||
mbbiTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp
|
||||
testHarness_SRCS += mbbiTest.c
|
||||
TESTFILES += ../mbbiTest.db
|
||||
TESTS += mbbiTest
|
||||
|
||||
TESTPROD_HOST += mbbioDirectTest
|
||||
mbbioDirectTest_SRCS += mbbioDirectTest.c
|
||||
mbbioDirectTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "errlog.h"
|
||||
#include "dbAccess.h"
|
||||
#include "menuAlarmSevr.h"
|
||||
#include "menuScan.h"
|
||||
|
||||
void recTestIoc_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
@@ -96,9 +97,71 @@ static void test_alarm(void){
|
||||
// number of tests = 13
|
||||
}
|
||||
|
||||
static void test_aftc(void){
|
||||
const double aftc = 3.0;
|
||||
testMonitor* test_mon = NULL;
|
||||
epicsTimeStamp startTime;
|
||||
epicsTimeStamp endTime;
|
||||
double diffTime = 0;
|
||||
|
||||
/* set soft channel */
|
||||
testdbPutFieldOk("test_bi_rec2.DTYP", DBF_STRING, "Soft Channel");
|
||||
testdbPutFieldOk("test_bi_rec2.INP", DBF_STRING, "test_bi_link_rec2.VAL");
|
||||
testdbPutFieldOk("test_bi_link_rec2.FLNK", DBF_STRING, "test_bi_rec2");
|
||||
|
||||
/* set alarm parameters */
|
||||
testdbPutFieldOk("test_bi_rec2.ZSV", DBF_SHORT, menuAlarmSevrMINOR);
|
||||
testdbPutFieldOk("test_bi_rec2.OSV", DBF_SHORT, menuAlarmSevrMAJOR);
|
||||
|
||||
/* set start VAL to FALSE (NO_ALARM) */
|
||||
testdbPutFieldOk("test_bi_link_rec2.VAL", DBF_SHORT, FALSE);
|
||||
|
||||
/* test AFTC using a monitor and time stamps */
|
||||
testdbPutFieldOk("test_bi_rec2.AFTC", DBF_DOUBLE, aftc);
|
||||
testdbPutFieldOk("test_bi_rec2.SCAN", DBF_SHORT, menuScan_1_second);
|
||||
|
||||
/* set VAL to TRUE (MAJOR alarm) */
|
||||
testdbPutFieldOk("test_bi_link_rec2.VAL", DBF_SHORT, TRUE);
|
||||
|
||||
/* Create test monitor for alarm SEVR */
|
||||
test_mon = testMonitorCreate("test_bi_rec2.VAL", DBE_ALARM, 0);
|
||||
|
||||
/* Get start time */
|
||||
epicsTimeGetCurrent(&startTime);
|
||||
|
||||
/* wait for monitor to trigger on the new alarm status */
|
||||
testMonitorWait(test_mon);
|
||||
epicsTimeGetCurrent(&endTime);
|
||||
|
||||
/* Verify that alarm status is now MAJOR */
|
||||
testdbGetFieldEqual("test_bi_rec2.SEVR", DBF_SHORT, menuAlarmSevrMAJOR);
|
||||
|
||||
/* set VAL back to FALSE (NO_ALARM) */
|
||||
testdbPutFieldOk("test_bi_link_rec2.VAL", DBF_SHORT, FALSE);
|
||||
|
||||
/* Create test monitor for alarm SEVR */
|
||||
test_mon = testMonitorCreate("test_bi_rec2.VAL", DBE_ALARM, 0);
|
||||
|
||||
/* Get start time */
|
||||
epicsTimeGetCurrent(&startTime);
|
||||
|
||||
/* wait for monitor to trigger on the new alarm status */
|
||||
testMonitorWait(test_mon);
|
||||
epicsTimeGetCurrent(&endTime);
|
||||
|
||||
/* Verify that alarm status is now NO_ALARM */
|
||||
testdbGetFieldEqual("test_bi_rec2.SEVR", DBF_SHORT, menuAlarmSevrMINOR);
|
||||
|
||||
/* Verify that time is at least equal to configured aftc */
|
||||
diffTime = epicsTimeDiffInSeconds(&endTime, &startTime);
|
||||
testOk(diffTime >= aftc, "AFTC time %lf", diffTime);
|
||||
|
||||
// number of tests = 13
|
||||
}
|
||||
|
||||
MAIN(biTest) {
|
||||
|
||||
testPlan(6+6+11+13);
|
||||
testPlan(6+6+11+13+13);
|
||||
|
||||
testdbPrepare();
|
||||
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
|
||||
@@ -114,6 +177,7 @@ MAIN(biTest) {
|
||||
test_raw_soft_input();
|
||||
test_operator_display();
|
||||
test_alarm();
|
||||
test_aftc();
|
||||
|
||||
testIocShutdownOk();
|
||||
testdbCleanup();
|
||||
|
||||
@@ -4,3 +4,10 @@ record(bi, "test_bi_rec") {
|
||||
record(bo, "test_bi_link_rec") {
|
||||
|
||||
}
|
||||
|
||||
record(bi, "test_bi_rec2") {
|
||||
}
|
||||
|
||||
record(bo, "test_bi_link_rec2") {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2026 Edmund Blomley
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include "dbUnitTest.h"
|
||||
#include "testMain.h"
|
||||
#include "errlog.h"
|
||||
#include "dbAccess.h"
|
||||
#include "menuAlarmSevr.h"
|
||||
#include "menuScan.h"
|
||||
|
||||
void recTestIoc_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
static void test_soft_input(void){
|
||||
/* set soft channel */
|
||||
testdbPutFieldOk("test_mbbi_rec.DTYP", DBF_STRING, "Soft Channel");
|
||||
testdbPutFieldOk("test_mbbi_rec.INP", DBF_STRING, "test_mbbi_link_rec.VAL");
|
||||
testdbPutFieldOk("test_mbbi_link_rec.FLNK", DBF_STRING, "test_mbbi_rec");
|
||||
|
||||
/* set VAL to on linked record */
|
||||
testdbPutFieldOk("test_mbbi_link_rec.VAL", DBF_SHORT, 1);
|
||||
|
||||
/* verify that this record VAL is updated but RVAL is not */
|
||||
testdbGetFieldEqual("test_mbbi_rec.VAL", DBF_SHORT, 1);
|
||||
testdbGetFieldEqual("test_mbbi_rec.RVAL", DBF_SHORT, 0);
|
||||
|
||||
// number of tests = 6
|
||||
}
|
||||
|
||||
static void test_operator_display(void){
|
||||
/* set operator display parameters */
|
||||
testdbPutFieldOk("test_mbbi_rec.ZRST", DBF_STRING, "ZRST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.ONST", DBF_STRING, "ONST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.TWST", DBF_STRING, "TWST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.THST", DBF_STRING, "THST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.FRST", DBF_STRING, "FRST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.FVST", DBF_STRING, "FVST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.SXST", DBF_STRING, "SXST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.SVST", DBF_STRING, "SVST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.EIST", DBF_STRING, "EIST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.NIST", DBF_STRING, "NIST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.TEST", DBF_STRING, "TEST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.ELST", DBF_STRING, "ELST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.TVST", DBF_STRING, "TVST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.TTST", DBF_STRING, "TTST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.FTST", DBF_STRING, "FTST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.FFST", DBF_STRING, "FFST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.DESC", DBF_STRING, "DESC_TEST");
|
||||
|
||||
/* verify operator display parameters */
|
||||
testdbGetFieldEqual("test_mbbi_rec.ZRST", DBF_STRING, "ZRST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.ONST", DBF_STRING, "ONST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.TWST", DBF_STRING, "TWST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.THST", DBF_STRING, "THST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.FRST", DBF_STRING, "FRST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.FVST", DBF_STRING, "FVST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.SXST", DBF_STRING, "SXST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.SVST", DBF_STRING, "SVST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.EIST", DBF_STRING, "EIST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.NIST", DBF_STRING, "NIST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.TEST", DBF_STRING, "TEST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.ELST", DBF_STRING, "ELST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.TVST", DBF_STRING, "TVST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.TTST", DBF_STRING, "TTST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.FTST", DBF_STRING, "FTST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.FFST", DBF_STRING, "FFST_TEST");
|
||||
testdbGetFieldEqual("test_mbbi_rec.NAME", DBF_STRING, "test_mbbi_rec");
|
||||
testdbGetFieldEqual("test_mbbi_rec.DESC", DBF_STRING, "DESC_TEST");
|
||||
|
||||
/* verify conversion */
|
||||
testdbPutFieldOk("test_mbbi_link_rec.VAL", DBF_SHORT, 1);
|
||||
testdbGetFieldEqual("test_mbbi_rec.VAL", DBF_STRING, "ONST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_link_rec.VAL", DBF_SHORT, 0);
|
||||
testdbGetFieldEqual("test_mbbi_rec.VAL", DBF_STRING, "ZRST_TEST");
|
||||
|
||||
// number of tests = 39
|
||||
}
|
||||
|
||||
static void test_alarm(void){
|
||||
/* set soft channel */
|
||||
testdbPutFieldOk("test_mbbi_rec.DTYP", DBF_STRING, "Soft Channel");
|
||||
testdbPutFieldOk("test_mbbi_rec.INP", DBF_STRING, "test_mbbi_link_rec.VAL");
|
||||
testdbPutFieldOk("test_mbbi_link_rec.FLNK", DBF_STRING, "test_mbbi_rec");
|
||||
testdbPutFieldOk("test_mbbi_rec.ZRST", DBF_STRING, "ZRST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.ONST", DBF_STRING, "ONST_TEST");
|
||||
testdbPutFieldOk("test_mbbi_rec.ZRVL", DBF_STRING, "0");
|
||||
testdbPutFieldOk("test_mbbi_rec.ONVL", DBF_STRING, "1");
|
||||
|
||||
/* set start VAL to 0*/
|
||||
testdbPutFieldOk("test_mbbi_link_rec.VAL", DBF_SHORT, 0);
|
||||
|
||||
/* set alarm parameters */
|
||||
testdbPutFieldOk("test_mbbi_rec.ZRSV", DBF_SHORT, menuAlarmSevrNO_ALARM);
|
||||
testdbPutFieldOk("test_mbbi_rec.ONSV", DBF_SHORT, menuAlarmSevrMINOR);
|
||||
testdbPutFieldOk("test_mbbi_rec.COSV", DBF_SHORT, menuAlarmSevrINVALID);
|
||||
|
||||
/* verify alarm status is NO_ALARM*/
|
||||
testdbGetFieldEqual("test_mbbi_rec.SEVR", DBF_SHORT, menuAlarmSevrNO_ALARM);
|
||||
|
||||
/* set ZRSV to MAJOR and verify that SEVR is now MAJOR */
|
||||
testdbPutFieldOk("test_mbbi_rec.ZRSV", DBF_SHORT, menuAlarmSevrMAJOR);
|
||||
testdbGetFieldEqual("test_mbbi_rec.SEVR", DBF_SHORT, menuAlarmSevrMAJOR);
|
||||
|
||||
/* set VAL to 1 on linked record and verify that COSV now sets the SEVR to INVALID */
|
||||
testdbPutFieldOk("test_mbbi_link_rec.VAL", DBF_SHORT, 1);
|
||||
testdbGetFieldEqual("test_mbbi_rec.SEVR", DBF_SHORT, menuAlarmSevrINVALID);
|
||||
|
||||
/* verify LAML */
|
||||
testdbGetFieldEqual("test_mbbi_rec.LALM", DBF_SHORT, 1);
|
||||
|
||||
// number of tests = 17
|
||||
}
|
||||
|
||||
static void test_aftc(void){
|
||||
const double aftc = 3.0;
|
||||
testMonitor* test_mon = NULL;
|
||||
epicsTimeStamp startTime;
|
||||
epicsTimeStamp endTime;
|
||||
double diffTime = 0;
|
||||
|
||||
/* set soft channel */
|
||||
testdbPutFieldOk("test_mbbi_rec2.DTYP", DBF_STRING, "Soft Channel");
|
||||
testdbPutFieldOk("test_mbbi_rec2.INP", DBF_STRING, "test_mbbi_link_rec2.VAL");
|
||||
testdbPutFieldOk("test_mbbi_link_rec2.FLNK", DBF_STRING, "test_mbbi_rec2");
|
||||
|
||||
/* set alarm parameters */
|
||||
testdbPutFieldOk("test_mbbi_rec2.ZRSV", DBF_SHORT, menuAlarmSevrMINOR);
|
||||
testdbPutFieldOk("test_mbbi_rec2.ONSV", DBF_SHORT, menuAlarmSevrMAJOR);
|
||||
|
||||
/* set start VAL to FALSE (NO_ALARM) */
|
||||
testdbPutFieldOk("test_mbbi_link_rec2.VAL", DBF_SHORT, FALSE);
|
||||
|
||||
/* test AFTC using a monitor and time stamps */
|
||||
testdbPutFieldOk("test_mbbi_rec2.AFTC", DBF_DOUBLE, aftc);
|
||||
testdbPutFieldOk("test_mbbi_rec2.SCAN", DBF_SHORT, menuScan_1_second);
|
||||
|
||||
/* set VAL to TRUE (MAJOR alarm) */
|
||||
testdbPutFieldOk("test_mbbi_link_rec2.VAL", DBF_SHORT, TRUE);
|
||||
|
||||
/* Create test monitor for alarm SEVR */
|
||||
test_mon = testMonitorCreate("test_mbbi_rec2.VAL", DBE_ALARM, 0);
|
||||
|
||||
/* Get start time */
|
||||
epicsTimeGetCurrent(&startTime);
|
||||
|
||||
/* wait for monitor to trigger on the new alarm status */
|
||||
testMonitorWait(test_mon);
|
||||
epicsTimeGetCurrent(&endTime);
|
||||
|
||||
/* Verify that alarm status is now MAJOR */
|
||||
testdbGetFieldEqual("test_mbbi_rec2.SEVR", DBF_SHORT, menuAlarmSevrMAJOR);
|
||||
|
||||
/* set VAL back to FALSE (NO_ALARM) */
|
||||
testdbPutFieldOk("test_mbbi_link_rec2.VAL", DBF_SHORT, FALSE);
|
||||
|
||||
/* Create test monitor for alarm SEVR */
|
||||
test_mon = testMonitorCreate("test_mbbi_rec2.VAL", DBE_ALARM, 0);
|
||||
|
||||
/* Get start time */
|
||||
epicsTimeGetCurrent(&startTime);
|
||||
|
||||
/* wait for monitor to trigger on the new alarm status */
|
||||
testMonitorWait(test_mon);
|
||||
epicsTimeGetCurrent(&endTime);
|
||||
|
||||
/* Verify that alarm status is now NO_ALARM */
|
||||
testdbGetFieldEqual("test_mbbi_rec2.SEVR", DBF_SHORT, menuAlarmSevrMINOR);
|
||||
|
||||
/* Verify that time is at least equal to configured aftc */
|
||||
diffTime = epicsTimeDiffInSeconds(&endTime, &startTime);
|
||||
testOk(diffTime >= aftc, "AFTC time %lf", diffTime);
|
||||
|
||||
// number of tests = 13
|
||||
}
|
||||
|
||||
MAIN(mbbiTest) {
|
||||
|
||||
testPlan(6+39+17+13);
|
||||
|
||||
testdbPrepare();
|
||||
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
|
||||
recTestIoc_registerRecordDeviceDriver(pdbbase);
|
||||
|
||||
testdbReadDatabase("mbbiTest.db", NULL, NULL);
|
||||
|
||||
eltc(0);
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
|
||||
test_soft_input();
|
||||
test_operator_display();
|
||||
test_alarm();
|
||||
test_aftc();
|
||||
|
||||
testIocShutdownOk();
|
||||
testdbCleanup();
|
||||
|
||||
return testDone();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
record(mbbi, "test_mbbi_rec") {
|
||||
}
|
||||
|
||||
record(longout, "test_mbbi_link_rec") {
|
||||
|
||||
}
|
||||
|
||||
record(mbbi, "test_mbbi_rec2") {
|
||||
}
|
||||
|
||||
record(longout, "test_mbbi_link_rec2") {
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user