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