EPICS V4 Normative Types

EPICS V4 Normative Types, Editors Draft, 18-Oct-2012

Latest version:
normativeTypes.html
This version:
normativeTypes_20121018.html
Previous version:
normativeTypes_20121008.html
Editors:
Greg White, SLAC, PSI
Bob Dalesio, BNL
James Rowland, Diamond
Marty Kraimer, BNL
Mark Rivers, APS (Invited Expert)

Abstract

This document defines a set of standard high level data types, to aid interoperability of peers at the application level of an EPICS V4 network.

The abstract type definition and function of each such standard type is described.

The data types described here are approximately equivalent to EPICS V3 Database Request types (commonly known as "DBR" types), although Normative Types extend the concept to structured data. Additionally, Normative Types may be used to define pvIOC records, or may be used purely for data exchange though the dynamic data exchange interfaces offered by EPICS V4's pvAccess and pvData modules.

For more information about EPICS, please refer to the home page of the Experimental Physics and Industrial Control System, and to the homepage of EPICS Version 4.

Status of this Document

This is the 18 Oct 2012 version of the Normative Types document. This version is a minor edit fixing the table of types. The last significant draft was the previous version which added NTURI.

Items planned but not described (ie "TODO"): Add MultiChannelVariantArray. Each optional field of each Normative type, where the option field is not in the Standard Optional Fields (so whose semantics are deliberately not defined), must be defined within the normative type. Ie, find all display and control, and define what they mean. Specify the order of all fields - we're not semi-structure any more.

See Appendix A for items that may be added to future revisions of this specification.

This version is an Editors Draft towards the First Public Working Draft. The First Public Working Draft will be intended for the EPICS community to review and comment. Resulting comments will drive subsequent revisions of the Normative Types specification and the EPICS V4 Working Group's reference implementations of software that helps create, populate and exchange Normative Type PVData.

Comments are welcome, though bear in mind this is a pre-public release version.

The terms MUST, MUST NOT, SHOULD, SHOULD NOT, REQUIRED, and MAY when highlighted (through style sheets, and in uppercase in the source) are used in accordance with RFC 2119 [RFC2119]. The term NOT REQUIRED (not defined in RFC 2119) indicates exemption.

Table of Contents


Introduction

The Normative Types described in this document are a set of software designs for high level composite data types suitable for the application level data exchange between EPICS V4 network endpoints. In particular, they are intended for use in online scientific data services. The intention is that where the endpoints in an EPICS V4 network use only Normative Types, each peer in the network should be able to understand all the data transmitted to it, at least syntactically, and be able to take processing steps appropriate to that data.

We call these types the Normative Types, to emphasise their role as the prescriptions of abstract data structures, whose role and intended semantics are described in this document, as opposed to implemented software; and that conformance to these semantics is a necessary condition for interoperability of using systems.

The EPICS version 4 module PVData bib:pvdata supplies a typing mechanism and object management API for efficiently defining, creating, accessing and updating memory resident structured data. EPICS V4 module PVAccess bib:pvaccess supports the efficient exchange of PVData defined data between EPICS V4 network peers. EPICS V4 Normative Types, defines some general purpose data types, that build on PVData. These are designed to be generally applicable to the process control, and the software applications level, of scientific instruments.

A simple example of a normative type described in this document, is the one for exchanging any single scalar value, such as one floating point number, one integer or one string. That normative type is named "NTScalar". When a client receives a PVData datum which identifies itself as being of type NTScalar, the client will know to expect that the structure which carries the NTScalar will include the scalar value in question (along with its type), and that value may accompanied up to 5 additional fields; a description of the quality in question, timeStamp, an indication of alarm severity, fields that help in how to display the value, and data about its operating limits. See the example below.

An example of a simple normative type is the NTScalar:

structure  NTScalar
    scalar_t    value
    string      descriptor  :opt 
    time_t      timeStamp   :opt
    alarm_t     alarm       :opt
    display_t   display     :opt
    control_t   control     :opt

A more complex example: If a client receives a PVData datum which identifies itself as being of type NTTable, this document specifies that it should expect the datum to contain 0 or more arrays of potentially different types. The description of NTTable in this document will say that the client should interpret the arrays as the columns of a table, and should render such a datum appropriately as a table, with row elements being taken from the same numbered elements of each array.

structure NTTable
  string[]    labels           // Very short text describing each field below, i.e. column labels
  structure value
     {scalar_t[] colname}0+  // 0 or more scalar array type
  instances, the column values.
  string      descriptor    : opt
  alarm_t     alarm         : opt
  time_t timeStamp          : opt

Description of Normative Types

All the EPICS V4 Normative Types are defined as particular structure instance definitions of a pvData structure. This is true even of the Normative Types describing simple values like a single int, since all Normative Types optionally include descriptor, alarm and timestamp. The fields of any given Ntype datum instance can be ascertained at runtime using the pvData Field introspection interface bib:pvdata.

See the Normative Type Instance Self Identificationsection below for more on how to examine a given pvData instance to see which fields it includes. That section also includes how to mark a pvData instance as a Normative Type, and how to look for that mark.

Definition: Normative Type

The Normative Types definitions in this document each have the following general form:

  1. They are defined as structures, composed of fields
  2. They usually have one primary field called "value", which encodes the most important data of the type
  3. They are composed of required fields, and optional fields. The required fields come first, the optional fields follow
  4. The order of fields matters. Although the Normative Types pvData binding allows for access though an introspection API, senders must encode the fields in the order described in this document

Linguistic conventions used in this document

A Normative Type can be used both for sending data from client to service and from service to client. In this document we refer generally to an agent, being either a client or a server. If the agent is specifically at the user's end, we call it the user agent. Client and server refer to the directionality of the transaction, server being the agent that is doing the sending.

The word "Ntype" is used as a short form of "Normative Type".

The Normative Type data descriptions are given with the syntactic conventions and grammar given below. This is a hybrid of the pvData "Meta" Language and BNF, in order to add clear distinctions between symbol types, particularly terminality, recurrence, which names a user is expected to add and which are predefined.

italics - a non-terminal. Used to stand for a choice of pvData type, or named sequence of fields, or for fields that are themselves defined as structures, and hence non-terminal. In implementation the latter will have pvData field Type structure

plaintext - terminals, either a terminal pvData type name or a label. In the case of terminal pvData type, in implementation these will be instances of pvData Field types scalar or scalarArray, eg double or int [].

name - A user provided label name. This is a kind of terminal. A programmer using the Normative Type will choose what goes in the <>.

{ } - a sequence of occurrences of the item or items in the braces. The number of occurrences is given in the following subscript, 0+ means 0 or more, 1+ means 1 or more.

The grammar for a normative type definition follows the pattern below. That is, a Normative Type is defined as a structure composed of fields. A field may be optional, and may be described along with a comment:

structure NTname
   { ( ntfield fieldName [:opt] [// comment text] ) }1+

where:

NTname
The name of the Normative Type
ntfield
One of the valid Normative Type Fields as defined below
fieldName
The identifier of the field. Where the field is a terminal in the grammar (ie, does not have <> around its name) then the fieldName is a PVData Field name, as returned by a call to getFieldName() on the Field member object. must add reference to Field, getFieldName when this interface is settled?
:opt
Indicates that the preceding field is optional in the normative type
// comment text
A field production element may be followed by a comment

Normative Type Fields

This section defines the fields that may appear in a Normative Type's definition.

Each field of a normative type ( ntfield_t ) will be one of the following:

ntfield := 

  scalar_t        // a simple numerical, boolean, or string value
| scalar_t[]      // an array of simple values
| enum_t          // an enumeration
| enum_t[]        // an array of enumerations 
| time_t          // a point in time, used for timestamps
| time_t[]        // an array of points in time
| alarm_t         // a summary diagnostic of a control system event
| alarm_t[]       // an array of summary diagnostics
| alarmlimit_t    // value thresholds for a control system diagnostic report
| alarmlimit_t[]  // an array of threshold values
| display_t       // meta data of displayed data
| display_t[]     // an array of display mata data
| control_t       // control setpoint range boundaries 
| control_t[]     // an array of control setpoint range boundaries 

Simple Normative Type Fields - scalar types

Note that of all the Normative Type fields only scalar_t is of simple type, that is, having a single or array value. All the others are represented by a structure (see Structure Normative Fields below).

scalar_t

The field is a scalar value. Scalar fields would be implemented with PVData field Type "scalar":

scalar_t :=

   boolean  // true or false 
|  byte     // 8 bit signed integer
|  ubyte    // 8 bit unsiged integer  
|  short    // 16 bit signed integer
|  ushort   // 16 bit unsigned integer 
|  int      // 32 bit signed integer
|  uint     // 32 bit unsigned integer
|  long     // 64 bit signed integer
|  ulong    // 64 bit unsigned integer
|  float    // single precision IEEE 754 
|  double   // double precision IEEE 754
|  string   // UTF-8 *

scalar_t[]

The field is an array of scalars. Scalar array fields would be implemented with PVData field Type "scalarArray":

scalar_t[] :=

   boolean[]  // array of true or false
|  byte[]     // array of 8 bit signed integer
|  ubyte[]    // array of 8 bit unsiged integer
|  short[]    // array of 16 bit signed integer
|  ushort[]   // array of 16 bit unsigned integer
|  int[]      // array of 32 bit signed integer
|  uint[]     // array of 32 bit unsigned integer
|  long[]     // array of 64 bit signed integer
|  ulong[]    // array of 64 bit unsigned integer
|  float[]    // array of single precision IEEE 754
|  double[]   // array of double precision IEEE 754
|  string[]   // array of UTF-8 *

Structured Normative Fields

This subsection defines those fields of a Normative Type structure definition, that are themselves structures or arrays of structures.

The structured normative fields would be implemented with type PVData field Type "structure" or "structureArray".

enum_t

An enum_t[] describes an enumeration. The field is a structure describing a value drawn from a given set of valid values also given. It is implemented as a pvData Field of Type "structure" with the following form:

enum_t :=

structure enum 
    int index
    string[] choices

where:

aname
The name of the structure can be any valid name.
index
The index of the current value of the enumeration in the array choices below
choices
An array of strings specifying the set of labels for the valid values of the enumeration.

enum_t[]

An enum_t[] describes an array of enumerations. The field is an array of structures each describing a value drawn from a given set of valid values also given in each. It is implemented as a PVData field of Type "structureArray" each element of which with the form of enum_t above.

time_t

A time_t describes a defined point in time. The field is a structure describing a time relative to midnight on January 1st, 1970 UTC. It is implemented as a pvData field of Type "structure" with the following form:

time_t :=

structure timeStamp
   long secsPastEpoch   
   int  nanoseconds
   int  userTag

where:

secsPastEpoch
Seconds since Jan 1, 1970 00:00:00 UTC
nanoSeconds
Nano seconds relative to the secsPastEpoch field
userTag
An integer value whose interpretation is deliberately undefined and therefore MAY be used by EPICS V4 agents in a user defined way

Interpretation: The point in time being identified by a time_t, is given by Jan 1, 1970 00:00:00 UTC plus some nanoseconds given by its secsPastEpoch times 109 plus its nanoseconds.

pvData provides two helper classes for a timeStamp structure: timeStamp, and PVTimeStamp.

time_t[]

A time_t[] describes an array of points in time. The field is an array of structures each describing a time relative to January 1st, 1970 UTC. It is implemented as a PVData field of Type "structureArray" each element of which with the form of time_t above.

alarm_t

An alarm_t describes a diagnostic of the value of a control system process variable. It indicates essentially whether the associated value is good or bad, and whether agent systems should alert people to the status of the process.

Processes in EPICS V3 and V4 IOCs include extensive support for evaluating alarm conditions. The definition of the fields in an alarm are given in bib:epicsrecref. The field is a structure describing an alarm. It is implemented as a PVData field of Type "structure" with the following form:

alarm_t :=

structure alarm
   int severity
   int status
   string message

where:

severity
severity is defined as an int (not an enum_t), but MUST be functionally interpreted as the enumeration {noAlarm, minorAlarm, majorAlarm, invalidAlarm, undefinedAlarm } indexed from noAlarm=0 bib:epicsrecref
status
status is defined as an int (not an enum_t), but MUST be functionally interpreted as the enumeration {noStatus, deviceStatus, driverStatus, recordStatus, dbStatus, confStatus, undefinedStatus, clientStatus } indexed from noStatus=0 bib:epicsrecref.
message
A message string.

Interpretation MUST be as with V3 IOC record processing, as described in the EPICS Reference Manual bib:epicsrecref.

pvData provides two helper classes for an alarm structure: alarm, and PVAlarm.

alarm_t[]

An alarm_t[] is an array of alarm conditions. The field is an array of structures each describing an alarm condition. It is implemented as a PVData field of Type "structureArray" each element of which with the form of alarm_t above.

alarmlimit_t

An alarmlimit_t is a structure that gives the numeric intervals to be used for the high and low limit ranges of an associated limit type alarm. The specific instance of the alarm to which the alarmlimit refers, is not specified in the alarmlimit structure, it may be any EPICS alarm. alarmlimit_t is implemented as a PVData field of Type "structure" with the following form:

alarmlimit_t :=

structure alarmlimit
    double highalarm
    double highwarning
    double lowwarning
    double lowalarm
 

where:

alarmlimit
The structure must have the name "alarmlimit".
highalarm
Upper bound of allowed operating range of the value to which the alarmlimit refers
highwarning
Upper bound of normal operating range of the value to which the alarmlimit refers
lowwarning
Lower bound of normal operating range of the value to which the alarmlimit refers
lowalarm
Lower bound of allowed operating range of the value to which the alarmlimit refers.

The interpretation is that where the Normative Type instance's value field is:

Since the above conditions do not at all form a three valued function over all possible values of the limits, the invariant lowalarm ≤ lowwarning ≤ highwarning ≤ highalarm SHOULD be observed when setting the those thresholds.

Code in both V3 IOC record support and in V4 IOC raises alarms based on how the alarm limits are valued according to the following algorithm:

If the value is >= highalarm then a major alarm is raised
else if value>=highwarning then a minor alarm is raised
else if value<= lowalarm then a major alarm is issued
else if value<=lowwarning then a minor alarm is raised
else do not raise an alarm.

Where an alarmlimit_t structure instance is present in a Normative Type structure, it MUST be interpreted as referring to that Normative Type's field named "value". Therefore it is only used in Normative Types that have a single numeric "value" field.

alarmlimit_t[]

An alarmlimit_t[] is an array of alarm limit conditions. The field is an array of structures each describing an alarm limit. It is implemented as a PVData field of Type "structureArray" each element of which with the form of alarmlimit_t above.

display_t

A display_t is a structure that describes some typical attributes of a numerical value that are of interest when displaying the value on a computer screen or similar medium. The units field SHOULD contain a string representation of the physical units for the value, if any. The description field SHOULD contain a short (one-line) description of what the value represents, such as can be used as a label in a display. The fields lowlimit and highlimit represent the range in between which the value should be presented as adjustable.

The field is a structure describing a display_t. It is implemented as a PVData field of Type "structure" with the following form:

display_t :=

structure display
    double lowlimit
    double highlimit
    string description
    string format
    string units
 

where:

display
The structure must have the name "display".
lowlimit
The lower bound of range within which the value must be set, to be presented to a user
highlimit
The upper bound of range within which the value must be set, to be presented to a user
description
A textual summary of the variable that the value quantifies
format
A format for converting the value field to a string Needs work: What is display.format? What's it for and what are examples? If it's a sprintf pattern, which syntax must it conform to - C or Java?
units
The units for the value field.

Where an display_t structure instance is present in a Normative Type structure, it MUST be interpreted as referring to that Normative Type's field named "value". Therefore it is only used in Normative Types that have a single numeric "value" field.

display_t[]

A display_t[] is an array of display_t. The field is an array of structures each describing the display media oriented metadata of some corresponding process variable value, as described by display_t above. It is implemented as a PVData field of Type "structureArray" each element of which with the form of display_t above.

control_t

An control_t is a structure that describes a range, given by the interval (limitlow,limithigh), within which it is expected some control software or hardware shall bind the control PV to which this Normative Type instance's value field refers.

The field is a structure describing a control_t. It is implemented as a PVData field of Type "structure" with the following form:

control_t :=

structure control
        double lowlimit
        double highlimit

where:

control
The structure must have the name "control" array.
lowlimit
The control low limit for the value field
highlimit
The control high limit for the value field.

control_t[]

A control_t[] is an array of control_t. The field is an array of structures each describing the setpoint range interval of some process variable. It is implemented as a PVData field of Type "structureArray" each element of which with the form of control_t above.

Normative Type Meta Data

Meta data are included in runtime instances of Normative Types. The meta data includes to which Normative Type the structure instance conforms, version information, and other data to aid efficient processing, diagnostics and displays.

Normative Type Instance Self Identification

Normative Type instance data MUST identify themselves as such by including a string in a well known part of their pvData instance datum (see below), that encodes an identifier of the Normative Type to which they conform. This is the Normative Type Identifier, or "Ntype identifier" string for short. Ntype identifiers have the syntax <namespace-name>:<type-name>. There are two parts to this Ntype identifier:

Namespace Name
The namespace has three roles. The first is the familiar one of simply distinguishing data that are named with the names of EPICS V4 normative types from names that are lexically identical but have a role outside the context of EPICS V4. The second is to give a string which distinguishes the maturity version of the Normative Types definition document (this document) which was used to define the normative type being identified. The third is to provide a basis for extending types. However, at present, in this draft, the mechanism of that type extension system is not defined.
Type Name
The name of the Normative Type to which the datum conforms, as it appears in this document.

A Normative Type Identifier MUST be considered to be "case sensitive."

The Namespace Name corresponding to this draft of the normative types document is:

 uri:ev4:nt/2012/pwd

The normative list of the Normative Type Identifiers corresponding to this draft of the EPICS V4 Normative Types specification document (this document), is given in Appendix B.

As an example, one of the simplest normative types is NTScalar. It has formal Type Name "NTScalar" (see Appendix B). Therefore, the Normative Type Identifier for an NTScalar, is uri:ev4:nt/2012/pwd:NTScalar.

At present it is envisaged that the same namespace value shall be used for all versions of this document prior to Recommendation, including all Public Working Drafts of this document and those marked Last Call or similar.

pvAccess binding type identification

In the EPICS v4 pvData/pvAccess binding, the structure identification string (ID) of pvData structures is used to communicate the Normative Type of the datum carried by the pvData structure. Every pvData datum which is intended to conform to a normative type, MUST identify the normative type to which it conforms through its ID field. Its ID field MUST have the value of its Normative Type Identifier. For instance, a pvData structure conforming to NTScalar, must have ID field equal to "uri:ev4:nt/2012/pwd:NTScalar". Every EPICS V4 agent which is encoding or decoding pvData data that is described by normative types, SHOULD examine the ID field of such data, to establish the normative type to which each datum conforms.

Example pvAccess/pvData binding

Recall that in the pvData system, data variables are constructed in two equally important parts; the introspection interface, in which data types are defined, and the data interface, in which instance variables are created and populated. The introspection interface can be used to examine an existing instance, to see what fields it posses. Getting and setting values, is done through the data interface. As a programmer, you have to define both parts, the introspection interface of your type, and its data interface. Both the data and the introspection interfaces are exchanged by pvAccess. That is, when a sender constructs a data type, such as one conforming to an Normative Type, plus an instance of that type, and it sends the instance to a receiver, the receiver can check that the instance indeed contains the member fields it should find for that type, using the type's introspection interface.

The following Java code snippets give an example of the use of a pvData structure of Normative Type NTScalar, as defined below. in this example we show code as may be included in a trivial "multiplier" service, and a client of the multiplier service.

Sender

The sender typically first creates an introspection definition, using the pvData introspection interfaces (Field, Structure etc). It then creates an instance of the type and populates it with the pvData data interfaces (PVField, PVstructure etc).

Example of creating the introspection interface of an NTScalar, as may be done on a server that will be returning one. In this example, only one of the optional fields of NTScalar, named "descriptor" is included, along with the required field named "value".

   // Create the data type definition, using the pvData introspection interface (Structure etc).
   FieldCreate fieldCreate = FieldFactory.getFieldCreate();
   Structure resultStructure = fieldCreate.createStructure( "uri:ev4:nt/2012/pwd:NTScalar", 
       new String[] { "value", "descriptor" },
       new Field[] { fieldCreate.createScalar(ScalarType.pvDouble),
 		     fieldCreate.createScalar(ScalarType.pvString) } );

Subsequently, the sender would create an instance of the type, and populate it.

Example of creating an instance and data interface of an NTScalar, as may be done on a data server, and populating it.

   // If a and b were arguments to this service, the following creates an instance of
   // a resultStructure, which conforms to the NTScalar normative type definition,
   // and populates it. It would then return this PVStructure instance.  
   PVStructure result = PVDataFactory.getPVDataCreate().createPVStructure(resultStructure);
   result.getDoubleField("value").put(a * b);
   result.getStringField("descriptor").put("The product of arguments a and b");

The PVStructure instance, in the example called "result" would be returned to the receiver.

Receiver

Having in some way done a pvaccess get, the receiver could simply extract the primary value:

   PVStructure result = easyPVA.createChannel("multiplierService").createRPC().request(request);
   double product = result.getDoubleField("value").get();

A well written receiver would check that the introspection interface (Structure etc) says that the received instance is indeed of the type it expects. It may extract the data fields individually, checking their type. Importantly, it can also see which optional fields it received, before attempting to access them. Here is a more complete receiver example for the NTScalar sent above. This code might be in the client side of the Multiplier service.

Example of a receiver of an NTScalar. The example checks that the returned pvData datum was an instance of an NTScalar, extracts the required value field, and then, if it's present, extracts the optional "descriptor" field.

   // Call the multiplier service sending the request in a structure 
   PVStructure result = easyPVA.createChannel("multiplierService").createRPC().request(request);

   // Examine the returned structure via its introspection interface, to check whether its
   // identifier says that it is a normative type, and the type we expected.
   if (!result.getStructure().getID().equals("uri:ev4:nt/2012/pwd:NTScalar")) 
   {
       System.err.println("Unexpected data identifier returned from multiplierService: " + 
          "Expected Normative Type ID uri:ev4:nt/2012/pwd:NTScalar, but got "
          + result.getStructure().getID());
       System.exit(-1);
   }
  
   // Get and print the required value member field as a Double. 
   System.out.println( "value = " + result.getDoubleField("value").get());

   // See if there was also the descriptor subField, and if so, get it and print it.
   PVString descriptorpv = (PVString)result.getSubField("descriptor");
   if ( descriptorpv != null)
      System.out.println( "descriptor = " + descriptorpv.get());

   // Or just print everything we got:
   System.out.println("\nWhole result structure toString =\n" + result);

Future of type identification

In future drafts of this specification, a pattern to create extensions to the EPICS V4 Normative Types may be presented. It may be based on a formalized link to the XML namespace and XML Schema system, whereby the namespace part of the Normative Type Identifier of a datum whose type is an extension of one of these Normative Types, is replaced by another namespace that extends this one through an XML Schema out of band. In that case, the type name part would identify a type in that other namespace, though it may extend a type in this namespace.

Standard optional meta data fields

All of the Normative Types defined below, optionally include a descriptor, alarm and timeStamp field. There is no required interpretation of these fields, and therefore their meaning is not further described in the Normative Type definitions. Additionally, Normative Types may have other optional fields, as defined individually below.

Optional Descriptor field

An object of Normative Type may optionally include a field named "descriptor" and of type string, to be used to give identity, name, or sense information. For instance, it may be valued with the name of a device associated with control data, or the run number of a table of model data.

string descriptor  :opt     // Contextual information 

Optional alarm field

An object of Normative Type may optionally include an alarm field.

alarm_t alarm      :opt     // Control system event summary

Optional timeStamp field

An object of Normative Type may optionally include a timeStamp field.

time_t timeStamp   :opt     // Event time

General Normative Types

The General Normative Types are for encapsulating data of any kind of application or use case. Compare to Specific Normative Types defined later in this document, and which are oriented to particular use cases.

NTScalar

NTScalar is the EPICS V4 Normative Type that describes a single scalar value plus metadata:

structure  NTScalar
    scalar_t    value
    string      descriptor  :opt 
    time_t      timeStamp   :opt
    alarm_t     alarm       :opt
    display_t   display     :opt
    control_t   control     :opt

where:

value
The primary data carried by the NTScalar object. The field must be named "value" and can be of any simple scalar type as defined above.

NTScalarArray

NTScalarArray is the EPICS V4 Normative Type that describes an array of values, plus metadata. All the elements of the array of the same scalar type.

structure  NTScalarArray
    scalar_t[]  value
    string      descriptor  :opt 
    time_t      timeStamp   :opt
    alarm_t     alarm       :opt
    display_t   display     :opt
    control_t   control     :opt

where:

value
The primary data carried by the NTScalarArray object. The field must be named "value" and can be of any scalar array type as defined above.

NTEnum

NTEnum is an EPICS V4 Normative Type that describes an enumeration (a closed set of possible values each described by an n-tuple).

structure NTEnum
    enum_t      value
    string[]    longdescriptions         :opt
    string      descriptor  :opt
    time_t      timeStamp   :opt
    alarm_t     alarm       :opt

where:

value
The primary data carried by the NTEnum object. The field must be named "value" and must be an enumeration as defined above.
longdescriptions
Text which may be used to add context and information for each choice, such as may be used in displays. If given, longdescriptions MUST be an array of strings of length equal to values.choices. Each element of the array SHOULD describe the ordinally corresponding values.choices element. For instance, if the NTEnum's value.index is valued 1, and longdescriptions is given, then longdescriptions[1] MUST contain a string meaningfully describing value.choice[1].

NTMatrix

NTMatrix is an EPICS V4 Normative Type used to define a matrix, specifically a 2-dimensional array of real numbers.

structure NTMatrix
    double[]  value
    int[2]       dim         :opt
    string      descriptor  :opt
    time_t      timeStamp   :opt
    alarm_t     alarm       :opt
    display_t   display     :opt

where:

value
The numerical data comprising the matrix. The value is given as a single array of doubles. When value holds the data of a matrix, rather than a vector, then the data MUST be layed out in "row major order"; that is, all the elements of the first row, then all the elements of the second row, and so on. For instance, where NTMatrix represented a 6x6 matrix, element (1,2) of the matrix would be in the 2nd element of value, and element (3,4) would be in the 16th element.
dim
dim indicates the dimensions of the matrix. If dim is not present, value MUST be interpreted as a vector, of length equal to the number of elements of value. If dim is present, then it must have 1 or 2 elements; its one element value or both elements values MUST be > 0, and the number of elements in value MUST be equal to the product of the elements of dim. If dim is present and contains a single element, then the NTMatrix MUST be interpreted as describing a vector. A dim of 2 elements describes a matrix, where the first element of dim gives the number of rows, and the second element of dim gives the number columns. If dim is present and contains 2 elements, of which the first is unity, and the second is not (therefore is >1) then the NTMatrix MUST be interpreted as describing a row vector. If dim is present as contains 2 elements, of which the second is unity, and the first is not (therefore is >1) then the NTMatrix MUST be interpreted as describing a column vector.

User agents that print or otherwise render an NTMarix SHOULD print row vector, column vector, and non-vector matrices appropriately.

NTVariantArray

NTVariantArray is an EPICS V4 Normative Type to define a single structure which contains an number of arrays, each of different type, but where the value of the NTVariantArray as a whole is taken to be the value of only one of the arrays at a time. In that way, it can be used to encode data in arrays whose type may be changed according to runtime conditions and the data to be expressed.

NTVariantArray is defined with arrays of each pvData scalar type. At any particular time its value MUST be interpreted to be only one of these arrays. The dataType member specifies which array MUST be taken to be the NTVariantArray's type. The data arrays need not be all the same length. Arrays other than that presently selected by dataType MAY be populated; in this way dataType can be used as a value selector.

structure NTVariantArray
    int dataType                  // Identifies which scalar array defines the present value
    boolean [] booleanValue       // Defines the NTVariantArray's value if dataType == 0
    byte [] byteValue             // Defines the NTVariantArray's value if dataType == 1 
    short [] shortValue           // Defines the NTVariantArray's value if dataType == 2
    int [] intValue               // Defines the NTVariantArray's value if dataType == 3
    long [] longValue             // Defines the NTVariantArray's value if dataType == 4
    float [] floatValue           // Defines the NTVariantArray's value if dataType == 5
    double [] doubleValue         // Defines the NTVariantArray's value if dataType == 6
    string [] stringValue         // Defines the NTVariantArray's value if dataType == 7
    time_t[] timeStampValue       // Defines the NTVariantArray's value if dataType == 8
    alarm_t [] alarmValue         // Defines the NTVariantArray's value if dataType == 9
    string      descriptor  :opt
    time_t      timeStamp   :opt
    alarm_t     alarm       :opt
    display_t   display     :opt 

where:

dataType
This defines that data type for the column. It is one of:
0 - booleanValue
1 - byteValue
2 - shortValue
3 - intValue
4 - longValue
5 - floatValue
6 - doubleValue
7 - stringValue
8 - timeStampValue
9 - alarmValue
       
booleanValue,...,alarmValue
The arrays that may be used to hold data. The array indicated by dataTypeis that one which defines the NTVariantArray's value.

NTURI

NTURI is the EPICS V4 Normative Type that describes a Uniform Resource Identifier (URI) bib:uri. Specifically, NTURI carries the four parts of a "Generic URI", as described in bib:uri as the subset of URI that share a common syntax for representing hierarchical relationships within the namespace. As such, NTURI is intended to be able to encode any generic URI sheme's data. However, NTURI's primary purpose in the context of EPICS, is to offer a well formed and standard compliant way that EPICS agents can make a request for an identified resource from a channel, especially an EPICS V4 RPC channel. See ChannelRPC.

The "pva" scheme is introduced here for EPICS V4 interactions. The pva scheme implies but does not require use of the pvaccess protocol. A scheme description for Channel Access (implying the ca protcol) will be added later. What follows is a description of the syntax and semantics for the pva scheme.

structure NTURI  
   string scheme      
   string authority   : opt  
   string path     
   structure query    : opt  
      {string | double | int <field-name>}0+ 
   {<field-type> <field-name>}0+

Interpretation of NTURI under the "pva" scheme

The following describes how the fields of the NTURI must be interpretted when the scheme is "pva":

scheme
The scheme name must be given. For the pva scheme, the scheme name is "pva". The pva scheme implies but does not require use of the pvaccess protocol.
authority
If given, then the IP name or address of an EPICS network pvaccess or channel access server
path
The path gives the channel from which data is being requested. "path" is the only required field of NTURI
query
A name value system for passing parameters. The types of the argument value MUST be drawn from the following restricted set of scalar types: double, int, or string.
<field-type>
Zero or more pvData Fields whose type are not defined until runtime, may be added to an NTURI by an agent creating an NTURI. This is the mechanism by which complex data may be sent to a channel. For instance a table of magnet setpoints.

The channel name given in the path MAY BE the name of an RPC channel. In that case, it's important to note that this specification makes no normative statement about where in the NTURI is encoded the name of the entity about which the RPC service is being called. For instance, an archive service, that gives the historical values of channels, may advertise itself as being on a single channel called say "archiveservice" (so the NTURI path field in that case would be set to "archiveservice", and in that case, the name of the EPICS channel about which archive data is wanted might well be encoded into one of the NTURI's query field parameters. Alternatively, the archive service might advertise a number of channels, each named perhaps after the channels whose historical data is being requested. For instance, a path may be "quad45:bdes;history", if that was the name of one of the channels offered by the archive service. An example of this second form is given below.

Use of NTURI may be explained by example. The following is an example client side of Channel RPC exchange, where a notional archive service, is asked for the data for a PV between two points in time. In this example, the archive service is advertising the channel name "quad45:bdes;history". Presumably, that service knows the archive history of a (second) channel, named probably, "quad45:bdes".

Construct the introspection interface (ie type definition) of the NTURI conformant structure that will be used to make requests to the archive service.

// Construct an NTURI for making a request to a service that understands 
// query arguments named "starttime" and "endtime".
FieldCreate fieldCreate = FieldFactory.getFieldCreate();
Structure queryStructure = fieldCreate.createStructure(
    new String[] {"starttime", "endtime"},
    new Field[] { fieldCreate.createScalar(ScalarType.pvString),
                  fieldCreate.createScalar(ScalarType.pvString)});
Structure uriStructure =
    fieldCreate.createStructure("uri:ev4:nt/2012/pwd:NTURI",
         new String[] { "path", "query" },
         new Field[] { fieldCreate.createScalar(ScalarType.pvString), 
                       queryStructure } );

Populate our uriStructure (conformant to NTURI) with a specific request.

// Get a EasyPVA singleton.
EasyPVA easyPVA = EasyPVAFactory.get();

// Construct an NTURI with which to ask for the archive data of quad45:bdes
PVStructure request = PVDataFactory.getPVDataCreate().
	createPVStructure(uriStructure);
request.getStringField("path").put("quad45:bdes;history");
PVStructure query = request.getStructureField("query");
query.getStringField("starttime").put("2011-09-16T02.12.55");
query.getStringField("endtime").put("2011-09-16T10.01.03");
		
// Ask for the data, using the NTURI
PVStructure result = easyPVA.createChannel(request.getStringField("path").get()).createRPC().request(request);
if ( result != null )
    System.out.println("The URI request structure:\n" + request
		+"\n\nResulted in:\n" + result);

The server side is not illustrated, but clearly its code would have registered a number of ChannelRPC services, each named after the PV whose historical data it offered.

NTNameValue

NTNameValue is the EPICS V4 Normative Type that describes a system of name and scalar values.

For the related problem of expressing a key-value system where each value may be array valued, see NTVariantArray or NTTable.

Use cases: In a school, a single NTNamedValue might describe the grades from a number of classes for for one student.

structure NTNameValue
   string[]          name
   scalar_t[]        value   
   string            descriptor :opt
   time_t            timeStamp  :opt
   alarm_t           alarm      :opt

where:

name
The keys associated with the value field. Each element of name identifies the same indexed element of the value field, using a string label.
value
The data values, each element of which is associated with the correspondingly indexed element of the name field.

Each name (or "key") in the array of names, MUST be interpreted as being associated with its same indexed element of the value array.

NTTable

NTTable is the EPICS V4 Normative Type for "2-d" tabular datasets.

An NTTable is made up of a number of arrays, each array being of a scalar type. Each array can be thought of as a column. Each ith array member makes up one row, or n-tuple.

Use case examples: a table of twiss paramaters of all lattice elements in an accelerator section. Another example, where the columns might vary call-to-call would be that of an EPICS V4 SQL database service. In that example one NTTable returned by the service would contain all the tabular results of a SQL SELECT, essentially a recoded JDBC or ODBC ResultSet - see the rdbservice.

structure NTTable
  string[]  labels             // Very short text describing each field below, i.e. column labels
  structure value
     {scalar_t[] colname}0+  // 0 or more scalar array instances, the column values.
  string      descriptor    : opt
  alarm_t     alarm         : opt
  time_t timeStamp          : opt

where:

labels
The table column headings of each column, each heading given as one element of the array of strings. The order of labels MUST match the intended order of the scalar_t[] data
value
The data of the table are encoded in a structure named "value" (that is, the pvData binding, whose field name is "value"). We call the columnar data Field "value" (rather than for instance "columndata") so that the primary field of the type is named the same for all normative types, and so to help general purpose clients identify the primary field.

Interpretation

This represents a table. The number of "columns" is equal to the number of fields which follows field "labels." Each colname scalar array field contains the data for the "column" corresponding to the same indexed element of the labels field. The value of each element of labels SHOULD be used as a column heading for the corresponding colname field.

Note that the above description is given in terms of a table and its columns, but there is nothing specifically columnar about how this data may be rendered. A user may choose to print the fields row wise. For instance, if there are many fields, but each has only length 1 or 2. E.g., if you wanted to give all the scalar data related to one device, then you might use an NTTable rendered in such a way. Note that one column of a table would also be easily described by NTNameValue.

Validation

The number of scalar_t[] fields in the value structure, and the length of labels MUST be the same. All scalar_t[] fields in the value structure, MUST have the same length, being the number of "rows" in the table. No array field within the value structure may itelf be named "value".

Specific Normative Types

The "specific normative types" below are types oriented towards application level scientific and engineering use cases. Compare to General Normative Types defined above. The currently defined types are each described in a section below.

Unless otherwise stated:

NTMultichannelArray

MultichannelArray is an EPICS V4 Normative Type that aggregates an array of scalar values from different EPICS Process Variable (PV) channel sources, into a single variable.

Use cases; in a particle accelerator, a single NTMultichannelArray might include the data of a number of Beam Positon Monitors' X offset values, or of a number of quadrupoles' desired field values.

structure NTMultichannelArray
  scalar_t[]  value               // The channel values
  string[]    PVnames             // Process Variable names
  time_t      timeStamp           // Base value time stamp 
  int[]       severities     :opt // Alarm severity associated with each value
  double[]    positions      :opt // The position of each value element
  double[]    deltaTimes     :opt // The time relative to the timeStamp, in seconds 
  string      descriptor     :opt
  alarm_t     alarm          :opt

where:

value
The array of values of the EPICS Process Variables
PVnames
The names of each of the EPICS Process Variables that sourced each of corresponding element of the value field
timeStamp
The base time stamp associated with values as a whole. See also deltaTimes field
severities
The EPICS alarm severity associated with each value
positions
A location (such as Z or S position) or cardinal value associated with each element of the value array
deltaTimes
The difference in seconds between the time that each corresponding element of the value array was read, and the timeStamp field.
alarm
The alarm of the NTMultiChannelArray as a whole. The association of the values in the severities field and the alarm field is not defined since the alarm field refers explicitly to the value field and so not necessarily to the severities field (although those are likely to be related through record processing).

The above descriptions of the optional fields, pertain in particular to when a NTMultichannelArray expresses measured values, but a NTMultichannelArray can be used to express desired values or setpoint values too.

NTContinuum

NTContinuum is the EPICS V4 Normative Type used to express a sequence of point values in time or frequency domain. Each point has N values (N>=1) and an additional value which describes the index of the list. The additional value is carried in the 'base' field. The 'value' field carries the values which make up the point in index order.

An additional 'units' field gives a units string for the N values and the additional value.

structure NTcontinuum
  double[] base
  double[] value
  string[] units
  string      descriptor    :opt
  alarm_t     alarm         :opt
  time_t      timeStamp     :opt

The number of values in a point must be derived as:

Nvals = len(value)/len(base)

And the following invariant must be preserved:

len(units)-1 == Nvals

The order of the point (A, B, C) for indices 1, 2, 3 the order of the 'value' array is:

[A1, B1, C1, A2, B2, C2, A3, B3, C3]

NTHistogram

NTHistogram is the EPICS V4 Normative Type used to encode the data and representation of a (1 dimensional) histogram. Specifically, it encapsulates frequency binned data.

For 2d histograms (i.e. both x and y observations are binned) and n-tuple data (e.g. land masses of different listed countries) see NTMatrix or NTTable.

structure NTHistogram
  double []  ranges                     // The start and end points of each bin 
  (short[] | int[] | long[])  value     // The frequency count, or otherwise value, of each bin
  string      descriptor    :opt
  alarm_t     alarm         :opt
  time_t      timeStamp     :opt

Interpretation

One NTHistogram gives the information required to convey a histogram representation of some underlying observations. It does not convey the values of each of the observations themselves.

The number of bins is given by the length of the value array. ranges indicates the low value and high value of each bin. The range for bin(i) is given by ranges(i) to ranges(i+1). Specifically, since we want end points of both the first bin and last bin included, all bin intervals except the last one, MUST be right half open; from that bin's low value ranges(i) (included) to that bin's high value ranges(i+1) (excluded). The last bin MUST be fully open (low and high value included).

A log plot histogram (in which the independent variable x is binned on a log scale), would be communicated using a range array of decades (1.0E01, 1.0E02, 1.0E03 etc).

Validation

The array length of range MUST be the array length of value + 1.

NTAggregate

NTAggregate is the EPICS V4 Normative Type to compactly convey data which combines several measurements or observation. NTAggregate gives simple summary statistic bib:agg about the central tendency and dispersion of a set of data points.

Use cases: for instance, an NTAggregate could be used to summarize the value of one beam position offset reading over some number of pulses (N). It also includes the time range of the sampled points, so it could be used for time domain rebasing. For instance, an FPGA sending data at 10KHz, and you want to display its output, but you don't want to display at the native rate. Also, it could be used for transmitting or storing compressed archive data.

NTAggregate doesn't cover the shape of a distribution so it only reasonably helps you do symmetrical distributions (no skewness or kurtosis), and it doesn't include any help for indicating the extent of dependency on another variable (correlation).

structure NTAggregate
  double      value                // The center point of the observations,
                                   // nominally the mean.         
  long        N                    // Number of observations
  double      dispersion      opt  // Dispersion of observations;
                                   // nominally the Standard Deviation or RMS
  double      first           opt  // Initial observation value 
  time_t      firstTimeStamp  opt  // Time of initial observation
  double      last            opt  // Final observation value
  time_t      lastTimeStamp   opt  // Time of final observation
  double      max             opt  // Highest value in the N observations
  double      min             opt  // Lowest value in the N observations
  string      descriptor      opt  
  alarm_t     alarm           opt  
  time_t      timeStamp       opt

Where:

value
The summary statistic of the set of observations conveyed by this NTAggregate. For instance their arithemtic mean.
N
The number of observations summarized by this NTAggregate.
dispersion
The extent to which the observations are centered around the value. For instance, if the value contains a mean, then the dispersion may be the variance or the standard deviation. The descriptor should indicate which.
first
The value of the temporally first observation conveyed by this NTAggregate
firstTimeStamp
The time of observation of the temporally first observation conveyed by this NTAggregate
last
The value of the temporally final observation conveyed by this NTAggregate
lastTimeStamp
The time of observation of the temporally final observation conveyed by this NTAggregate
max
The numerically largest value in the set of observations conveyed by this NTAggregate
min
The numerically smallest value in the set of observations conveyed by this NTAggregate

Interpretation

One NTAggregate instance describes some number (given by N) of observations. If firstTimeStamp and lastTimeStamp are given, then the N observations MUST have been taken over the period of time specified. If first, last, max or min are given, they MUST refer to the actual values of the N observations being summarized.

The value field value computed by server agents may be the arithmetic mean of the observation data being summarized by this NTAggregate, but NTAggregate does not normatively define that. Other measures of mean (geometric, harmonic) may be assigned. Indeed other measures of central tendency may be used. The interpretation to give an instance of an NTAggregate SHOULD be conveyed in the descriptor.

Where dispersion is a measure of the standard deviation, which estimator of the standard deviation [1/N or 1/(N-1)] was used, is also not defined normatively.

NTImage

NTImage is the EPICS V4 Normative Type to express image data, particularly camera images. One NTImage gives one frame.

The EPICS V3 image type is provided by areaDetector. See the NDArray class declaration for details of the image properties. The EPICS V4 image type (NTImage) is a superset of this functionality.

Byte [] data may contain a compressed image so the size may not be at least prod(dim) * element_size(datatype).

An NTImage is composed of three parts:

structure NTImage
    Arraypart
    Imagepart
    Metadatapart

Each of these will be discussed separately.

NTImage Array Part

The Arraypart of an NTImage is composed of the following fields:

   (boolean [] | byte[] | short[] | int[] | long[] | float[] | double[])  value
    int[]       dim
    string      descriptor  :opt
    time_t timeStamp        :opt
    alarm_t     alarm       :opt
    display_t   display     :opt

These fields are the same as for NTMatrix defined previously.

A generic tool that operates on NTMatrixs will be able to use the image as long as compression is not used.

NTImage Image Part

The Imagepart of an NTImage is composed of the following fields:

    int colorMode 
    int bayerPattern
    char [4] fourcc 
    int [] offset // same length as dim, start of readout
    int [] binning
    int [] reverse
    int [] fullDim

where:

colorMode
This is one of the following:
NDColorModeMono = 0,    /** Monochromatic image */
NDColorModeBayer = 1,   /** Bayer pattern image,
                            1 value per pixel but with color filter on detector */
NDColorModeRGB1 = 2,    /** RGB image with pixel color interleave,
                            data array is [3, NX, NY] */
NDColorModeRGB2 = 3,    /** RGB image with row color interleave,
                            data array is [NX, 3, NY]  */
NDColorModeRGB3 = 4,    /** RGB image with plane color interleave,
                            data array is [NX, NY, 3]  */
NDColorModeYUV444 = 5,  /** YUV image, 3 bytes encodes 1 RGB pixel */
NDColorModeYUV422 = 6,  /** YUV image, 4 bytes encodes 2 RGB pixel */
NDColorModeYUV411 = 7   /** YUV image, 6 bytes encodes 4 RGB pixels */
       
bayerPattern
This is one of the following:
NDBayerRGGB        = 0,    /** First line RGRG, second line GBGB... */
NDBayerGBRG        = 1,    /** First line GBGB, second line RGRG... */
NDBayerGRBG        = 2,    /** First line GRGR, second line BGBG... */
NDBayerBGGR        = 3     /** First line BGBG, second line GRGR... */
       
fourcc
Identifies codec in case of compressed data. "JPEG", for example. List of codecs
offset
Offset for each dimension.
binning
The binning (pixel summation, 1=no binning) relative to original data source
reverse
The orientation (0=normal, 1=reversed) relative to the original data source
fullDim
The size of each dimension. This may be a chunk of metadata part

NTImage Metadata Part

The Metadatapart of an NTImage is composed of the following fields:

    int uniqueId
    string [] attributeDescriptions
    int [] attributeSourceTypes
    string [] attributeSources
    NTVariantArray [] attributes

where:

uniqueId
A number that must be unique for all NDArrays produced by a driver after it has started
attributeDescriptions
A description of the attribute.
attributeSourceTypes
NDAttrSourceDriver = 0,  /** Attribute is obtained directly from driver */
NDAttrSourceParam,   /** Attribute is obtained from parameter library */
NDAttrSourceEPICSPV  /** Attribute is obtained from an EPICS PV */
      
attributeSources
Source string - EPICS PV name or DRV_INFO string
attributes
The "table" for each attribute. Defined by an array of NTVariantArray.

Appendix A: Possible Future Additions to this Specification

The following types may be added to this specification, following further refinement and according to feedback to this draft. Comments welcome on these definitions or alternatives.

anydata_t

anydata_t describes a pvData structure that contains an array of elements, each of which may be a scalar array or structure array. Such structures would then be able to transport an essentially unlimited variety of data. However, the use of anydata_t in a Normative Type's specification would considerably complicate agent implementations that may receive instances of those Normative Types.

anydata_t :=
structure 
  {  scalar_t[] <name> | structure_t[] <name> }1+  

NTAny

NTAny would be a Normative Type for interoperation of essentially data structure, plus description, alarm and timeStamp.

structure NTAny  
  string      description      : opt
  time_t      timeStamp     : opt
  alarm_t     alarm         : opt
  string[]    label         : opt
  anydata_t value

NTSnapShot

NTSnapshot would be the Normative Type for interoperation of EPICS V4 snapshot and configuration services, such as MASAR, with their clients.

structure NTSnapshotData             // snapshot data [that may inc waveform ]
   time_t timeStamp                  // time of snapshot
    time_t      timeStamp   :opt
    alarm_t     alarm       :opt
   string[] channelNames
   alarm_t[] alarms                  // Alarm of each data value
   anydata_t value

Maybe rather than anydata_t here, we should say any Normative Type instance? That would usefully constrain the potential types agents must implement.

NTArchive

NTArchive would be the Normative Type for interoperation of EPICS V4 capable archive services, with their clients.

structure NTArchivedata
   string channelName                 // EPICS channel name
   time_t[] timeStamps                // Timestamps of each sample
   alarm_t[] alarms                
   anydata_t value                    

Maybe rather than anydata_t here, we should say any Normative Type instance? That would usefully constrain the potential types agents must implement.

Appendix B: Normative Type Identifiers

This Appendix normatively describes the Normative Type Identifiers of the abstract data types defined by this document. It gives the namespace value as it MUST appear in the "Namespace Name" part of the Normative Type Identifier, and it gives the type names as they MUST appear in the "Type Name" part of a Normative Type Identifier. These identifier part values MUST be considered case sensitive.

The Normative Type Identifier "Namespace Name" part, corresponding to this draft of the Normative Types Document (this document), is:

    uri:ev4:nt/2012/pwd
    

The Normative Type Identifier "Type Name" part corresponding to this draft of the Normative Types Document (this document), MUST be valued only as one of the following:

Type Names that may be used in the Type Name part of a Normative Type Identifier of an EPICS V4 Normative Type in the namespace of this draft of the Normative Types specification
Type Name Short Description
NTScalar A single scalar value
NTScalarArray An array of scalar values of some single type. Compare with NTVariantArray
NTEnum An enumeration list and a value of that enumeration
NTMatrix A real number matrix
NTVariantArray An array of some scalar type, where the type and values may be changed
NTURI A structure for encapsulating a Uniform Resource Identifier (URI)
NTNameValue An array of scalar values where each element is named
NTTable A table of scalars, where each column may be of different scalar array type
NTMultichannelArray An array of PV names, their values, and metadata
NTContinuum Expersses a sequence of data points in time or frequency domain
NTHistogram An array of real number intervals, and their frequency counts. Expresses a 1D histogram.
NTAggregate A mean value, standard deviation, and other meta data. Expresses the central tendency and dispersion of a set of data points
NTImage A general purpose pixel and meta data type, to encode image data of a single picture frame.

Following drafts of this document MAY well correspond to the same Namespace Name and Type Names as used in this draft. Note that the same namespace may well be used for a different collection of types or Type Names, as this document matures.

Bibliography

[bib:pvdata]
EPICS V4 Developer's page, pvData section
[bib:pvaccess]
EPICS V4 Developer's page, pvAccess section
[bib:epicsrecref]
EPICS Reference Manual, Philip Stanley, Janet Anderson, Marty Kraimer, APS, http://www.aps.anl.gov/epics/EpicsDocumentation/AppDevManuals/RecordRef/Recordref-1.html
[bib:epicsappdev]
EPICS Input / Output Controller (IOC) Application Developer's Guide Marty Kraimer, APS, 1994, http://www.aps.anl.gov/epics/EpicsDocumentation/AppDevManuals/AppDevGuide/3.12BookFiles/AppDevGuide.book.html
bib:agg
Aggregate data, Wikipedia article, http://en.wikipedia.org/wiki/Aggregate_data
bib:rdbservice
rdbService, example EPICS V4 service, https://github.com/epics-base/exampleJava/tree/master/src/rdbService
bib:uri
Uniform Resource Identifiers (URI): Generic Syntax, http://www.ietf.org/rfc/rfc2396.txt.