This product is made available subject to acceptance of the EPICS open source license.
EPICS Version 4 provides efficient
storage, access, and communication, of memory resident structured data.
The EPICS V4 Normative Types are a collection of structured data types
that can be used by the application level of EPICS V4 network endpoints,
to interoperably exchange scientific data.
normativeTypesCPP is the C++ implementation.
It is one part of the set of related products in the EPICS
V4 control system programming environment:
relatedDocumentsV4.html
This is the 18-March-2016 version for the 5.1-development release of the C++ implementation of normativeTypes.
RELEASE_NOTES.md provides changes since the last release. TODO.md describes things to do before the next release.
This manual assumes that the reader is familiar with the material in pvDataCPP.html
At present the following normative types are implemented:
There is also additional support for NTAttributes which are extended as required by NTNDArray.
Thus normativeTypesCPP implements fully the March 16 2015 version the Normative Types Specification.
This version of the document only covers the types originally implemented:
Documentation for the remaining types will addressed in the next version of this document.
Each normative type consists of a set of mandatory fields, a set of optional fields, and any arbitrary number of extra fields. The mandatory and optional fields are meant for use by standard tools such as Display Managers and Alarm Handlers. The extra fields are for specialized tools.
A helper class NTField is provided to enforce the proper implementation of property fields as defined by pvData. A property field is normally associated with a field that has the name "value". The property fields currently used are alarm, timeStamp, display, control, and alarmLimit. In addition pvData defines a standard structure for a value field that represents enumerated values. NTField has methods associated with each of these.
An include file "nt.h" includes all the other header files that are provided by ntCPP.
The next section describes NTField. Next a set of standard optional fields used by many normative types is described. Then each normative type is described.
These are helper classes for creating standard fields for normative types. There is a single instance of this class, which is obtained via NTField::get().
class NTField{ public: static NTFieldPtr get(); ~NTField() {} bool isEnumerated(FieldConstPtr const & field); bool isTimeStamp(FieldConstPtr const & field); bool isAlarm(FieldConstPtr const & field); bool isDisplay(FieldConstPtr const & field); bool isAlarmLimit(FieldConstPtr const & field); bool isControl(FieldConstPtr const & field); StructureConstPtr createEnumerated(); StructureConstPtr createTimeStamp(); StructureConstPtr createAlarm(); StructureConstPtr createDisplay(); StructureConstPtr createControl(); StructureArrayConstPtr createEnumeratedArray(); StructureArrayConstPtr createTimeStampArray(); StructureArrayConstPtr createAlarmArray(); };
where
Often a property field is associated with another field. This other field is referred to as the value field. Usually the value field will have the field name "value". An example is:
structure parent double value structure alarm
In this example the alarm field reports alarms for the value field.
An alarm structure is used to report alarms and other problems to the client. An alarm may be associated with a value field or can be used by a server to report problems to the client. An alarm attached to a substructure of the top-level structure is normally associated with a value field. An alarm field attached to the top-level structure can be used for either:
If alarms do appear at multiple levels then an alarm is always provided at the top-level. It uses "maximize severity" to report the highest level severity of all alarms, i.e. the top-level severity is the maximum severity of all the alarms.
An example is:
structure top structure alarm structure power double value structure alarm structure voltage double value structure alarm structure current double value structure alarm
In this example power, voltage, and current all have an associated alarm. The top-level alarm would have a severity that matches the highest level severity of power, voltage, an current.
A alarm structure has the following fields:
structure alarm int severity int status string message
Clients and Servers should use alarm.h and pvAlarm.h which are provided by pvDataCPP instead of directly using the alarm structure itself. In particular severity and status are defined as:
enum AlarmSeverity { noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm }; enum AlarmStatus { noStatus,deviceStatus,driverStatus,recordStatus, dbStatus,confStatus,undefinedStatus,clientStatus };
A timeStamp provides the time when the server executes or the time when a the data for a value field was collected. There can be multiple timeStamp fields. A timeStamp associated with a substructure is usually associated with a value field. An timeStamp field attached to the top-level structure can be used for either:
NTNDArray is an example that has two top-level timeStamp fields with different field names because it wants to report both.
A timeStamp structure has the following fields:
structure timeStamp long secondsPastEpoch int nanoseconds int userTag
Clients and Servers should use timeStamp.h and pvTimeStamp.h which are provided by pvDataCPP instead of directly using the timeStamp structure itself. Note that timeStamp.h provides many methods for manipulating time.
The meaning of the fields is:
This is used to specify operational limits for a numeric scalar value field.
structure control double limitLow double limitHigh double minStep
Servers should use control.h and pvControl.h which are provided by pvDataCPP instead of directly using the control structure itself. Note that control.h provides many methods for manipulating time.
This is used to specify display limits and other information for a numeric scalar value field.
structure display double limitLow double limitHigh string description string format string units
Note that the format should be a simplified version of the standard C formatting conventions.
This is used to specify a set of choices and an index that selects one of the choices. For readers familiar with EPICS core this is like the ENUM types.
structure int index string[] choices
This is used to specify alarm limits for a double scalar value field. It can be used by plotting tools to show alarm limits and associated severities.
structure boolean active double lowAlarmLimit double lowWarningLimit double highWarningLimit double highAlarmLimit int lowAlarmSeverity int lowWarningSeverity int highWarningSeverity int highAlarmSeverity double hysteresis
NOTE: NTField, described above, has support for checking to see if a structure is an alarmLimit structure but no other support for alarmLimit.
pvData has support named valueAlarm instead of alarmLimit (alarmLimit is identical to valueAlarm for type double). For numeric types the field names are the same but the type for lowAlarmLimit, lowWarningLimit, highWarningLimit, and highAlarmLimit is based on the scalarType. pvData also defines valueAlarm for a scalar boolean value field and for an enumerated structure. For these completely different field names are defined. valueAlarm is more for use by servers than for clients. Thus normative types only defines alarmLimit since this is what clients like plot tools use. If the valueAlarm fields, including alarmLimit, are desired than the standardField support from pvData can be used to generate a valueAlarm field as an extra field.
Each normative type has two classes: a builder and a class for the normative type itself.
This is a class that can create one of the following:
Each builder also has a number of additional methods for optional fields and a method to add extra fields.
This has methods to do the following:
This has the following fields:
epics:nt/NTScalar:1.0 double value // mandatory and can be any numeric type string descriptor // optional alarm_t alarm // optional int severity int status string message time_t timeStamp // optional long secondsPastEpoch int nanoseconds int userTag display_t display // optional double limitLow double limitHigh string description string format string units control_t control // optional double limitLow double limitHigh double minStep string extra1 // extra string[] extra2 //
This is a class that creates the introspection and data instances for NTScalar and an a NTScalar instance itself.
ntscalar.h defines the following:
class NTScalar; typedef std::tr1::shared_ptr<NTScalar> NTScalarPtr; class NTScalarBuilder { public: POINTER_DEFINITIONS(NTScalarBuilder); shared_pointer value(ScalarType scalarType); shared_pointer addDescriptor(); shared_pointer addAlarm(); shared_pointer addTimeStamp(); shared_pointer addDisplay(); shared_pointer addControl(); StructureConstPtr createStructure(); PVStructurePtr createPVStructure(); NTScalarPtr create(); shared_pointer add( string const & name, FieldConstPtr const & field); private: }where
An NTScalarBuilder can be used to create multiple PVStructure and/or NTScalar instances. Each time createPVScalar is called it clears all internal data after the PVStructure is created.
An example of creating an NTScalar instance is:
NTScalarBuilderPtr builder = NTScalar::createBuilder(); NTScalarPtr ntScalar = builder-> value(pvInt)-> addDescriptor()-> addAlarm()-> addTimeStamp()-> addDisplay()-> addControl()-> create();
The same results could be done by:
NTScalarBuilderPtr builder = NTScalar::createBuilder(); builder->value(pvInt); builder->addDescriptor(); builder->addAlarm(); builder->addTimeStamp(); builder->addDisplay(); builder->addControl(); NTScalarPtr ntScalar = builder->create();
ntscalar.h defines the following:
class NTScalar; typedef std::tr1::shared_ptr<NTScalar> NTScalarPtr; class NTScalar { public: POINTER_DEFINITIONS(NTScalar); ~NTScalar() {} static shared_pointer wrap(PVStructurePtr const & structure); static shared_pointer wrapUnsafe(PVStructurePtr const & structure); static bool is_a(StructureConstPtr const & structure); static bool isCompatible(PVStructurePtr const &pvStructure); static NTScalarBuilderPtr createBuilder(); bool attachTimeStamp(PVTimeStamp &pvTimeStamp) const; bool attachAlarm(PVAlarm &pvAlarm) const; bool attachDisplay(PVDisplay &pvDisplay) const; bool attachControl(PVControl &pvControl) const; PVStructurePtr getPVStructure() const; PVStructurePtr getTimeStamp() const; PVStructurePtr getAlarm() const; PVStructurePtr getDisplay() const; PVStructurePtr getControl() const; PVFieldPtr getValue() const; template<typename PVT> std::tr1::shared_ptr<PVT> getValue() const private: }where
void myCallback(PVStructurePtr const & PVStructure) { NTScalarPtr ntscalar = NTScalar::wrap(PVStructure); if(!ntscalar) { // not a valid NTScalar } ... }
PVTimeStamp pvTimeStamp; TimeStamp timeStamp; ntscalar->attachTimeStamp(pvTimeStamp); pvTimeStamp.get(timeStamp); TimeStamp current; current.getCurrent(); double diff = TimeStamp::diff(timeStamp,current); // timeStamp - current
PVAlarm pvAlarm; Alarm alarm; ntscalar->attachAlarm(pvAlarm); pvAlarm.get(alarm); int severity = alarm.getSeverity(); int status = alarm.getStatus(); string message = alarm.getMessage();
This class is similar to NTScalar except that the value field is a scalar array field instead of just a scalar.
This has the following fields:
epics:nt/NTScalarArray:1.0 double[] value // mandatory and can be any numeric type string descriptor // optional alarm_t alarm // optional int severity int status string message time_t timeStamp // optional long secondsPastEpoch int nanoseconds int userTag display_t display // optional double limitLow double limitHigh string description string format string units control_t control // optional double limitLow double limitHigh double minStep string extra1 // extra string[] extra2 //
ntscalarArray.h defines the following:
class NTScalarArray; typedef std::tr1::shared_ptr<NTScalarArray> NTScalarArrayPtr; class NTScalarArrayBuilder { public: POINTER_DEFINITIONS(NTScalarArrayBuilder); shared_pointer arrayValue(ScalarType elementType); shared_pointer addDescriptor(); shared_pointer addAlarm(); shared_pointer addTimeStamp(); shared_pointer addDisplay(); shared_pointer addControl(); StructureConstPtr createStructure(); PVStructurePtr createPVStructure(); NTScalarArrayPtr create(); shared_pointer add( string const & name, FieldConstPtr const & field); private: }where
ntscalarArray.h defines the following:
class NTScalarArray; typedef std::tr1::shared_ptr<NTScalarArray> NTScalarArrayPtr; class NTScalarArray { public: POINTER_DEFINITIONS(NTScalarArray); ~NTScalarArray() {} static shared_pointer wrap(PVStructurePtr const & structure); static shared_pointer wrapUnsafe(PVStructurePtr const & structure); static bool is_a(StructureConstPtr const & structure); static bool isCompatible(PVStructurePtr const &pvStructure); static NTScalarArrayBuilderPtr createBuilder(); bool attachTimeStamp(PVTimeStamp &pvTimeStamp) const; bool attachAlarm(PVAlarm &pvAlarm) const; bool attachDisplay(PVDisplay &pvDisplay) const; bool attachControl(PVControl &pvControl) const; PVStructurePtr getPVStructure() const; PVStructurePtr getTimeStamp() const; PVStructurePtr getAlarm() const; PVStructurePtr getDisplay() const; PVStructurePtr getControl() const; PVFieldPtr getValue() const; template<typename PVT> std::tr1::shared_ptr<PV> getValue() const private: }where
epics:nt/NTNameValue:1.0 string[] name // mandatory double[] value // mandatory, can be any type, must be same length as name string descriptor // optional alarm_t alarm // optional int severity int status string message time_t timeStamp // optional long secondsPastEpoch int nanoseconds int userTag string extra1 // extra string[] extra2 // extra
ntnameValue.h defines the following:
class NTNameValue; typedef std::tr1::shared_ptr<NTNameValue> NTNameValuePtr; class NTNameValueBuilder { public: POINTER_DEFINITIONS(NTNameValueBuilder); shared_pointer value(ScalarType scalarType); shared_pointer addDescriptor(); shared_pointer addAlarm(); shared_pointer addTimeStamp(); StructureConstPtr createStructure(); PVStructurePtr createPVStructure(); NTNameValuePtr create(); shared_pointer add( string const & name, FieldConstPtr const & field); private: }where
class NTNameValue; typedef std::tr1::shared_ptr<NTNameValue> NTNameValuePtr; class NTNameValue { public: POINTER_DEFINITIONS(NTNameValue); ~NTNameValue() {} static shared_pointer wrap(PVStructurePtr const & structure); static shared_pointer wrapUnsafe(PVStructurePtr const & structure); static bool is_a(StructureConstPtr const & structure); static bool isCompatible(PVStructurePtr const &pvStructure); static NTNameValueBuilderPtr createBuilder(); bool attachTimeStamp(PVTimeStamp &pvTimeStamp) const; bool attachAlarm(PVAlarm &pvAlarm) const; PVStringPtr getDescriptor() const; PVStructurePtr getPVStructure() const; PVStructurePtr getTimeStamp() const; PVStructurePtr getAlarm() const; PVStringArrayPtr getName() const; PVFieldPtr getValue() const; template<typename PVT> std::tr1::shared_ptr<PV> getValue() const private: }where
epics:nt/NTTable:1.0 string[] labels [column0,column1,column2] // mandatory structure value // mandatory double[] column0 [] // can be any scalar type string[] column1 [] // can be any scalar type int[] column2 [] // can be any scalar type string descriptor // optional alarm_t alarm // optional int severity int status string time_t timeStamp // optional long secondsPastEpoch int nanoseconds 498486530 int userTag string extra1 // extra
nttable.h defines the following:
class NTTable; typedef std::tr1::shared_ptr<NTTable> NTTablePtr; class NTTableBuilder { public: POINTER_DEFINITIONS(NTTableBuilder); shared_pointer addColumn(string const & name,ScalarType scalarType); shared_pointer addDescriptor(); shared_pointer addAlarm(); shared_pointer addTimeStamp(); StructureConstPtr createStructure(); PVStructurePtr createPVStructure(); NTTablePtr create(); shared_pointer add( string const & name, FieldConstPtr const & field); private: }where
class NTTable; typedef std::tr1::shared_ptr<NTTable> NTTablePtr; class NTTable { public: POINTER_DEFINITIONS(NTTable); ~NTTable() {} static shared_pointer wrap(PVStructurePtr const & structure); static shared_pointer wrapUnsafe(PVStructurePtr const & structure); static bool is_a(StructureConstPtr const & structure); static bool isCompatible(PVStructurePtr const &pvStructure); static NTTableBuilderPtr createBuilder(); bool attachTimeStamp(PVTimeStamp &pvTimeStamp) const; bool attachAlarm(PVAlarm &pvAlarm) const; PVStructurePtr getPVStructure() const; PVStringPtr getDescriptor() const; PVStructurePtr getTimeStamp() const; PVStructurePtr getAlarm() const; PVStringArrayPtr getLabels() const; PVFieldPtr getColumn(string const & columnName) const; template<typename PVT> std::tr1::shared_ptr<PV> getColumn(string const & columnName) const; private: }where
structure NTMultiChannel union_t[] value // mandatory string[] channelName // mandatory; must be same length as value time_t timeStamp // optional; time when data collected alarm_t alarm // optional; alarm associated with data collection int[] severity // optional; alarm severity for each value int[] status // optional; alarm status for each value string[] message // optional; alarm message for each value long[] secondsPastEpoch // optional; seconds for each value. int[] nanoseconds // optional; nanoseconds for each value string descriptor // optional; descriptor data
ntmultiChannel.h defines the following:
class NTMultiChannel; typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr; class NTMultiChannelBuilder { public: POINTER_DEFINITIONS(NTMultiChannelBuilder); shared_pointer value(UnionConstPtr valuePtr); shared_pointer addDescriptor(); shared_pointer addAlarm(); shared_pointer addTimeStamp(); shared_pointer addSeverity(); shared_pointer addStatus(); shared_pointer addMessage(); shared_pointer addSecondsPastEpoch(); shared_pointer addNanoseconds(); shared_pointer addUserTag(); StructureConstPtr createStructure(); PVStructurePtr createPVStructure(); NTMultiChannelPtr create(); shared_pointer add( string const & name, FieldConstPtr const & field); private: }where
class NTMultiChannel; typedef std::tr1::shared_ptr<NTMultiChannel> NTMultiChannelPtr; class NTMultiChannel { public: POINTER_DEFINITIONS(NTMultiChannel); ~NTMultiChannel() {} static shared_pointer wrap(PVStructurePtr const & structure); static shared_pointer wrapUnsafe(PVStructurePtr const & structure); static bool is_a(StructureConstPtr const & structure); static bool isCompatible(PVStructurePtr const &pvStructure); static NTMultiChannelBuilderPtr createBuilder(); bool attachTimeStamp(PVTimeStamp &pvTimeStamp) const; bool attachAlarm(PVAlarm &pvAlarm) const; PVStringPtr getDescriptor() const; PVStructurePtr getPVStructure() const; PVStructurePtr getTimeStamp() const; PVStructurePtr getAlarm() const; PVUnionArrayPtr getValue() const; PVStringArrayPtr getChannelName() const; PVBooleanArrayPtr getIsConnected() const; PVIntArrayPtr getSeverity() const; PVIntArrayPtr getStatus() const; PVStringArrayPtr getMessage() const; PVLongArrayPtr getSecondsPastEpoch() const; PVIntArrayPtr getNanoseconds() const; PVIntArrayPtr getUserTag() const; private: }where
epics:nt/NTNDArray:1.0 union value // mandatory codec_t codec // mandatory string name any parameters long compressedSize // mandatory long uncompressedSize // mandatory dimension_t[] dimension // mandatory dimension_t[] dimension_t int size int offset int fullSize int binning boolean reverse int uniqueId // mandatory time_t dataTimeStamp // mandatory long secondsPastEpoch int nanoseconds int userTag epics:nt/NTAttribute:1.0[] attribute // mandatory epics:nt/NTAttribute:1.0[] epics:nt/NTAttribute:1.0 string name any value string description int sourceType string source string descriptor // optional time_t timeStamp // optional long secondsPastEpoch int nanoseconds int userTag alarm_t alarm // optional int severity int status string message display_t display // optional double limitLow double limitHigh string description string format string units string extra1 // extra
ntndArray.h defines the following:
class NTNDArray; typedef std::tr1::shared_ptr<NTNDArray> NTNDArrayPtr; class NTNDArrayBuilder { public: POINTER_DEFINITIONS(NTNDArrayBuilder); shared_pointer addDescriptor(); shared_pointer addAlarm(); shared_pointer addTimeStamp(); shared_pointer addDisplay(); StructureConstPtr createStructure(); PVStructurePtr createPVStructure(); NTNDArrayPtr create(); shared_pointer add( string const & name, FieldConstPtr const & field); private: }where
class NTNDArray; typedef std::tr1::shared_ptr<NTNDArray> NTNDArrayPtr; class NTNDArray { public: POINTER_DEFINITIONS(NTNDArray); ~NTNDArray() {} static shared_pointer wrap(PVStructurePtr const & structure); static shared_pointer wrapUnsafe(PVStructurePtr const & structure); static bool is_a(StructureConstPtr const & structure); static bool isCompatible(PVStructurePtr const &pvStructure); static NTNDArrayBuilderPtr createBuilder(); PVStringPtr getDescriptor() const; bool attachTimeStamp(PVTimeStamp &pvTimeStamp) const; bool attachDataTimeStamp(PVTimeStamp &pvTimeStamp) const; bool attachAlarm(PVAlarm &pvAlarm) const; PVStructurePtr getPVStructure() const; PVUnionPtr getValue() const; PVStructurePtr getCodec() const; PVLongPtr getCompressedDataSize() const; PVLongPtr getUncompressedDataSize() const; PVStructureArrayPtr getAttribute() const; PVStructureArrayPtr getDimension() const; PVIntPtr getUniqueId() const; PVStructurePtr getDataTimeStamp() const; PVStringPtr getDescriptor() const; PVStructurePtr getTimeStamp() const; PVStructurePtr getAlarm() const; PVStructurePtr getDisplay() const; private: }where