Author: Marty Kraimer
Date: 2018.05.09
WARNING: This is a draft version of this document.
The following provide network access to ioc DBrecords:
This document describes compatability issues between these network providers.
The immediate goal is to start a discussion about possible changes to ca and qsrv. At the BNL FTF meeting in May 2018 we did discuss the Known issues. This document has been updated to give the current status.
Starting with Overview, this document will descibe compatability issues between the three network providers.
precision description For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. ... For a, A, e, E, f and F specifiers: this is the number of digits to be printed after the decimal point. ...If a channel access client makes a DBR_STRING request for reading a channel with native type DBF_DOUBLE or DBF_FLOAT then the server will use a Fl.p conversion where l is the total number of characters and p is the precision. But this is only done if the value is such that an F style format makes sense. If it does not it uses an E style format and ignores precision.
field(value[bytearray=string])
field(elements=value])
Current Status: Will be implemented.
channel access allows the client to specify the data types to be received from the server.
The necessary conversions are done on the server.
This is especially a problem for DBF_CHAR fields.
A DBRecord can have a DBF_CHAR or DBF_UCHAR value field,
but channel access has no concept of signed and unsigned types.
In the description of channel access below an example is given
that demonstrates the problem:
Note that the client does get correct values for DBF_CHAR but not for DBF_UCHAR
Perhaps there could be a field option:
field(value[byte=signed]) or field(value[byte=unsigned])
mrk> pvget -m -r "alarm" -i DBRdoubleArrayThe client will also get value,display,control, and valueAlarm fields.
mrk> pvget -p ca -m -r "alarm" -i DBRdoubleArrayThe client will only receive the requested fields.
EPICS has existed since the early 1990's. It evolved from a control system named GTACS which was developed at LANL in the second half of the 1980's. Two major features are:
An extensible set of record types can be created. Each record type has associated code, which is what makes the record "smart". Many record types are designed to interact with hardware like ADCs, DACs, etc. This document only discusses how a client, via channel access, or qsrv or ca can read, write, a monitor data from DBRecord instances.
exampleCPP has a number of examples. This document uses two of the examples.
database supports an IOC that has a combination of PVRecords and DBRecords. In this document we are only interested in DBRecords.
If an IOC is started as follows:
mrk> pwd /home/epicsv4/masterCPP/exampleCPP/database/iocBoot/exampleDatabase mrk> ../../bin/linux-x86_64/exampleDatabase st.cmdtypes
Then a set of DBRecords are available for every possible DBF type:
epics> dbnr Records Aliases Record Type 1 0 longout 2 0 mbbi 1 0 bi 1 0 floatout 1 0 ucharout 1 0 mbbo 1 0 ao 1 0 simpleBusy 1 0 bo 1 0 charout 9 0 waveform 1 0 stringout 1 0 ushortout 1 0 ai 1 0 calc 1 0 longin 1 0 stringin 1 0 shortout 1 0 calcout 1 0 ulongout Total 29 records, 0 aliases epics> dbl longout DBRlongout ... // similar for other scalar types epics> dbl waveform DBRbyteArray DBRshortArray DBRintArray DBRubyteArray DBRushortArray DBRuintArray DBRstringArray DBRfloatArray DBRdoubleArray epics>
The examples in this document access these records.
This has examples for issuing client get, put and monitor requests. For example:
mrk> exampleClient/get -help -h -p provider -r request - d debug channelNames default -p pva -r value,alarm,timeStamp -d false PVRdouble
A DBRecord instance is a structure with a set of fields defined by the record type. Each field name consists of at most 4 characters. For the database the characters are all lower case and for client access the same name but in upper case. There is a set of fields that are common to all record types and each record type defines an additional set of fields. Some of the fields accessable to clients are:
char name[61]; /* Record Name */ char desc[41]; /* Descriptor */ ... epicsTimeStamp time; /* Time */ ...
Each record type must define a field name val, must be one of the types defined in the next subsection. Many fields are declared NOACCESS, which means that clients can not directly access these fields. Each DBRecord instance has a record name. A client can access a record via a channel name. A channel name is identical to the record name with an optional .fieldname. If a field name is not specified then recordname.VAL is implied. A field accessible to clients is one of the following:
typedef struct epicsTimeStamp { epicsUInt32 secPastEpoch; /* seconds since 0000 Jan 1, 1990 */ epicsUInt32 nsec; /* nanoseconds within second */ } epicsTimeStamp;NOTE secPastEpoch overflows 136 years after 1900, i. e. in 2126.
Each record type must define a value field. Client code refers to this field with the name VAL and record support code the name val. Each record type must define the value field to be one of the following types.
typedef enum { DBF_STRING, // char[40]; DBF_CHAR, // epicsInt8 DBF_UCHAR, // epicsUInt8 DBF_SHORT, // epicsInt16 DBF_USHORT, // epicsUInt16 DBF_LONG, // epicsInt32 DBF_ULONG, // epicsUInt32 DBF_INT64, // epicsInt64 NOTE: Only starting with base 3.15 releases DBF_UINT64, // epicsUInt64 NOTE: Only starting with base 3.15 releases DBF_FLOAT, // epicsFloat32 DBF_DOUBLE, // epicsFloat64 DBF_ENUM, // epicsEnum16 ... }dbfType;
struct aRecord { char name[61]; /* Record Name */ char desc[41]; /* Descriptor */ ... /* other fields */ epicsEnum16 stat; /* Alarm Status */ epicsEnum16 sevr; /* Alarm Severity */ ... /* other fields */ epicsTimeStamp time; /* Time */ <type> val; /* Current value. Type is record type specific */ ... /* record type specific fields */ }
The val field type can be:
Each record support can implement a combination of the methods described in this section. Only the methods that make sense for the record type need to be implemented.
This section only describes the methods used for client access. Methods related to record processing are not described.
long get_units(DBADDR *, char * units);
long get_precision(const DBADDR *, long *precision);
long get_graphic_double(DBADDR *, struct dbr_grDouble *); struct dbr_grDouble { epicsFloat64 upper_disp_limit; /*upper limit of graph*/ epicsFloat64 lower_disp_limit; /*lower limit of graph*/ }
long get_control_double(DBADDR *, struct dbr_ctrlDouble *) struct dbr_ctrlDouble { epicsFloat64 upper_ctrl_limit; /*upper limit of graph*/ epicsFloat64 lower_ctrl_limit; /*lower limit of graph*/ }
long get_alarm_double(DBADDR *, struct dbr_alDouble *); struct dbr_alDouble { epicsFloat64 upper_alarm_limit; epicsFloat64 upper_warning_limit; epicsFloat64 lower_warning_limit; epicsFloat64 lower_alarm_limit; }
long get_enum_str(const DBADDR *, char *choice);
long get_enum_strs(const DBADDR *, struct dbr_enumStrs *) struct dbr_enumStrs { epicsUInt32 no_str; /* number of strings*/ epicsInt32 padenumStrs; /*padding to force 8 byte align*/ char strs[DB_MAX_CHOICES][MAX_STRING_SIZE]; /* string values */ } #define MAX_STRING_SIZE 40 #define DB_MAX_CHOICES 30
long put_enum_str(const DBADDR *, const char *choice);
long get_array_info(DBADDR *, long *no_elements, long *offset);
long put_array_info(DBADDR *, long nNew);
The basic functionality of channel access is defined in the header files db_access.h and cadef.h.
The primitive types supported are:
DBR_STRING char[MAX_STRING_SIZE] // MAX_STRING_SIZE=40 DBR_CHAR epicsInt8 DBR_SHORT epicsInt16 DBR_LONG epicsInt32 DBR_FLOAT epicsFloat32 DBR_DOUBLE epicsFloat64 DBR_ENUM epicsUInt16 // SEE BELOW FOR MORE DETAILS
Except for DBR_ENUM, an array of each type is also supported.
Notice that, other than DBR_ENUM, there is no concept of unsigned integer types. When a client connects to a channel, i.e recordname or recordname.fieldname, the client can get the type defined in the record. If the record holds an unsigned type then the type reported to the client is promoted to a wider type as follows:
BBR_CHAR NO PROMOTION DBR_SHORT => DBR_LONG DBR_LONG => DBR_DOUBLE
Note that since there is no promotion for DBR_CHAR the client can have strange behavior as follows:
mrk> caput DBRucharout -1 mrk> caget DBRucharout DBRucharout -1 mrk> caget -d DBR_CHAR DBRucharout DBRucharout Native data type: DBF_CHAR Request type: DBR_CHAR Element count: 1 Value: -1 mrk> caget -d DBR_LONG DBRucharout DBRucharout Native data type: DBF_CHAR Request type: DBR_LONG Element count: 1 Value: 255
The client can ask for any type it wants and the server side will convert between requested and actual types. In particular if the client ask for DBR_STRING then most conversion will be what the client desires. But this can be quite expensive, especially for arrays.
If the client specifies a type that is not the native type than the server converts between the native type and the type the client requests. If the client requests a type that is narrower than the native type then overflow can happen. The client will not be notified when this happens. Also note the problem mentioned above about unsigned integer types.
Note that the record support methods for limits, e. g. get_graphic_double, get_control_double, and get_alarm_double only get limit values as double. This means that for other types conversion are made when a client makes a request that involves limits.
For example consider a longout record and the client issues a DBR_CNTL_LONG request. The limit values in the record are type epicsInt32. When the limit values are read from the record they are converted to double. But the client requested limit values as epicsInt32 so the values are converted from double to epicsInt32. This works but causes some cpu usage.
caget is used in many of the examples below. It allows you to specify the request type:
mrk> caget -help ... -d <type>: Request specific dbr type; use string (DBR_ prefix may be omitted) or number of one of the following types: DBR_STRING 0 DBR_STS_FLOAT 9 DBR_TIME_LONG 19 DBR_CTRL_SHORT 29 DBR_INT 1 DBR_STS_ENUM 10 DBR_TIME_DOUBLE 20 DBR_CTRL_INT 29 DBR_SHORT 1 DBR_STS_CHAR 11 DBR_GR_STRING 21 DBR_CTRL_FLOAT 30 DBR_FLOAT 2 DBR_STS_LONG 12 DBR_GR_SHORT 22 DBR_CTRL_ENUM 31 DBR_ENUM 3 DBR_STS_DOUBLE 13 DBR_GR_INT 22 DBR_CTRL_CHAR 32 DBR_CHAR 4 DBR_TIME_STRING 14 DBR_GR_FLOAT 23 DBR_CTRL_LONG 33 DBR_LONG 5 DBR_TIME_INT 15 DBR_GR_ENUM 24 DBR_CTRL_DOUBLE 34 DBR_DOUBLE 6 DBR_TIME_SHORT 15 DBR_GR_CHAR 25 DBR_STSACK_STRING 37 DBR_STS_STRING 7 DBR_TIME_FLOAT 16 DBR_GR_LONG 26 DBR_CLASS_NAME 38 DBR_STS_SHORT 8 DBR_TIME_ENUM 17 DBR_GR_DOUBLE 27 DBR_STS_INT 8 DBR_TIME_CHAR 18 DBR_CTRL_STRING 28
Some examples are:
mrk> caput DBRdoubleout 1.33333 mrk> caget DBRdoubleout DBRdoubleout 1.33333 mrk> caget -d DBR_STRING DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_STRING Element count: 1 Value: 1.33 // NOTE PREC=2 mrk> caget -d DBR_SHORT DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_SHORT Element count: 1 Value: 1 mrk> caput DBRdoubleout 1e6 mrk> caget DBRdoubleout DBRdoubleout 1e+06 mrk> caget -d DBR_STRING DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_STRING Element count: 1 Value: 1000000.00 mrk> caget -d DBR_SHORT DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_SHORT Element count: 1 Value: 16960 // NOTE OVERFLOW mrk>
mrk> caput DBRushortout 65535 mrk> caget DBRushortout DBRushortout 65535 mrk> caget -d DBR_STRING DBRushortout DBRushortout Native data type: DBF_LONG // NOTE PROMOTION TO WIDER TYPE Request type: DBR_STRING Element count: 1 Value: 65535 mrk> caget -d DBR_SHORT DBRushortout DBRushortout Native data type: DBF_LONG Request type: DBR_SHORT Element count: 1 Value: -1 // NOTE CONVERSION TO SIGNED mrk> caget -d DBR_DOUBLE DBRushortout DBRushortout Native data type: DBF_LONG Request type: DBR_DOUBLE Element count: 1 Value: 65535
A way to pass strings longer than MAX_STRING_SIZE is to create a record with a value field that is an array of type DBF_UCHAR. The client must know that this is why the record exists and must convert the array of bytes to a string.
For example:
mrk> caput -a -S DBRbyteArray test mrk> caget -S DBRbyteArray DBRbyteArray test mrk>
This is how channel access provides access to record types like bi, bo, mbbbi,and mbbo. The value field is just an epicsUInt16.
The value is the index of a set of choices. The choices can be obtained as follows:
mrk> caget -d DBR_GR_ENUM DBRmbbout DBRmbbout Native data type: DBF_ENUM Request type: DBR_GR_ENUM Element count: 1 Value: one Status: UDF Severity: NO_ALARM Enums: (16) [ 0] zero [ 1] one [ 2] two [ 3] three [ 4] four [ 5] five [ 6] six [ 7] seven [ 8] eight [ 9] nine [10] ten [11] eleven [12] twelve [13] thirteen [14] fourteen [15] fifteen
This is the prefix to obtain the status and severity in addition to a value. The complete set of types are DBR_STS_STRING, DBR_STS_STRING, DBR_STS_CHAR, DBR_STS_SHORT, DBR_STS_LONG, DBR_STS_FLOAT,DBR_STS_DOUBLE and DBR_STS_ENUM.
Some examples are:
mrk> caget -d DBR_STS_ENUM DBRmbbout DBRmbbout Native data type: DBF_ENUM Request type: DBR_STS_ENUM Element count: 1 Value: 2 Status: NO_ALARM Severity: NO_ALARM mrk> caget -d DBR_STS_STRING DBRmbbout DBRmbbout Native data type: DBF_ENUM Request type: DBR_STS_STRING Element count: 1 Value: two Status: NO_ALARM Severity: NO_ALARM mrk> caget -d DBR_STS_DOUBLE DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_STS_DOUBLE Element count: 1 Value: 1.5 Status: NO_ALARM Severity: NO_ALARM
This is similar to DBR_STS except that the time is also returned.
Some examples are:
mrk> caget -d DBR_TIME_ENUM DBRmbbout DBRmbbout Native data type: DBF_ENUM Request type: DBR_TIME_ENUM Element count: 1 Value: 2 Timestamp: 2018-04-17 13:43:38.936139 Status: NO_ALARM Severity: NO_ALARM mrk> caget -d DBR_TIME_STRING DBRmbbout DBRmbbout Native data type: DBF_ENUM Request type: DBR_TIME_STRING Element count: 1 Value: two Timestamp: 2018-04-17 13:43:38.936139 Status: NO_ALARM Severity: NO_ALARM mrk> caget -d DBR_TIME_DOUBLE DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_TIME_DOUBLE Element count: 1 Value: 1.5 Timestamp: 2018-04-17 13:43:27.019340 Status: NO_ALARM Severity: NO_ALARM
This returns value, status, severity, units, precision, display limits, and alarm limits. Note that it is similar to DBR_CTRL except that it does not return control limits,
This returns value, status, severity, units, precision, display limits, alarm limits,
and control limits.
Note that epicsTimeStamp is not returned.
Some examples are:
mrk> caget -d DBR_CTRL_DOUBLE DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_CTRL_DOUBLE Element count: 1 Value: 1.5 Status: NO_ALARM Severity: NO_ALARM Units: volts Precision: 2 Lo disp limit: -10 Hi disp limit: 10 Lo alarm limit: -8 Lo warn limit: -6 Hi warn limit: 6 Hi alarm limit: 8 Lo ctrl limit: -1e+29 Hi ctrl limit: 1e+29 mrk> caget -d DBR_CTRL_LONG DBRlongout DBRlongout Native data type: DBF_LONG Request type: DBR_CTRL_LONG Element count: 1 Value: 100 Status: HIHI Severity: MAJOR Units: volts Lo disp limit: -2147483648 Hi disp limit: 2147483647 Lo alarm limit: -80 Lo warn limit: -60 Hi warn limit: 60 Hi alarm limit: 80 Lo ctrl limit: -2147483648 Hi ctrl limit: 2147483647 mrk>
As mentioned above the database has field types DBF_CHAR and DBF_UCHAR but channel access only has DBR_CHAR. In addition DBF_UCHAR is not promoted to DBR_SHORT.
This leads to strange behavior as the following examples show.
For channel access
mrk> caget -d DBR_GR_CHAR DBRcharout DBRcharout Native data type: DBF_CHAR Request type: DBR_GR_CHAR Element count: 1 Value: -127 Status: NO_ALARM Severity: NO_ALARM Units: Lo disp limit: -128 Hi disp limit: 127 Lo alarm limit: -100 Lo warn limit: -80 Hi warn limit: 80 Hi alarm limit: 100 mrk> caget -d DBR_GR_CHAR DBRucharout DBRucharout Native data type: DBF_CHAR Request type: DBR_GR_CHAR Element count: -127 //NOT CORRECT Value: 0 //NOT CORRECT Status: NO_ALARM Severity: NO_ALARM Units: Lo disp limit: 0 Hi disp limit: -1 //NOT CORRECT Lo alarm limit: 20 Lo warn limit: 50 Hi warn limit: -106 //NOT CORRECT Hi alarm limit: -56 //NOT CORRECT mrk> caget -d DBR_GR_DOUBLE DBRcharout DBRcharout Native data type: DBF_CHAR Request type: DBR_GR_DOUBLE Element count: 1 Value: -127 Status: NO_ALARM Severity: NO_ALARM Units: Precision: 0 Lo disp limit: -128 Hi disp limit: 127 Lo alarm limit: -100 Lo warn limit: -80 Hi warn limit: 80 Hi alarm limit: 100 mrk> caget -d DBR_GR_DOUBLE DBRucharout DBRucharout Native data type: DBF_CHAR Request type: DBR_GR_DOUBLE Element count: 1 Value: 129 Status: NO_ALARM Severity: NO_ALARM Units: Precision: 0 Lo disp limit: 0 Hi disp limit: 255 Lo alarm limit: 20 Lo warn limit: 50 Hi warn limit: 150 Hi alarm limit: 200
If the client specifies DBR_GR_DOUBLE the client always gets correct values for limits and value. If the client specifies DBR_GR_CHAR the client does not always get correct values for limits and value.
The mapping from the DBF types for the value field of DBRecord to pvData is:
DBF_STRING pvString DBF_CHAR pvByte DBF_SHORT pvShort DBF_UCHAR pvUByte DBF_USHORT pvUShort DBF_LONG pvInt DBF_ULONG pvUInt DBF_INT64 pvLong DBF_UINT64 pvULong DBF_FLOAT pvFloat DBF_DOUBLE pvDouble DBF_ENUM SEE BELOWExcept for enum each of these is either type scalar or scalarArray.
pvDataCPP defines property structures for enum,alarm,timeStamp,display,control, and valueAlarm.
This is a structure for representing DBF_ENUM DBRecord fields.
An example is:
mrk> pvget -i -p ca -r "value" DBRmbbout DBRmbbout epics:nt/NTEnum:1.0 enum_t value int index 2 string[] choices [zero,one,two,three,four,five,six, seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen]
A structure with fields for status, severity, message, and userTag.
An example is:
mrk> pvget -i -p ca -r "alarm" DBRdoubleout DBRdoubleout structure alarm_t alarm int severity 2 int status 3 string message HIHI
pvDataCPP provides alarm.h and pvAlarm.h to make it easier to work with alarms.
A structure with fields for a timeStamp and userTag.
An example is:
mrk> pvget -i -p ca -r "timeStamp" DBRdoubleout DBRdoubleout structure time_t timeStamp long secondsPastEpoch 1523989803 int nanoseconds 829527650 int userTag 0
Note that secondsPastEpoch is a 64 bit integer and the base year is the posix base year which is Jan 1, 1970 UTC.
qsrv and ca both convert the DBRecord time stamp so that the client has the correct posix base.
Note also that, since secondsPastEpoch is a 64 bit integer, it will not overflow for a number
of years greater than the age of our universe.
pvDataCPP provides timeStamp.h and pvTimeStamp.h to make it easier to work with timeStamps.
A structure of the form:
mrk> pvget -i -p ca -r "display" DBRdoubleout DBRdoubleout structure display_t display double limitLow -10 double limitHigh 10 string description string format F8.2 string units volts
pvDataCPP provides display.h, which makes it easier to work with display.
A structure of the form:
mrk> pvget -i -p ca -r "control" DBRdoubleout DBRdoubleout structure control_t control double limitLow -1e+29 double limitHigh 1e+29 double minStep 0 //NOTE that channel access does not define this
pvDataCPP provides control.h, which makes it easier to work with control.
A structure of the form:
mrk> pvget -i -p ca -r "valueAlarm" DBRdoubleout DBRdoubleout structure valueAlarm_t valueAlarm boolean active false double lowAlarmLimit -8 double lowWarningLimit -6 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 //NOTE that channel access does not define this int lowWarningSeverity 0 //NOTE that channel access does not define this int highWarningSeverity 0 //NOTE that channel access does not define this int highAlarmSeverity 0 //NOTE that channel access does not define this double hysteresis 0
qsrv is a server side channel provider that directly accesses the DBRecord database, i. e. it does NOT use channel access.
ca is a client side channel provider. It uses the channel access network protocol to communicate with an IOC. Thus no pvData related code needs to be in the IOC. It converts between pvData and the data used by channel access.
A major difference between both qsrv/ca and pure channel access is that all conversion between datatypes is done by the client instead of by the server. For example there is no equivalent to:
mrk> caget -d DBR_STRING DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_STRING Element count: 1 Value: 100.00
With qsrv and ca the following happens:
mrk> pvget -i -p pva -r "value" DBRdoubleout DBRdoubleout epics:nt/NTScalar:1.0 double value 100 mrk> pvget -i -p ca -r "value" DBRdoubleout DBRdoubleout structure double value 100
Since qsrv interfaces directly to the DBRecord database, it supports all DBF types including unsigned integers.
Since ca uses channel access to communicated with the IOC DBRecords, it is subject to the same restrictions as channel access itself. In particular it does not support 64 bit integers. It also has behavior similar to channel access for unsigned integers,
mrk> caget -d DBR_TIME_STRING DBRlongout DBRlongout Native data type: DBF_LONG Request type: DBR_TIME_STRING Element count: 1 Value: 100 Timestamp: 2018-04-17 13:53:55.932364 Status: HIHI Severity: MAJOR mrk> caget -d DBR_TIME_DOUBLE DBRlongout DBRlongout Native data type: DBF_LONG Request type: DBR_TIME_DOUBLE Element count: 1 Value: 100 Timestamp: 2018-04-17 13:53:55.932364 Status: HIHI Severity: MAJOR mrk> pvget -p pva -r "value,alarm,timeStamp" DBRlongout DBRlongout epics:nt/NTScalar:1.0 int value 100 alarm_t alarm MAJOR DEVICE HIHI time_t timeStamp 2018-04-17T13:53:55.932 0 // NOTE trailing 0 is userTag display_t display // NOTE THAT THIS WAS NOT REQUESTED double limitLow -2.14748e+09 double limitHigh 2.14748e+09 string description longout string format string units volts control_t control // NOTE THAT THIS WAS NOT REQUESTED double limitLow -2.14748e+09 double limitHigh 2.14748e+09 double minStep 0 valueAlarm_t valueAlarm // NOTE THAT THIS WAS NOT REQUESTED boolean active false int lowAlarmLimit -80 int lowWarningLimit -60 int highWarningLimit 60 int highAlarmLimit 80 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 int hysteresis 0 mrk> pvget -p ca -r "value,alarm,timeStamp" DBRlongout DBRlongout structure int value 100 alarm_t alarm MAJOR RECORD HIHI time_t timeStamp 2018-04-17T13:53:55.932 0 // NOTE trailing 0 is userTag
mrk> caget -d DBR_TIME_STRING DBRulongout DBRulongout Native data type: DBF_DOUBLE Request type: DBR_TIME_STRING Element count: 1 Value: 10 Timestamp: 2018-04-18 06:21:31.829911 Status: LOLO Severity: MAJOR mrk> caget -d DBR_TIME_DOUBLE DBRulongout DBRulongout Native data type: DBF_DOUBLE Request type: DBR_TIME_DOUBLE Element count: 1 Value: 10 Timestamp: 2018-04-18 06:21:31.829911 Status: LOLO Severity: MAJOR mrk> pvget -p pva -r "value,alarm,timeStamp" DBRulongout DBRulongout epics:nt/NTScalar:1.0 uint value 10 alarm_t alarm MAJOR DEVICE LOLO time_t timeStamp 2018-04-18T06:21:31.830 0 display_t display // NOTE THAT THIS WAS NOT REQUESTED double limitLow 0 double limitHigh 4.29497e+09 string description ulongout string format string units control_t control // NOTE THAT THIS WAS NOT REQUESTED double limitLow 0 double limitHigh 4.29497e+09 double minStep 0 valueAlarm_t valueAlarm // NOTE THAT THIS WAS NOT REQUESTED boolean active false uint lowAlarmLimit 20 uint lowWarningLimit 40 uint highWarningLimit 60 uint highAlarmLimit 80 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 uint hysteresis 0 mrk> pvget -p ca -r "value,alarm,timeStamp" DBRulongout DBRulongout structure double value 10 alarm_t alarm MAJOR CONF LOLO time_t timeStamp 2018-04-18T06:21:31.830 0
mrk> caget -d DBR_TIME_STRING DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_TIME_STRING Element count: 1 Value: 90.00 Timestamp: 2018-04-18 06:25:04.045084 Status: HIHI Severity: MAJOR mrk> caget -d DBR_TIME_DOUBLE DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_TIME_DOUBLE Element count: 1 Value: 90 Timestamp: 2018-04-18 06:25:04.045084 Status: HIHI Severity: MAJOR mrk> pvget -p pva -r "value,alarm,timeStamp" DBRdoubleout DBRdoubleout epics:nt/NTScalar:1.0 double value 90 alarm_t alarm MAJOR DEVICE HIHI time_t timeStamp 2018-04-18T06:25:04.045 0 display_t display // NOTE THAT THIS WAS NOT REQUESTED double limitLow -10 double limitHigh 10 string description ao string format string units volts control_t control // NOTE THAT THIS WAS NOT REQUESTED double limitLow -1e+29 double limitHigh 1e+29 double minStep 0 valueAlarm_t valueAlarm // NOTE THAT THIS WAS NOT REQUESTED boolean active false double lowAlarmLimit -8 double lowWarningLimit -6 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hysteresis 0 mrk> pvget -p ca -r "value,alarm,timeStamp" DBRdoubleout DBRdoubleout structure double value 90 alarm_t alarm MAJOR RECORD HIHI time_t timeStamp 2018-04-18T06:25:04.045 0
mrk> caget -d DBR_TIME_STRING DBRdoubleArray DBRdoubleArray Native data type: DBF_DOUBLE Request type: DBR_TIME_STRING Element count: 5 Value: 1.11 2.22 3.33 4.44 5.56 Timestamp: 2018-04-18 06:28:26.644374 Status: NO_ALARM Severity: NO_ALARM mrk> caget -d DBR_TIME_DOUBLE DBRdoubleArray DBRdoubleArray Native data type: DBF_DOUBLE Request type: DBR_TIME_DOUBLE Element count: 5 Value: 1.11111 2.22222 3.33333 4.44444 5.55555 Timestamp: 2018-04-18 06:28:26.644374 Status: NO_ALARM Severity: NO_ALARM mrk> pvget -p pva -r "value,alarm,timeStamp" DBRdoubleArray DBRdoubleArray epics:nt/NTScalarArray:1.0 double[] value [1.11111,2.22222,3.33333,4.44444,5.55555] alarm_t alarm NO_ALARM NO_STATUS NO_ALARM time_t timeStamp 2018-04-18T06:28:26.644 0 display_t display // NOTE THAT THIS WAS NOT REQUESTED double limitLow -1000 double limitHigh 1000 string description doubleArray string format string units control_t control // NOTE THAT THIS WAS NOT REQUESTED double limitLow -1000 double limitHigh 1000 double minStep 0 valueAlarm_t valueAlarm // NOTE THAT THIS WAS NOT REQUESTED boolean active false double lowAlarmLimit nan double lowWarningLimit nan double highWarningLimit nan double highAlarmLimit nan int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hysteresis 0 mrk> pvget -p ca -r "value,alarm,timeStamp" DBRdoubleArray DBRdoubleArray structure double[] value [1.11111,2.22222,3.33333,4.44444,5.55555] alarm_t alarm NO_ALARM NO_STATUS <no message> time_t timeStamp 2018-04-18T06:28:26.644 0
mrk> caget -d DBR_TIME_STRING DBRbinaryout DBRbinaryout Native data type: DBF_ENUM Request type: DBR_TIME_STRING Element count: 1 Value: one Timestamp: 2018-04-18 06:31:47.470022 Status: LINK Severity: INVALID mrk> caget -d DBR_TIME_ENUM DBRbinaryout DBRbinaryout Native data type: DBF_ENUM Request type: DBR_TIME_ENUM Element count: 1 Value: 1 Timestamp: 2018-04-18 06:31:47.470022 Status: LINK Severity: INVALID mrk> pvget -p pva -r "value,alarm,timeStamp" DBRbinaryout DBRbinaryout epics:nt/NTEnum:1.0 enum_t value one alarm_t alarm INVALID RECORD LINK time_t timeStamp 2018-04-18T06:31:47.470 0 mrk> pvget -p ca -r "value,alarm,timeStamp" DBRbinaryout DBRbinaryout epics:nt/NTEnum:1.0 enum_t value one alarm_t alarm INVALID 14 LINK time_t timeStamp 2018-04-18T06:31:47.470 0 mrk> exampleClient/get -p ca -r "value,alarm,timeStamp" DBRbinaryout ... Type exit to stop: // enter key pressed channelGetDone DBRbinaryout status Status [type=OK] changed DBRbinaryout = epics:nt/NTEnum:1.0 enum_t value int index 1 string[] choices [zero,one] alarm_t alarm int severity 3 int status 14 string message LINK time_t timeStamp long secondsPastEpoch 1524047507 int nanoseconds 470022134 int userTag 0 bitSet {0} Type exit to stop: exit
mrk> caget -d DBR_CTRL_STRING DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_CTRL_STRING Element count: 1 Value: 0.00 Status: UDF Severity: INVALID mrk> caget -d DBR_CTRL_DOUBLE DBRdoubleout DBRdoubleout Native data type: DBF_DOUBLE Request type: DBR_CTRL_DOUBLE Element count: 1 Value: 0 Status: UDF Severity: INVALID Units: volts Precision: 2 Lo disp limit: -10 Hi disp limit: 10 Lo alarm limit: -8 Lo warn limit: -6 Hi warn limit: 6 Hi alarm limit: 8 Lo ctrl limit: -1e+29 Hi ctrl limit: 1e+29 mrk> pvget -p pva -r "display,control,valueAlarm" DBRdoubleout DBRdoubleout epics:nt/NTScalar:1.0 double value 0 // NOT REQUESTED alarm_t alarm INVALID DRIVER UDF // NOT REQUESTED time_t timeStamp <undefined> 0 // NOT REQUESTED display_t display double limitLow -10 double limitHigh 10 string description ao string format string units volts control_t control double limitLow -1e+29 double limitHigh 1e+29 double minStep 0 valueAlarm_t valueAlarm boolean active false double lowAlarmLimit -8 double lowWarningLimit -6 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hysteresis 0 mrk> pvget -p ca -r "display,control,valueAlarm" DBRdoubleout DBRdoubleout structure display_t display double limitLow -10 double limitHigh 10 string description string format F8.2 string units volts control_t control double limitLow -1e+29 double limitHigh 1e+29 double minStep 0 valueAlarm_t valueAlarm boolean active false double lowAlarmLimit -8 double lowWarningLimit -6 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hysteresis 0
mrk> pvget -i -p pva -m -r "value,alarm,timeStamp" DBRdoubleout DBRdoubleout epics:nt/NTScalar:1.0 double value 0 alarm_t alarm int severity 0 int status 0 string message NO_ALARM time_t timeStamp long secondsPastEpoch 1524049231 int nanoseconds 383230407 int userTag 0 display_t display // NOT REQUESTED double limitLow -10 double limitHigh 10 string description ao string format string units volts control_t control // NOT REQUESTED double limitLow -1e+29 double limitHigh 1e+29 double minStep 0 valueAlarm_t valueAlarm // NOT REQUESTED boolean active false double lowAlarmLimit -8 double lowWarningLimit -6 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hysteresis 0 // NOTE A PUT WAS ISSUED DBRdoubleout epics:nt/NTScalar:1.0 double value 1 alarm_t alarm // DID NOT CHANGE int severity 0 int status 0 string message NO_ALARM time_t timeStamp long secondsPastEpoch 1524049280 int nanoseconds 90405898 int userTag 0 display_t display // DID NOT CHANGE AND NOT REQUESTED double limitLow -10 double limitHigh 10 string description ao string format string units volts control_t control // DID NOT CHANGE AND NOT REQUESTED double limitLow -1e+29 double limitHigh 1e+29 double minStep 0 valueAlarm_t valueAlarm // DID NOT CHANGE AND NOT REQUESTED boolean active false double lowAlarmLimit -8 double lowWarningLimit -6 double highWarningLimit 6 double highAlarmLimit 8 int lowAlarmSeverity 0 int lowWarningSeverity 0 int highWarningSeverity 0 int highAlarmSeverity 0 double hysteresis 0
With pvget
mrk> pvget -m -p ca -r "value,alarm,timeStamp" -i DBRdoubleout DBRdoubleout structure double value 0 alarm_t alarm int severity 0 int status 0 string message time_t timeStamp long secondsPastEpoch 1524049508 int nanoseconds 416616659 int userTag 0 // NOTE THAT WHEN A PUT CAUSES AN EVENT pvput still displays all fields. DBRdoubleout structure double value 1 alarm_t alarm int severity 0 int status 0 string message time_t timeStamp long secondsPastEpoch 1524049828 int nanoseconds 542712998 int userTag 0
Now with exampleClient
mrk> exampleClient/monitor -p ca -r "value,alarm,timeStamp" DBRdoubleout event DBRdoubleout monitor changed = structure double value 1 alarm_t alarm int severity 0 int status 0 string message time_t timeStamp long secondsPastEpoch 1524049423 int nanoseconds 322158828 int userTag 0 overrun // NOTE THAT WHEN PUT IS ISSUED ONLY CHANGED FIELDS ARE DISPLAYED event DBRdoubleout monitor changed value = 0 timeStamp.secondsPastEpoch = 1524049508 timeStamp.nanoseconds = 416616659 overrun