Add deadband plugin (client defined monitor deadband)

This commit is contained in:
Michael Davidsaver
2012-04-27 13:22:01 -04:00
parent b843a8990a
commit 0cfe224f47
3 changed files with 143 additions and 0 deletions

View File

@@ -85,4 +85,5 @@ dbCore_SRCS += dbIocRegister.c
dbCore_SRCS += chfPlugin.c
LIB_SRCS += ts.c
LIB_SRCS += dbnd.c

141
src/ioc/db/filters/dbnd.c Normal file
View File

@@ -0,0 +1,141 @@
/*************************************************************************\
* Copyright (c) 2010 Brookhaven National Laboratory.
* Copyright (c) 2010 Helmholtz-Zentrum Berlin
* fuer Materialien und Energie GmbH.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Ralph Lange <Ralph.Lange@bessy.de>
*/
#include <stdio.h>
#include <epicsExport.h>
#include <epicsMath.h>
#include <freeList.h>
#include <dbConvertFast.h>
#include <chfPlugin.h>
#include <db_field_log.h>
typedef struct myStruct {
int mode;
double cval;
double hyst;
double last;
} myStruct;
static void *myStructFreeList;
static const
chfPluginEnumType modeEnum[] = { {"abs", 0}, {"rel", 1}, {NULL,0} };
static const
chfPluginArgDef opts[] = {
chfDouble (myStruct, cval, "d", 0, 1),
chfEnum (myStruct, mode, "m", 0, 1, modeEnum),
chfPluginArgEnd
};
void * allocPvt(void)
{
return freeListCalloc(myStructFreeList);
}
void freePvt(void *pvt)
{
freeListFree(myStructFreeList, pvt);
}
int parse_ok(void *pvt)
{
myStruct *my = (myStruct*) pvt;
my->hyst = my->cval;
my->last = epicsNAN;
return 0;
}
static void shiftval (myStruct *my, double val) {
my->last = val;
if (my->mode == 1)
my->hyst = val * my->cval/100.;
}
static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl) {
myStruct *my = (myStruct*) pvt;
long status;
double val, delta;
short drop = 0;
/*
* Only scalar values supported - strings, arrays, and conversion errors
* are just passed on
*/
if (pfl->type == dbfl_type_val) {
DBADDR localAddr = chan->addr; /* Structure copy */
localAddr.field_type = pfl->field_type;
localAddr.field_size = pfl->field_size;
localAddr.no_elements = pfl->no_elements;
localAddr.pfield = (char *) &pfl->u.v.field;
status = dbFastGetConvertRoutine[pfl->field_type][DBR_DOUBLE]
(localAddr.pfield, (void*) &val, &localAddr);
if (!status) {
if (isnan(my->last)) {
shiftval(my, val);
} else {
delta = fabs(my->last - val);
if (delta <= my->hyst) {
drop = 1;
} else {
shiftval(my, val);
}
}
}
}
if (drop) return NULL;
else 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 *pvt, int level, const unsigned short indent)
{
myStruct *my = (myStruct*) pvt;
printf("%*s plugin dbnd, mode=%s, delta=%g%s\n", indent, "",
chfPluginEnumString(modeEnum, my->mode, "n/a"), my->cval,
my->mode == 1 ? "%" : "");
}
static chfPluginIf pif = {
allocPvt,
freePvt,
NULL, /* parse_error, */
parse_ok,
NULL, /* channel_open, */
channelRegisterPre,
NULL, /* channelRegisterPost, */
channel_report,
NULL /* channel_close */
};
static void dbndInitialize(void)
{
static int firstTime = 1;
if (!firstTime) return;
firstTime = 0;
if (!myStructFreeList)
freeListInitPvt(&myStructFreeList, sizeof(myStruct), 64);
chfPluginRegister("dbnd", &pif, opts);
}
epicsExportRegistrar(dbndInitialize);

View File

@@ -1 +1,2 @@
registrar(tsInitialize)
registrar(dbndInitialize)