Data Request Format 2.0

Revision 3 • January 6, 2016

K. Cahill, B. Hendricks, C. King, R. Neswold, J. Patrick, A. Petrov, and C. Schumann

Edited by Andrey Petrov <apetrov@fnal.gov>

Last version of the spec: https://www-bd.fnal.gov/controls/public/drf2

Revision History

© 2009–2011 Fermi Research Alliance, LLC.

Table Of Contents

  1. Introduction
  2. The Request Structure
  3. Device Format
  4. Property Format
  5. Range Format
  6. Field Format
  7. Event Format

1. Introduction

This document describes a uniform data request format for the use in applications, data acquisition protocols, and the middleware (DAE, DPM) of the Fermilab Accelerator Control System.

The established practice of denominating control system's entities — devices, properties, and events — originates from several protocols and APIs developed long time ago. Intuitive, yet somewhat ambiguous, the naming conventions have never been fully documented independently of their implementations. As such, various pieces of software interpret those concepts differently, making their own assumptions about the permitted syntax and character sets. The further evolution of the control system calls for a review of the existing naming practices, in order to make them more rational, remove ambiguity, and to formalize the syntax.

The Data Request Format, Version 2 (DRF2) is based on the existing naming conventions. It is backward compatible, meaning that the new format will honor currently accepted device names, property qualifiers, array indices and range denominators, event names, as well as relevant ACL property and field names. The new format, however, may not be understood by the existing software, and it is intended only for new implementations of data acquisition clients, middleware, and such. A standard DRF2 parser, fully compatible with this document, is provided in Java, Erlang, and C++.

The principal features of DRF2 are:

This document uses a BNF-like grammar (similar to one from RFC2396) to describe the syntax of DRF2. The following definitions are common to many elements:

upalpha           = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J"
                  | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T"
                  | "U" | "V" | "W" | "X" | "Y" | "Z"

lowalpha          = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"
                  | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t"
                  | "u" | "v" | "w" | "x" | "y" | "z"

alpha             = upalpha | lowalpha

dec-digit         = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

dec-number        = 1*( dec-digit )

hex-digit         = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
                  | "A" | "B" | "C" | "D" | "E" | "F"
                  | "a" | "b" | "c" | "d" | "e" | "f"

hex-number        = 1*( hex-digit )

; Canonical forms

c-dec-number      = <a dec-number with no leading zeroes>

c-hex-number      = <a hex-number with no leading zeroes and all chars capitalized>

2. The Request Structure

The data request is defined as a case-insensitive ASCII string with all characters in the range 0x21 (“!”) to 0x7E (“~”).

The request includes an ordered sequence of up to five attributes: device, property, range, field, and event. The only required attribute is device.

request           = device [ "." property ] [ range ] [ "." field ] [ "@" event ]

In the canonical form of a request each attribute is individually transformed to its canonical notation. A missing property attribute is replaced with its default value, as described in §4. The range, field, and event attributes are present in the canonical form only if their values are not default. The notion of a NULL attribute used later in this document describes the entire attribute absent from the request along with its delimiter, not the delimiter and an empty string.

3. Device Format

The device attribute specifies a 64-character ACNET device name or a device index. The name starts with a letter and may include alphanumeric characters, an underscore, and a colon. The index start with a “0” and includes only decimal digits. The second character may designate a property.

device            = device-name | device-index

device-name       = alpha prop-qualifier 1*62( device-char )

device-index      = "0" prop-qualifier dec-number          ; dec-number < 222

device-char       = alpha | dec-digit | "_" | ":"

prop-qualifier	  = ":"       ; Reading and default
                  | "?"       ; Reading 
                  | "_"       ; Setting
                  | "|"       ; Basic Status
                  | "&"       ; Basic Control
                  | "@"       ; Analog Alarm
                  | "$"       ; Digital Alarm
                  | "~"       ; Description

In the canonical form the property qualifier is changed to a colon. Whenever possible, the original character case shall be preserved to facilitate the recognition of device names by the users.

; Canonical

c-device          = c-device-name | c-device-index

c-device-name     = alpha ":" 1*62( device-char )

c-device-index    = "0" ":" c-dec-number

4. Property Format

The property attribute specifies the name of a property within the device. The format supports seven properties: Reading, Setting, Basic Status, Basic Control, Analog Alarm, Digital Alarm, and Description. This list may be extended in the future. Each property has one canonical name and several synonyms.

The default property is specified by a property qualifier inside the device name. If a property is explicitly specified in a request, the property qualifier inside the device name must either match that property or be a colon.

; Canonical property names are in the upper case

property          = reading 
                  | setting 
                  | basic-status 
                  | basic-control
                  | analog-alarm 
                  | digital-alarm 
                  | description
                  | index
                  | long-name

reading           = "READING"                              ; canonical
                  | "READ" | "PRREAD"

setting           = "SETTING"                              ; canonical
                  | "SET" | "PRSET"

basic-status      = "STATUS"                               ; canonical
                  | "BASIC_STATUS" | "STS" | "PRBSTS"

basic-control     = "CONTROL"                              ; canonical
                  | "BASIC_CONTROL" | "CTRL" | "PRBCTL"

analog-alarm      = "ANALOG"                               ; canonical
                  | "ANALOG_ALARM" | "AA" | "PRANAB"

digital-alarm     = "DIGITAL"                              ; canonical
                  | "DIGITAL_ALARM" | "DA" | "PRDABL"

description       = "DESCRIPTION"                          ; canonical
                  | "DESC" | "PRDESC"

index             = "INDEX"                          	   ; canonical

long-name         = "LONG_NAME"                            ; canonical
                  | "LNGNAM" | "PRLNAM"

alarm-list-name   = "ALARM_LIST_NAME"                      ; canonical
                  | "LSTNAM" | "PRALNM"

5. Range Format

The range attribute addresses an individual element or a sequence of elements in the data set.

A data set can be viewed either as an array of homogenous elements or as a sequence of raw bytes. Accordingly, a range may be specified in two forms, depending on which model is used. Array indices are enclosed in brackets, a byte offset and a length are enclosed in braces. One shall make no assumption, based on a form of the range, whether the request asks for raw or scaled data. The use of the bytewise form is discouraged, as it requires a knowledge of front-end data lengths.

An open-ended range is used to request an unknown number of items, either array elements or raw bytes, from the given start index (or byte offset) up to the end of the data set. The full range (a special case of the open-ended range) describes the entire data set, making no distinction between array and bytewise forms.

range             = full-range                             ; default is "[0]" 
                  | array-range 
                  | byte-range

full-range        = "[]" | "[:]" | "[0:]"
                  | "{}" | "{:}" | "{0:}"

array-range       = "[" start-index               "]"      ; end-index is assumed to be the same as start-index
                  | "[" start-index ":"           "]"      ; open-ended
                  | "["             ":" end-index "]"      ; start-index is assumed to be 0
                  | "[" start-index ":" end-index "]" 
                  ; 0 ≤ start-index ≤ end-index < 215

byte-range        = "{" offset            "}"              ; length is assumed to be 1
                  | "{" offset ":"        "}"              ; open-ended
                  | "{"        ":" length "}"              ; offset is assumed to be 0
                  | "{" offset ":" length "}"
                  ; 0 ≤ offset < 231
                  ; length > 0
                  ; offset + length ≤ 231

start-index       = dec-number

end-index         = dec-number

offset            = dec-number

length            = dec-number

The canonical form of a range is defined as follows:

; Canonical

c-range           = c-full-range 
                  | c-array-range 
                  | c-byte-range

c-full-range      = "[]"

c-array-range     = NULL                                   ; when start-index = end-index = 0
                  | "[" c-start-index                 "]"  ; when start-index = end-index > 0
                  | "[" c-start-index ":"             "]"  ; open-ended
                  | "[" c-start-index ":" c-end-index "]"  ; in all other cases

c-array-range     = "{" c-offset              "}"          ; when length = 1
                  | "{" c-offset ":"          "}"          ; open-ended
                  | "{" c-offset ":" c-length "}"          ; in all other cases

c-start-index     = c-dec-number

c-end-index       = c-dec-number

c-offset          = c-dec-number

c-length          = c-dec-number

6. Field Format

The field attribute specifies a flavor of data, such as raw, scaled, or a particular field inside a complex structure. Each property has its own set of valid fields.

; Canonical field names are in the upper case.

field             = reading-fld 
                  | setting-fld 
                  | status-fld 
                  | control-fld 
                  | analog-alarm-fld 
                  | digital-alarm-fld 
                  | description-fld

reading-fld       = "RAW"
                  | "PRIMARY" | "VOLTS"                    ; canonical is "PRIMARY"
                  | "SCALED" | "COMMON"                    ; default is "SCALED"

setting-fld       = "RAW"
                  | "PRIMARY" | "VOLTS"                    ; canonical is "PRIMARY"
                  | "SCALED" | "COMMON"                    ; default is "SCALED"

status-fld        = "RAW"
                  | "ALL"                                  ; default
                  | "TEXT"
                  | "EXTENDED_TEXT"
                  | "ON"
                  | "READY"
                  | "REMOTE"
                  | "POSITIVE"
                  | "RAMP"

control-fld     = NULL

analog-alarm-fld  = "RAW"
                  | "ALL"                                  ; default
                  | "TEXT"
                  | "MIN" | "MINIMUM"                      ; canonical is "MIN"
                  | "MAX" | "MAXIMUM"                      ; canonical is "MAX"
                  | "NOM" | "NOMINAL"                      ; canonical is "NOM"
                  | "TOL" | "TOLERANCE"                    ; canonical is "TOL"
                  | "RAW_MIN" | "RAWMIN"                   ; canonical is "RAW_MIN"
                  | "RAW_MAX" | "RAWMAX"                   ; canonical is "RAW_MAX"
                  | "RAW_NOM" | "RAWNOM"                   ; canonical is "RAW_NOM"
                  | "RAW_TOL" | "RAWTOL"                   ; canonical is "RAW_TOL"
                  | "ALARM_ENABLE" | "ENABLE"              ; caninical is "ALARM_ENABLE"
                  | "ALARM_STATUS" | "STATUS"              ; canonical is "ALARM_STATUS"
                  | "TRIES_NEEDED"
                  | "TRIES_NOW"
                  | "ALARM_FTD" | "FTD"                    ; canonical is "ALARM_FTD"
                  | "ABORT"
                  | "ABORT_INHIBIT"
                  | "FLAGS"

digital-alarm-fld = "RAW"
                  | "ALL"                                  ; default
                  | "TEXT"
                  | "NOM" | "NOMINAL"                      ; canonical is "NOM"
                  | "MASK"
                  | "ALARM_ENABLE" | "ENABLE"              ; caninical is "ALARM_ENABLE"
                  | "ALARM_STATUS" | "STATUS"              ; canonical is "ALARM_STATUS"
                  | "TRIES_NEEDED"
                  | "TRIES_NOW"
                  | "ALARM_FTD" | "FTD"                    ; canonical is "ALARM_FTD"
                  | "ABORT"
                  | "ABORT_INHIBIT"
                  | "FLAGS"

description-fld   = NULL

7. Event Format

The event attribute specifies on which moments of time the data should be read or set. The syntax of event descriptors is based on the one used in the Get32 protocol and in the DataEventFactory class.

The time values used in events (periods, delays) are specified as an integer number optionally followed by a time unit. By default, the numeric value is in milliseconds. The unit suffixes can also be used to switch between a time notation and a frequency notation.

time-freq         = dec-number [ time-freq-unit ]          ; dec-number < 231
                 
time-freq-unit    = "S"                                    ; seconds
                  | "M"                                    ; milliseconds (default)
                  | "U"                                    ; microseconds
                  | "H"                                    ; Hertz
                  | "K"                                    ; kilohertz

The canonical form of time and frequency values is defined as follows:

c-time-freq       = "0"                                    ; time = 0
                  | c-dec-number "S"                       ; time ≥ 1 s.  & ms-time = 0 & µs-time = 0
                  | c-dec-number                           ; time ≥ 1 ms. & µs-time = 0
                  | c-dec-number "U"                       ; time ≥ 1 µs. 
                  | c-dec-number "K"                       ; frequency ≥ 1 kHz & hz-frequency = 0
                  | c-dec-number "H"                       ; frequency ≥ 1 Hz

The format supports five types of events: Default, Once Immediate, Periodic, Clock, and State. The first two are trivial and do not require any additional values.

event             = default-evt                            ; default
                  | immediate-evt 
                  | periodic-evt 
                  | clock-evt 
                  | state-evt

default-evt       = "U"

immediate-evt     = "I"

The Periodic event acquires data at a fixed rate. A special flavor of it, the periodic non-continuous event, does not fire (skips cycles) unless the data provided by the frontend has changed.

periodic-evt      = ("P" | "Q") [ "," period [ "," immediate ] ]
                  ; "P" for continuous
                  ; "Q" for non-continuous
                  
period            = time-freq                              ; default is 1S

immediate         = "TRUE"  | "T"                          ; default
                  | "FALSE" | "F"

The Clock event uses signals provided by the global timing system.

clock-evt         = "E," evt-number [ "," type [ "," delay ] ]

evt-number        = hex-number                             ; evt-number < 216

type              = "H"                                    ; hardware 
                  | "S"                                    ; software
                  | "E"                                    ; either one (default)
                  
delay             = time-freq                              ; default is 0

The State event acquires data upon a state transition on a device.

state-evt         = "S," device "," value "," delay "," expression

value             = dec-number                             ; value < 216

expression        = "=" 
                  | "!=" 
                  | ">" 
                  | "<" 
                  | "<=" 
                  | ">=" 
                  | "*"

The canonical form of events is defined as follows:

;Canonical

c-event           = c-default-evt 
                  | c-immediate-evt 
                  | c-periodic-evt 
                  | c-clock-evt 
                  | c-state-evt
                  
c-default-evt     = NULL

c-immediate-evt   = "I"

c-periodic-evt    = ("P" | "Q") "," c-time-freq "," ("TRUE" | "FALSE")

c-clock-evt       = "E," c-hex-number "," ("H" | "S" | "E") "," c-time-freq

c-state-evt       = "S," c-device "," c-dec-number "," c-time-freq "," expression

Security, Privacy, Legal