add meta-data mappings

map:
* display.description to DESC
* display.format based on PREC
* valueAlarm.*Limit based on alarm limits

format is always empty if qsrvDisableFormat=1
which is the default as I worry that
clients will this printf() spec is unfortunate ways.
This commit is contained in:
Michael Davidsaver
2017-11-02 14:43:15 -05:00
parent f71d0a8d3c
commit c79f3624bd
3 changed files with 95 additions and 9 deletions

View File

@ -16,6 +16,16 @@ record(calc, "circle:angle") {
field(INPA, "circle:angle NPP")
field(INPB, "circle:step NPP")
field(INPD, "360")
field(DESC, "Angle")
field(EGU , "deg")
field(LOLO, "45")
field(LOW , "135")
field(HIGH, "225")
field(HIHI, "315")
field(LLSV, "MAJOR")
field(LSV , "MINOR")
field(HSV , "MINOR")
field(HHSV, "MAJOR")
field(CALC, "C:=A+B;(C>=D)?C-D:C")
field(FLNK, "circle:x")
field(PREC, "3")

View File

@ -21,6 +21,18 @@
#define epicsExportSharedSymbols
#include "pvif.h"
#include <epicsExport.h>
#ifdef EPICS_VERSION_INT
# if EPICS_VERSION_INT>=VERSION_INT(3,16,1,0)
# define USE_INT64
# endif
#endif
extern "C" {
int qsrvDisableFormat = 1;
}
namespace pvd = epics::pvData;
DBCH::DBCH(dbChannel *ch) :chan(ch)
@ -90,12 +102,10 @@ struct pvCommon : public pvTimeAlarm {
pvd::BitSet maskVALUE, maskPROPERTY, maskVALUEPut;
pvd::PVDoublePtr displayLow, displayHigh, controlLow, controlHigh;
pvd::PVStringPtr egu;
pvd::PVStringPtr egu, desc, prec;
pvd::PVScalarPtr warnLow, warnHigh, alarmLow, alarmHigh;
pvd::PVScalarPtr prec;
pvd::PVStringArrayPtr enumopts;
};
@ -184,11 +194,12 @@ void attachMeta(pvCommon& pvm, const pvd::PVStructurePtr& pv)
FMAP(controlHigh, PVDouble, "control.limitHigh", PROPERTY);
FMAP(controlLow, PVDouble, "control.limitLow", PROPERTY);
FMAP(egu, PVString, "display.units", PROPERTY);
//FMAP(prec, PVScalar, "display.format", PROPERTY);
FMAP(warnHigh, PVScalar, "alarm.highWarningLimit", PROPERTY);
FMAP(warnLow, PVScalar, "alarm.lowWarningLimit", PROPERTY);
FMAP(alarmHigh, PVScalar, "alarm.highAlarmLimit", PROPERTY);
FMAP(alarmLow, PVScalar, "alarm.lowAlarmLimit", PROPERTY);
FMAP(desc, PVString, "display.description", PROPERTY);
FMAP(prec, PVString, "display.format", PROPERTY);
FMAP(warnHigh, PVScalar, "valueAlarm.highWarningLimit", PROPERTY);
FMAP(warnLow, PVScalar, "valueAlarm.lowWarningLimit", PROPERTY);
FMAP(alarmHigh, PVScalar, "valueAlarm.highAlarmLimit", PROPERTY);
FMAP(alarmLow, PVScalar, "valueAlarm.lowAlarmLimit", PROPERTY);
FMAP(enumopts, PVStringArray, "value.choices", PROPERTY);
#undef FMAP
}
@ -406,6 +417,7 @@ void putMeta(const pvCommon& pv, unsigned dbe, db_field_log *pfl)
{
META meta;
long options = (int)META::mask, nReq = 0;
dbCommon *prec = dbChannelRecord(pv.chan);
long status = dbChannelGet(pv.chan, dbChannelFinalFieldType(pv.chan), &meta, &options, &nReq, pfl);
if(status)
@ -425,6 +437,7 @@ void putMeta(const pvCommon& pv, unsigned dbe, db_field_log *pfl)
}
if(dbe&DBE_PROPERTY) {
#undef FMAP
if(pv.desc) pv.desc->put(prec->desc);
#define FMAP(MASK, MNAME, FNAME) if(META::mask&(MASK) && pv.MNAME) pv.MNAME->put(meta.FNAME)
FMAP(DBR_GR_DOUBLE, displayHigh, upper_disp_limit);
FMAP(DBR_GR_DOUBLE, displayLow, lower_disp_limit);
@ -432,6 +445,58 @@ void putMeta(const pvCommon& pv, unsigned dbe, db_field_log *pfl)
FMAP(DBR_CTRL_DOUBLE, controlLow, lower_ctrl_limit);
FMAP(DBR_GR_DOUBLE, egu, units);
#undef FMAP
if(META::mask&DBR_PRECISION && pv.prec && !qsrvDisableFormat) {
// construct printf() style format.
// Widths based on epicsTypes.h
char buf[8];
char *pos = &buf[8]; // build string in reverse order
bool ok = true;
*--pos = '\0'; // buf[7] = '\0'
switch(dbChannelFinalFieldType(pv.chan)) {
#ifdef USE_INT64
case DBF_UINT64:
*--pos = 'l';
*--pos = 'l';
#endif
case DBF_UCHAR:
case DBF_USHORT:
case DBF_ULONG:
*--pos = 'u';
break;
#ifdef USE_INT64
case DBF_INT64:
*--pos = 'l';
*--pos = 'l';
#endif
case DBF_CHAR:
case DBF_SHORT:
case DBF_LONG:
*--pos = 'd';
break;
case DBF_DOUBLE:
case DBF_FLOAT:
*--pos = 'g'; // either decimal or scientific
break;
case DBF_STRING:
*--pos = 's';
break;
default:
ok = false;
}
if(ok) {
long dp = meta.precision.dp;
if(dp<0) dp = 0;
else if(dp>=99) dp = 99;
for(;dp;dp = dp/10u) {
*--pos = '0'+(dp%10u);
}
*--pos = '%';
}
pv.prec->put(pos);
}
#define FMAP(MASK, MNAME, FNAME) if(META::mask&(MASK) && pv.MNAME) pv.MNAME->putFrom(meta.FNAME)
// not handling precision until I get a better idea of what 'format' is supposed to be...
//FMAP(prec, PVScalar, "display.format", PROPERTY);
@ -612,7 +677,11 @@ ScalarBuilder::dtype(dbChannel *channel)
return pvd::getStandardField()->enumerated("alarm,timeStamp");
//TODO: ,valueAlarm for numeric
std::string options("alarm,timeStamp,display,control");
std::string options;
if(dbr!=DBR_STRING)
options = "alarm,timeStamp,display,control,valueAlarm";
else
options = "alarm,timeStamp,display,control";
if(maxelem==1)
return pvd::getStandardField()->scalar(pvt, options);
@ -1005,3 +1074,7 @@ PVIFBuilder* PVIFBuilder::create(const std::string& type)
else
throw std::runtime_error(std::string("Unknown +type=")+type);
}
extern "C" {
epicsExportAddress(int, qsrvDisableFormat);
}

View File

@ -6,3 +6,6 @@ registrar(QSRVRegistrar)
device(waveform, CONSTANT, devWfPDBDemo, "QSRV Demo")
# from imagedemo.c
function(QSRV_image_demo)
# from pvif.cpp
# Disable mapping of display.format
variable(qsrvDisableFormat, int)