Merge branch 'epics-base:7.0' into add-simm-to-ao-records
This commit is contained in:
@@ -63,7 +63,7 @@ static long read_lsi(lsiRecord *prec)
|
||||
prec->val[0] = 0;
|
||||
prec->len = 1;
|
||||
prec->udf = TRUE;
|
||||
recGblSetSevr(prec, UDF_ALARM, prec->udfs);
|
||||
recGblSetSevrMsg(prec, UDF_ALARM, prec->udfs, "No such ENV");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -114,7 +114,7 @@ static long read_stringin(stringinRecord *prec)
|
||||
else {
|
||||
prec->val[0] = 0;
|
||||
prec->udf = TRUE;
|
||||
recGblSetSevr(prec, UDF_ALARM, prec->udfs);
|
||||
recGblSetSevrMsg(prec, UDF_ALARM, prec->udfs, "No such ENV");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -16,6 +16,7 @@ dbRecStd_SRCS += dbnd.c
|
||||
dbRecStd_SRCS += arr.c
|
||||
dbRecStd_SRCS += sync.c
|
||||
dbRecStd_SRCS += decimate.c
|
||||
dbRecStd_SRCS += utag.c
|
||||
|
||||
HTMLS += filters.html
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ The following filters are available in this release:
|
||||
|
||||
=item * L<Decimation|/"Decimation Filter dec">
|
||||
|
||||
=item * L<UTag|/"UTag Filter utag">
|
||||
|
||||
=back
|
||||
|
||||
=head2 Using Filters
|
||||
@@ -285,3 +287,26 @@ once every minute:
|
||||
...
|
||||
|
||||
=cut
|
||||
|
||||
registrar(utagInitialize)
|
||||
|
||||
=head3 UTag Filter C<"utag">
|
||||
|
||||
This filter applies a test UTAG&M==V to the value taken from the UTAG record field
|
||||
and drops those updates which evaluate as false.
|
||||
|
||||
=head4 Parameters
|
||||
|
||||
=over
|
||||
|
||||
=item Mask C<"M">
|
||||
|
||||
Bit mask.
|
||||
|
||||
=item Value C<"V">
|
||||
|
||||
Required value.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
99
modules/database/src/std/filters/utag.c
Normal file
99
modules/database/src/std/filters/utag.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2020 Michael Davidsaver
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <caeventmask.h>
|
||||
#include <chfPlugin.h>
|
||||
#include <dbCommon.h>
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsExport.h>
|
||||
|
||||
typedef struct {
|
||||
epicsInt32 mask, value;
|
||||
int first;
|
||||
} utagPvt;
|
||||
|
||||
static const
|
||||
chfPluginArgDef opts[] = {
|
||||
chfInt32(utagPvt, mask, "M", 0, 1),
|
||||
chfInt32(utagPvt, value, "V", 0, 1),
|
||||
chfPluginArgEnd
|
||||
};
|
||||
|
||||
static void * allocPvt(void)
|
||||
{
|
||||
utagPvt *pvt;
|
||||
pvt = calloc(1, sizeof(utagPvt));
|
||||
pvt->mask = 0xffffffff;
|
||||
return pvt;
|
||||
}
|
||||
|
||||
static void freePvt(void *pvt)
|
||||
{
|
||||
free(pvt);
|
||||
}
|
||||
|
||||
static int parse_ok(void *raw)
|
||||
{
|
||||
utagPvt *pvt = (utagPvt*)raw;
|
||||
pvt->first = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static db_field_log* filter(void* raw, dbChannel *chan, db_field_log *pfl)
|
||||
{
|
||||
utagPvt *pvt = (utagPvt*)raw;
|
||||
epicsUTag utag = pfl->utag;
|
||||
int drop = (utag&pvt->mask)!=pvt->value;
|
||||
|
||||
if(pfl->ctx!=dbfl_context_event || pfl->mask&DBE_PROPERTY) {
|
||||
/* never drop for reads, or property events */
|
||||
|
||||
} else if(pvt->first) {
|
||||
/* never drop first */
|
||||
pvt->first = 0;
|
||||
|
||||
} else if(drop) {
|
||||
db_delete_field_log(pfl);
|
||||
pfl = NULL;
|
||||
}
|
||||
|
||||
return pfl;
|
||||
}
|
||||
|
||||
static void channelRegisterPre(dbChannel *chan, void *pvt,
|
||||
chPostEventFunc **cb_out, void **arg_out, db_field_log *probe)
|
||||
{
|
||||
*cb_out = filter;
|
||||
*arg_out = pvt;
|
||||
}
|
||||
|
||||
static void channel_report(dbChannel *chan, void *raw, int level, const unsigned short indent)
|
||||
{
|
||||
utagPvt *pvt = (utagPvt*)raw;
|
||||
printf("%*sutag : mask=0x%08x value=0x%08x\n", indent, "", (epicsUInt32)pvt->mask, (epicsUInt32)pvt->value);
|
||||
}
|
||||
|
||||
static const
|
||||
chfPluginIf pif = {
|
||||
allocPvt,
|
||||
freePvt,
|
||||
NULL, /* parse_error */
|
||||
parse_ok, /* parse_ok */
|
||||
NULL, /* channel_open */
|
||||
channelRegisterPre,
|
||||
NULL, /* channelRegisterPost */
|
||||
channel_report,
|
||||
NULL, /* channel_close */
|
||||
};
|
||||
|
||||
static
|
||||
void utagInitialize(void)
|
||||
{
|
||||
chfPluginRegister("utag", &pif, opts);
|
||||
}
|
||||
epicsExportRegistrar(utagInitialize);
|
||||
@@ -53,6 +53,7 @@ typedef struct calc_link {
|
||||
} pstate;
|
||||
epicsEnum16 stat;
|
||||
epicsEnum16 sevr;
|
||||
char amsg[DB_AMSG_SIZE];
|
||||
short prec;
|
||||
char *expr;
|
||||
char *major;
|
||||
@@ -66,6 +67,7 @@ typedef struct calc_link {
|
||||
struct link out;
|
||||
double arg[CALCPERFORM_NARGS];
|
||||
epicsTimeStamp time;
|
||||
epicsUTag utag;
|
||||
double val;
|
||||
} calc_link;
|
||||
|
||||
@@ -385,9 +387,10 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent)
|
||||
|
||||
if (level > 0) {
|
||||
if (clink->sevr)
|
||||
printf("%*s Alarm: %s, %s\n", indent, "",
|
||||
printf("%*s Alarm: %s, %s, \"%s\"\n", indent, "",
|
||||
epicsAlarmSeverityStrings[clink->sevr],
|
||||
epicsAlarmConditionStrings[clink->stat]);
|
||||
epicsAlarmConditionStrings[clink->stat],
|
||||
clink->amsg);
|
||||
|
||||
if (clink->post_major)
|
||||
printf("%*s Major expression: \"%s\"\n", indent, "",
|
||||
@@ -532,6 +535,7 @@ static long lnkCalc_getElements(const struct link *plink, long *nelements)
|
||||
struct lcvt {
|
||||
double *pval;
|
||||
epicsTimeStamp *ptime;
|
||||
epicsUTag *ptag;
|
||||
};
|
||||
|
||||
static long readLocked(struct link *pinp, void *vvt)
|
||||
@@ -541,7 +545,7 @@ static long readLocked(struct link *pinp, void *vvt)
|
||||
long status = dbGetLink(pinp, DBR_DOUBLE, pvt->pval, NULL, &nReq);
|
||||
|
||||
if (!status && pvt->ptime)
|
||||
dbGetTimeStamp(pinp, pvt->ptime);
|
||||
dbGetTimeStampTag(pinp, pvt->ptime, pvt->ptag);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -567,7 +571,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
long nReq = 1;
|
||||
|
||||
if (i == clink->tinp) {
|
||||
struct lcvt vt = {&clink->arg[i], &clink->time};
|
||||
struct lcvt vt = {&clink->arg[i], &clink->time, &clink->utag};
|
||||
|
||||
status = dbLinkDoLocked(child, readLocked, &vt);
|
||||
if (status == S_db_noLSET)
|
||||
@@ -576,6 +580,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
if (dbLinkIsConstant(&prec->tsel) &&
|
||||
prec->tse == epicsTimeEventDeviceTime) {
|
||||
prec->time = clink->time;
|
||||
prec->utag = clink->utag;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -583,6 +588,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
}
|
||||
clink->stat = 0;
|
||||
clink->sevr = 0;
|
||||
clink->amsg[0] = '\0';
|
||||
|
||||
if (clink->post_expr) {
|
||||
status = calcPerform(clink->arg, &clink->val, clink->post_expr);
|
||||
@@ -604,7 +610,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
if (!status && alval) {
|
||||
clink->stat = LINK_ALARM;
|
||||
clink->sevr = MAJOR_ALARM;
|
||||
recGblSetSevr(prec, clink->stat, clink->sevr);
|
||||
strcpy(clink->amsg, "post_major error");
|
||||
recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,7 +622,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
if (!status && alval) {
|
||||
clink->stat = LINK_ALARM;
|
||||
clink->sevr = MINOR_ALARM;
|
||||
recGblSetSevr(prec, clink->stat, clink->sevr);
|
||||
strcpy(clink->amsg, "post_minor error");
|
||||
recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,7 +651,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
|
||||
long nReq = 1;
|
||||
|
||||
if (i == clink->tinp) {
|
||||
struct lcvt vt = {&clink->arg[i], &clink->time};
|
||||
struct lcvt vt = {&clink->arg[i], &clink->time, &clink->utag};
|
||||
|
||||
status = dbLinkDoLocked(child, readLocked, &vt);
|
||||
if (status == S_db_noLSET)
|
||||
@@ -652,6 +660,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
|
||||
if (dbLinkIsConstant(&prec->tsel) &&
|
||||
prec->tse == epicsTimeEventDeviceTime) {
|
||||
prec->time = clink->time;
|
||||
prec->utag = clink->utag;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -659,6 +668,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
|
||||
}
|
||||
clink->stat = 0;
|
||||
clink->sevr = 0;
|
||||
clink->amsg[0] = '\0';
|
||||
|
||||
/* Get the value being output as VAL */
|
||||
status = conv(pbuffer, &clink->val, NULL);
|
||||
@@ -673,7 +683,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
|
||||
if (!status && alval) {
|
||||
clink->stat = LINK_ALARM;
|
||||
clink->sevr = MAJOR_ALARM;
|
||||
recGblSetSevr(prec, clink->stat, clink->sevr);
|
||||
strcpy(clink->amsg, "post_major error");
|
||||
recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,7 +695,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
|
||||
if (!status && alval) {
|
||||
clink->stat = LINK_ALARM;
|
||||
clink->sevr = MINOR_ALARM;
|
||||
recGblSetSevr(prec, clink->stat, clink->sevr);
|
||||
strcpy(clink->amsg, "post_major error");
|
||||
recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,8 +730,8 @@ static long lnkCalc_getUnits(const struct link *plink, char *units, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity)
|
||||
static long lnkCalc_getAlarmMsg(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity, char *msgbuf, size_t msgbuflen)
|
||||
{
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
@@ -728,17 +740,23 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
*status = clink->stat;
|
||||
if (severity)
|
||||
*severity = clink->sevr;
|
||||
if (msgbuf && msgbuflen) {
|
||||
strncpy(msgbuf, clink->amsg, msgbuflen-1);
|
||||
msgbuf[msgbuflen-1] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long lnkCalc_getTimestamp(const struct link *plink, epicsTimeStamp *pstamp)
|
||||
static long lnkCalc_getTimestampTag(const struct link *plink, epicsTimeStamp *pstamp, epicsUTag *ptag)
|
||||
{
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
if (clink->tinp >= 0) {
|
||||
*pstamp = clink->time;
|
||||
if(ptag)
|
||||
*ptag = clink->utag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -761,9 +779,11 @@ static lset lnkCalc_lset = {
|
||||
lnkCalc_getValue,
|
||||
NULL, NULL, NULL,
|
||||
lnkCalc_getPrecision, lnkCalc_getUnits,
|
||||
lnkCalc_getAlarm, lnkCalc_getTimestamp,
|
||||
NULL, NULL,
|
||||
lnkCalc_putValue, NULL,
|
||||
NULL, doLocked
|
||||
NULL, doLocked,
|
||||
lnkCalc_getAlarmMsg,
|
||||
lnkCalc_getTimestampTag,
|
||||
};
|
||||
|
||||
static jlif lnkCalcIf = {
|
||||
|
||||
@@ -432,7 +432,7 @@ static void convert(aiRecord *prec)
|
||||
|
||||
default: /* must use breakpoint table */
|
||||
if (cvtRawToEngBpt(&val,prec->linr,prec->init,(void *)&prec->pbrk,&prec->lbrk)!=0) {
|
||||
recGblSetSevr(prec,SOFT_ALARM,MAJOR_ALARM);
|
||||
recGblSetSevrMsg(prec,SOFT_ALARM,MAJOR_ALARM, "BPT Error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ static long process(struct dbCommon *pcommon)
|
||||
}
|
||||
if (fetch_values(prec) == 0) {
|
||||
if (calcPerform(&prec->a, &prec->val, prec->rpcl)) {
|
||||
recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM);
|
||||
recGblSetSevrMsg(prec, CALC_ALARM, INVALID_ALARM, "calcPerform");
|
||||
} else {
|
||||
prec->udf = isnan(prec->val);
|
||||
}
|
||||
@@ -610,7 +610,7 @@ static void execOutput(calcoutRecord *prec)
|
||||
break;
|
||||
case calcoutDOPT_Use_OVAL:
|
||||
if (calcPerform(&prec->a, &prec->oval, prec->orpc)) {
|
||||
recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM);
|
||||
recGblSetSevrMsg(prec, CALC_ALARM, INVALID_ALARM, "OCAL calcPerform");
|
||||
} else {
|
||||
prec->udf = isnan(prec->oval);
|
||||
}
|
||||
@@ -770,7 +770,7 @@ static long writeValue(calcoutRecord *prec)
|
||||
|
||||
if (!pcalcoutDSET || !pcalcoutDSET->write) {
|
||||
errlogPrintf("%s DSET write does not exist\n", prec->name);
|
||||
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
|
||||
recGblSetSevrMsg(prec, SOFT_ALARM, INVALID_ALARM, "DSET write does not exist");
|
||||
prec->pact = TRUE;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,5 @@ softIoc_LIBS = $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
DB += softIocExit.db
|
||||
|
||||
FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION))
|
||||
|
||||
CLEANS += epicsInstallDir.h
|
||||
|
||||
|
||||
@@ -249,7 +249,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
} else {
|
||||
if (loadedDb || ranScript) {
|
||||
epicsThreadExitMain();
|
||||
// non-interactive IOC. spin forever
|
||||
while(true) {
|
||||
epicsThreadSleep(1000.0);
|
||||
}
|
||||
|
||||
} else {
|
||||
usage(argv[0], dbd_file);
|
||||
|
||||
Reference in New Issue
Block a user