EPICS V4 Developer's Guide

editions

2019.04.19
Original
2012.04.22
Update

NOTE: This is the working version of the developerGuide.

Editors:
Marty Kraimer

Abstract

This document is a developer guide for the module components of EPICS-7

Table of Contents

Overview of the PVA components of EPICS 7

This document briefly describes a set of application programming interfaces (APIs) for PVA.

These core APIs provide a toolkit for creating applications that access and/or provide sources of structured data. This document is intended for EPICS software developers who want to implement applications via the core APIs.

This document is a tutorial rather then a detailed reference manual. Links to the reference manual for each PVA modules are provided in the following overview sections.

PVA Modules

The current release of EPICS 7 includes the following PVA modules:

pvData
The EPICS PVA type system, which describes and implements structured data.
normativeTypes
A set of standard pvData structures.
pvAccess
Support for connecting a client to servers and for transporting pvData between client and server.
pvaClient
pvAccess is a callback based API. pvaClient provides a synchronous interface, simpified callback classes, and a number of convenience methods.
pvDatabase
A memory resident database of PVRecords and a channel provider for accessing the PVRecords.
pva2pva
This consists of two components: 1) A gateway, and 2) qsrv. This document only discusses qsrv.
qsrv is a channel provider for EPICS DBRecords.

In addition the following, although not part of the current EPICS 7 release, are based on PVA:

example
A set of examples that use all of the above components.
pvaPy
Python wrapper for pvData and pvAccess. This is not described in this docmument.

pva2pva and pvaPy are implemented only in C++. Each has a single github repository.

All the components are implemented in C++. Some of the components are also implemented in Java, but the Java components are not described here.

All components have it's own public repository. For example pvDataCPP has the repository pvDataCPP

Terminology

EPICS 7
This is a combination of epics-base and what was previously called EPICS V4, but is now called PVA.
epics-base is what has existed since about 1990. It has had many releases: The oldest set of releases are the 3.11 series and the newest is the base_7.* series. epics-base is also refered to as EPICS V3. It provides support for DBRecords.
A DBRecord has as a flat data structure, with fields determined by the record type. PVA adds structured data and works along side EPICS V3. It's main components are:
pvData
API and implementation for structured data
normativeTypes
A set of structures designed for use by tools like display managers, archivers, etc.
pvAccess
Network support and API for transfering data between clients and servers. All data is handled as pvData objects.
API - Application Programming Interface
The pvData API is how a client accesses the type system and data objects for each type.
Introspection API
The type system supports both introspection and data interfaces. The introspection interfaces allow a client to determine the data types for objects without requiring a data instance.
Data API
These provide access to data instances.
type
Often used when talking about a field. In this case it means the intospection interface for the field.
PVScalarType
Generic name for the data type for a scalar. Thus a generic name for one of PVBoolean, PVByte, ..., PVString.
PVScalarArrayType
Generic name for the data type for a scalarArray. This a generic name for one of PVBooleanArray, PVByteArray, ..., PVStringArray.
PVType
Generic name for any valid Data API type.
Special Field
These are a set standard structure definitions: enum, alarm, timeStamp, control, display, and alarmLimit.

Overview: pvData

pvData supports structured data where a structure is a set of fields. Each field is composed of one of the following types:

scalar
The field holds data that has a single scalarType:
boolean
Can be true or false.
signed Integer
Integers of 8, 16, 32, and 64 bits are supported.
unsigned Integer
Unsigned integers of 8, 16, 32, and 64 bits are supported.
float
IEEE 32 bit floating point.
double
IEEE 64 bit floating point.
string
In C++ std::string and on the network UTF8.
scalarArray
An array of one of the scalar types.
structure
A set of fields and a name for each field. Each field can have any valid type but the type can not change.
structureArray
An array of structures. Each element must have the same introspection interface.
union
A field that has a single sub field which can dynamically change type. A variant union allows any valid type. A restricted union allows for a set of valid types.
unionArray
A array of unions. Each element must have the same introspection interface.

Overview: normativeTypes

Each normative type defines a structure that has a set of standard fields. For example NTScalar defines:

epics:nt/NTScalar:1.0
    double value                        // mandatory and can be any scalar 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                     //

Overview: pvAccess

A client written in either Java or C++ can communicate with a server written in either Java or C++. All communication between client and server is done via the methods provided by pvAccess and by pvData objects.

pvAccess provides:

channelProviderRegistry
An arbitrary number of channelProviders can be created. Starting with EPICS 7, a separate registry exists for client and server.
channelProvider
Code that provides access to a pvData data source. It creates channels.
A channel:
  • Provides access to a pvData structure.
  • Has an associated channelName.
channel
Methods for each of the following:
getField
Get the pvData introspection information.
channelGet
Get data.
channelPut
Put data.
channelPutGet
Put data, let server process, and then get result.
monitor
Monitor pvData changes.
channelArray
get/put subArray data.
channelRPC
Like channelPutGet but on each request pvData interfaces for put and get can change.

channelPutGet and channelRPC provide the equivalent of a Remote Procedure Call. The client passes a pvData object to the server. This pvData object is the argument for the RPC. The server uses this to decide what to do and sends a pvData object back to the client, which is the RPC result.

Overview: pvaClient

pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API. In addition pvaClient provides many convenience methods. Thus it is easier to use than pvAccess itself.

pvaClientCPP also provides simplified callback classes, which can be used to implement non blocking client code.

Overview: pvDatabase

A framework for implementing a network accessible database of smart memory resident records. Network access is via pvAccess. The data in each record is a top level PVStructure as defined by pvData. A complete implementation of ChannelProvider, named local, is provided for accessing the records. The framework can be extended in order to create record instances that implement services. The minimum that an extension must provide is a top level PVStructure, a record name, and a process method. The record name is the channel name for provider local.

Overview: pva2pva

qsrv (a major component of pva2pva) is a channel provider for accessing DBRecords in an IOC. qsrv allows clients to get, put and monitor V3 PVs (fields of EPICS DB records) via pvAccess, translating the value and its meta data (graphics limits, alarm status, timestamp) to or from V4 Normative Type (NT) pvData structures (NTScalar, NTScalarArray, and NTEnum).

Overview: pvaPy

A Python wrapper for pvData and pvAccess. This is not discussed in this document.

Overview: channelProvider

The basic requirements for a channel provider are:

  1. Given a channel name, find and connect to the data source
  2. Implement one or more of the channel methods: getField, createChannelGet, etc.
  3. get/put all data as pvData.

pvAccess implements channelProviderRegistry, which allows an arbitrary number of providers.

Starting with EPICS 7 there are separate client and server registries.

A provider is one of the following:

Client Provider
Called by code that wants to access a channel, where each channel has a unique channel name
Server Provider
A provider for the remote side of the pva provider, which is described next.

Before either kind of provider can be used it must first register itself with the channelProviderRegistry

Provider pva

An important component of EPICS V4 is provider pva, which is a provider that implements a connection between a client and a server that uses the pva network protocol.

Provider pva has two components:

client
This is what a pvAccess client uses.
remote
This connects to server providers.

Network communcation is used between client and server. Remote pva transfers data between the network and channel providers that have registered at the remote node.

Client Providers

An arbitrary number of client providers can be implemented. Each provider must implement the channel interface mentioned above and must register with the channelProviderRegistry before it can be used by a client.

pvAccess itself provides the following client providers:

pva
The client side of provider pva.
ca
This is a connection that uses channel access to access an epics V3 channel.
pipelineService
A pipelineService is a service that provides a lossless channel monitor. A client requests access to a pipelineService via a pvRequest argument.

Server Providers

At present the following providers are available for the remote side of pva

local
This is implemented by pvDatabase
qsrv
This is a provider that directly accesses DBRecords.
pipelineService
pvAccess provides a helper class for a service that wants to implement a pipelineService.

Client Provider Choices

At present a client that is not running as part of a V3 IOC or a pvDatabase has two choices for channelProvider: pva and ca. A client running as part of a V3 IOC also has the same choices.

Since channelProviderRegistry allows an arbitrary number of providers, additional providers can be developed for either the client or remote side of pva.

pvTools

pvAccessCPP implements the following command line tools: pvlist, pvget, pvput, pvinfo, and eget.

See: pvTools

pvget and pvput support request options. See: pvRequest

example code

NOTE: exampleCPP is not part of the EPICS 7 release. It must be cloned from github:

git clone https://github.com/epics-base/exampleCPP.git

exampleCPP has examples that use code from all modules described in this document except for pvaPy. In particular it has examples:

database
Example server code implemented via pvDatabase.
In addition it shows how to have PVRecords and V3 Records both running as part of a V3 IOC.
It also shows how to start provider qsrv so that both ca and pva can be used to access the V3 records.
In addition it uses several support modules that are also part of exampleCPP. It also uses support from pvDatabaseCPP
See: pvService for details
serviceMain
A main program that the same set support modules that are used by database.
exampleClient
example client code using the pvaClient API.

These examples can be used while learning what is described in this document. ExampleCPP has other examples.

Examples in exampleClient require that the database in exampleCPP/database or exampleCPP/serviceMain is started. The exampleDatabase is started as part of a V3 IOC. It has PVRecords and V3 DBRecords and starts qsrv. All the V4 PVRecords have the prefix PVR and all the V3 DBRecords have the prefix DBR.

In linux exampleCPP/serviceMain can be started as follows:

pwd
/home/epicsv4/master/exampleCPP/serviceMain
bin/linux-x86_64/serviceMain

In linux exampleCPP/database can be started as follows:

pwd
/home/epicsv4/master/exampleCPP/database/iocBoot/exampleDatabase
../../bin/linux-x86_64/exampleDatabase st.cmd

The example database has both V3 IOC records and V4 PVRecords. In addition qsrv is running. Thus all V3 records are available via either ca or pva. The PVRecords are only available via pva. Examples of using ca and pva command line tools are:

pvlist 
GUID 0x7F06B2560000000047B97D25 version 1: tcp@[10.0.0.37:45345, 192.168.124.1:45345]
pvlist 0x7F06B2560000000047B97D25
DBRao01
DBRdouble00
.... many more records
pvget PVRlong
PVRlong                        0
caget PVRlong
Channel connect timed out: 'PVRlong' not found.
caget DBRdouble01
DBRdouble01                       0
pvget DBRdouble01
DBRdouble01                       0
caget PVRushort01
Channel connect timed out: 'PVRushort01' not found.
pvget PVRushort01
PVRushort01                       0

The examples in exampleCPP/exampleClient can now be run. For example:

pwd
/home/epicsv4/masterCPP/exampleCPP/exampleClient
ls bin/linux-x86_64/
addRecord                    getField            ntMultiGet
examplePvaClientGet          getputmonitor       ntMultiMonitor
examplePvaClientMonitor      helloWorldPutGet    ntMultiPut
examplePvaClientMultiDouble  helloWorldRPC       process
examplePvaClientNTMulti      monitor             put
examplePvaClientProcess      multiGetDouble      putGet
examplePvaClientPut          multiMonitorDouble  putUnion
get                          multiPutDouble      rpc

bin/linux-x86_64/examplePvaClientGet
_____examplePvaClientGet starting_______
__exampleDouble__
short way
as double 0
long way
as double 0
... LOTS MORE OUTPUT

pvaClient Tutorial

Some Basic Concepts

Special Field Structures

EPICS V3 DBD defines data related to the VAL field of a DBRecord

The following provide pvData definitions for this data: alarm, timeStamp, enum, display, control, and alarmLimit.

Each is a structure that also has an associated structure id name. For example alarm_t is the structure id name for an alarm structure. For the tutorial alarm, timeStamp, and enum are briefly discussed. Below, in section "Special Fields", there is a fuller description of these and the other definitions. Also see: pvRequest

alarm
alarm_t alarm
    int severity
    int status
    string message 

pvData provides code associated with a alarm structure. This code restricts severity to be one of:

noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm

and status to be one of:

noStatus,deviceStatus,driverStatus,recordStatus,
dbStatus,confStatus,undefinedStatus,clientStatus
timeStamp
time_t timeStamp
    long secondsPastEpoch
    int nanoseconds
    int userTag

pvData provides code associated with a timeStamp structure. This code provides support that makes the timeStamp UTC (Universial Time Coordinated) compliant.

enum
enum_t value
    int index
    string[] choices

pvData provides code associated with an enum structure. This forces the index to select an element of the choices.

pvRequest

Each of the PVChannel create methods has a PVStructure argument named pvRequest. This structure allows the client to 1) select a subset of the fields in the top level structure from the server, 2) provide record options, and 3) provide field specific options.
See: pvRequest for a full description.

pvAccess provides a method createRequest that, given a string, creates a pvRequest structure.

For this tutorial lets just give a simple example:

"field(value, alarm, timeStamp)"
or just
"value, alarm, timeStamp"
Specifies that the client wants to receive the top level fields named value, alarm , and timeStamp.

C++ Tutorial

The tutorial is not part of an EPICS 7 release. It can be cloned via the command:

git clone  https://github.com/mrkraimer/pvaClientTutorialCPP.git
cd pvaClientTutorialCPP
make

Clone it in the same directory that holds your EPICS 7 release. Documentation is provided in pvaClientTutorialCPP/documentation/clientTutorialCPP.html.

pvAccess Channel Providers.

NOTES:

pvaClient
If you are using pvaClientCPP to write client code then pvaClient takes care of starting and shutting down client providers.
pvDatabase
If you are using pvDatabaseCPP then pvDatabase takes care of starting and shutting down server providers.
pav2pva
This provides support for starting a remote pva server and provider qsrv as part of an IOC.

pvAccess implements the following providers:

pva
This is a provider that trasfers data via the pva network protocol implemented by pvAccess.
This provides the client and server side of the network protocol. The client side is a complete implementation. The server side requires additional code to access data sources but takes care of all network code.
ca
This is client support for transfering data via the EPICS V3 channel access protocol.

Providers can be provided for other data sources. A provider must implement ChannelProvider and Channel. pvAccess supports an arbitrary number of providers. On the server side of remote pva providers must be implemented, because pva calls the providers to implement the Channel methods.

At present C++ provides two server side providers:

qsrv
This is a pvAccess server that accesses V3 records,
local
This is implemented by pvDatabaseCPP

pvData: Standard Fields

The following discusses the following fields:

enum
V4 replacment for the value field data for bi, bi, mbbi, mbbo, records types.
alarm
V4 implementation of alarm status and severity.
timeStamp
V4 implementation of timeStamp.
display
V4 implementation of display fields.
control
V4 implementation of control fields.
valueAlarm
V4 implementation of alarm limits.

enum

Defined in:
pvDataCPP/include/pv/pvEnumerated.h

structure

An enumerated structure is a structure that has fields:

enum_t
    int index
    string[] choices

PVEnumerated

PVEnumerated
    bool attach(PVField pvField)
    void detach()
    boolean isAttached()
    boolean setIndex(int index)
    int getIndex()
    String getChoice()
    boolean choicesMutable()
    String[] getChoices()
    int getNumberChoices()
    bool setChoices(String[] choices)

where

attach
Attempts to attach to pvField It returns (false,true) if pvField (is not, is) an enumerated structure.
detach
Detaches from the pvData structure.
isAttached
Is there an attachment to an enumerated structure?
setIndex
Set the index field in the pvData structure. An exception is thrown if not attached to a pvData structure.
getIndex
Get the index field in the pvData structure.
getChoice
Get the String value corresponding to the current index field in the pvData structure. An exception is thrown if not attached to a pvData structure.
choicesMutable
Can the choices be changed? Note that this is often true. An exception is thrown if not attached to a pvData structure.
getChoices
Get the array of choices. An exception is thrown if not attached to a pvData structure.
getNumberChoices
Return the number of choices
getNumberChoices
Get the number of choices. An exception is thrown if not attached to a pvData structure.
setChoices
Change the choices. An exception is thrown if not attached to a pvData structure.

alarm

Defined in:
pvDataCPP/include/pv/alarm.h
and
pvDataCPP/include/pv/pvAlarm.h

structure

An alarm structure is defined as follows:

alarm_t alarm
    int severity
    int status
    string message

Note that severity and status are NOT defined as enumerated structures. The reason is performance, i. e. prevent passing the array of choice strings everywhere. The AlarmStatus and AlarmSeverity provide the equivalent of choices for an enumerated structure.

AlarmSeverity

Alarm Severity defines the possible alarm severities

enum AlarmSeverity{
    noAlarm,minorAlarm,majorAlarm,invalidAlarm,undefinedAlarm
}
AlarmSeverityFunc {
    AlarmSeverity getSeverity(int value)
    String[] getSeverityNames()
}
where
getSeverity
Get the alarm severity corresponding to the integer value.
getSeverityNames
Get the array of severity choices.

AlarmStatus

Alarm Status defines the possible alarm status conditions

enum AlarmStatus {
    noStatus,deviceStatus,driverStatus,recordStatus,
    dbStatus,confStatus,undefinedStatus,clientStatus
}

AlarmStatusFunc{
    getStatus(int value)
    String[] getStatusNames()
where
getStatus
Get the alarm status corresponding to the integer value.
getStatusNames
Get the array of status choices.

Alarm

Alarm {
    String getMessage()
    void setMessage(String message)
    AlarmSeverity getSeverity()
    void setSeverity(AlarmSeverity alarmSeverity)
    AlarmStatus getStatus()
    void setStatus(AlarmStatus alarmStatus)
}
where
getMessage
Get the message.
setMessage
Set the message.
getSeverity
Get the severity.
setSeverity
Set the severity.
getStatus
Get the status.
setStatus
Set the status.

PVAlarm

PVAlarm {
    bool attach(PVField pvField)
    void detach()
    boolean isAttached()
    void get(Alarm alarm)
    bool set(Alarm alarm)
}

where

PVAlarm
The default constructor. Attach must be called before get or set can be called.
attach
Attempts to attach to pvField It returns (false,true) if it found an appropriate pvData structure. It looks first a pvField itself and if is not an appropriate pvData structure but the field name is value it looks to see if the parent structure has an appropriate sub structure.
detach
Detaches from the pvData structure.
isAttached
Is there an attachment to an alarm structure?
get
Copies data from the pvData structure to an Alarm. An exception is thrown if not attached to a pvData structure.
set
Copies data from Alarm to the pvData structure. An exception is thrown if not attached to a pvData structure.

timeStamp

Defined in:
pvDataCPP/include/pv/timeStamp.h
and
pvDataCPP/include/pv/pvTimeStamp.h

structure

A timeStamp is represented by the following structure

time_t timeStamp
    long secondsPastEpoch
    int nanoseconds
    int userTag

The Epoch is the POSIX epoch, i.e. Jan 1, 1970 00:00:00 UTC. Both the seconds and nanoseconds are signed integers and thus can be negative. Since the seconds is kept as a 64 bit integer, it allows for a time much greater than the present age of the universe. Since the nanoseconds portion is kept as a 32 bit integer it is subject to overflow if a value that corresponds to a value that is greater than a little more than 2 seconds or a little less than -2 seconds. The support code always adjust seconds so that the nanoSecconds part is normalized, i. e. it has is 0<=nanoseconds<nanoSecPerSec..

TimeStamp

The definition of TimeStamp is:

TimeStamp {
    void normalize()
    void fromTime_t(time_t time)
    void toTime_t(time_t time
    long getSecondsPastEpoch()
    long getEpicsSecondsPastEpoch()
    int getNanoseconds()
    int getUserTag()
    void setUserTag(int userTag)
    void put(long secondsPastEpoch,int nanoseconds)
    long getMilliSeconds()
    void put(long milliSeconds)
    void getCurrent()
    double toSeconds()
    boolean equals(TimeStamp other)
    boolean lt(TimeStamp other)
    boolean le(TimeStamp other)
    void add(long seconds)
    void add(double seconds)
    double diff(TimeStamp a,TimeStamp b)
}

where:

normalize
Adjust secondsPastEpoch and nanoseconds so that 0<=nanoseconds<nanoSecPerSec.
fromTime_t
Set timeStamp from standard C time
toTime_t
Set time from timeStamp
getSecondsPastEpoch
Get the seconds part of timeStamp
getEpicsSecondsPastEpoch
Get seconds relative to the EPICS epoch. The epics epoch starts on Jan 1 1990 00:00:00 UTC.
getNanoseconds
Get the nanoseconds part of timeStamp.
getUserTag
Get the userTag
setUserTag
Set the userTag
put(long secondsPastEpoch,int nanoseconds)
Put a value into the timeStamp.
getMilliSeconds
Get the number of milliseconds since the epoch.
put(long milliSeconds);
Put a value into the timeStamp given the number of milliSeconds since the epoch.
getCurrent
Get the current time.
toSeconds
Convert the timeStamp to a double value that is seconds past epoch/
equals
Is this time equal other?
lt
Is this time less than other.
le
Is this time less that or equal to other.
add(long seconds)
Add the specified number of seconds.
add(double seconds)
Add the specified number of seconds.
diff
Compute a-b. The result is in seconds.

The TimeStamp class provides arithmetic and comparison methods for time stamps. The result is always kept in normalized form, which means that the nanosecond portion is 0<=nano<nanoSecPerSec. Note that it is OK to have timeStamps for times previous to the epoch.

PVTimeStamp

PVTimeStamp {
    bool attach(PVField pvField)
    void detach()
    bool isAttached()
    void get(TimeStamp timeStamp)
    boolean set(TimeStamp timeStamp)
}
where
attach
Attempts to attach to pvField It returns (false,true) if a timeStamp structure is found. It looks first at pvField itself and if is not an appropriate pvData structure but the field name is value it looks up the parent structure tree.
detach
Detach from the pvData structure.
isAttached
Is there an attachment to a timeStamp structure?
get
Copies data from the pvData structure to a TimeStamp. An exception is thrown if not attached to a pvData structure.
set
Copies data from TimeStamp to the pvData structure. An exception is thrown if not attached to a pvData structure.

display

Defined in:
pvDataCPP/include/pv/display.h
and
pvDataCPP/include/pv/pvDisplay.h
NOTE: Should format be replaced by precision and form?

structure

Display information is represented by the following structure

structure display
    double limitLow
    double limitHigh
    string description
    string format
    string units

Display

Display {
    double getLow()
    double getHigh()
    void setLow(double value)
    void setHigh(double value)
    String getDescription()
    void setDescription(String value)
    String getFormat()                 // broken
    void setFormat(String value)       // broken 
    String getUnits()
    void setUnits(String value)
}

where

getLow
Get the low limit.
getHigh
Get the high limit.
setLow
Set the low limit.
setHigh
Set the high limit.
getDescription
Get the description.
setDescription
Set the description.
getFormat
Get the format.
setFormat
Set the format.
getUnits
Get the units.
setUnits
Set the units.

PVDisplay

PVDisplay {
    bool attach(PVField pvField)
    void detach()
    bool isAttached()
    void get(Display display)
    bool set(Display display)
}

where

attach
Attempts to attach to pvField It returns (false,true) if it found an appropriate pvData structure. It looks first a pvField itself and if is not an appropriate pvData structure but the field name is value it looks to see if the parent structure has an appropriate sub structure.
detach
Detaches from the pvData structure.
isAttached
Is there an attachment to a display structure?
get
Copies data from the pvData structure to a Display. An exception is thrown if not attached to a pvData structure.
set
Copies data from Display to the pvData structure. An exception is thrown if not attached to a pvData structure.
create
Create a PVDisplay instance. Attach must be called before get or set can be called.

control

Defined in:
pvDataCPP/include/pv/control.h
and
pvDataCPP/include/pv/pvControl.h
NOTE: Should minStep be named maxStep?

structure

Control information is represented by the following structure

structure control
    double limitLow
    double limitHigh
    double minStep

Control

The definition for Control is:
Control{
    double getLow()
    double getHigh()
    double getMinStep()
    void setLow(double value)
    void setHigh(double value)
    void setMinStep(double value)
}

where

getLow
Get the low limit.
getHigh
Get the high limit.
getMinStep
Get the minimum stepsize.
setLow
Set the low limit.
setHigh
Set the high limit.
setMinStep
Set the minimum stepsize.

PVControl

PVControl
    boolean attach(PVField pvField)
    void detach()
    boolean isAttached()
    void get(Control control)
    boolean set(Control control)

where

attach
Attempts to attach to pvField It returns (false,true) if it found an appropriate pvData structure. It looks first a pvField itself and if is not an appropriate pvData structure but the field name is value it looks to see if the parent structure has an appropriate sub structure.
detach
Detaches from the pvData structure.
isAttached
Is there an attachment to a control structure?
get
Copies data from the pvData structure to a Control. An exception is thrown if not attached to a pvData structure.
set
Copies data from Control to the pvData structure. An exception is thrown if not attached to a pvData structure.
create
Create a PVControl instance. Attach must be called before get or set can be called.

valueAlarm

NOTE: Not sure if this is being used by anyone.

Defined in:
pvDataCPP/include/pv/standardField.h
and
pvDataCPP/include/pv/standardPVField.h

structure

For each numeric scalar type the following is defined:

boolean active
scalarType lowAlarmLimit
scalarType lowWarningLimit
scalarType highWarningLimit
scalarType highAlarmLimit
int lowAlarmSeverity
int lowWarningSeverity
int highWarningSeverity
int highAlarmSeverity
scalarType hysteresis

For boolean the following is defined:

boolean active
int falseSeverity
int trueSeverity
int changeStateSeverity

For enum the following is defined:

boolean active
int stateSeverity
int changeStateSeverity

Appendix I: Standard for Field::ID

The introspection interface for every field has an ID, which is available via method:

class Field {
...
    string getID();
...
};

This section describes how the IDs are assigned.

Scalar

boolean
byte
short
int
long
ubyte
ushort
ulong
float
double
string

Scalar Array

boolean[]
byte[]
short[]
int[]
long[]
ubyte[]
ushort[]
ulong[]
float[]
double[]
string[]

Union

any        // variant union
union      // restricted union

Union Array

any[]
union[]

structure

default

structure

standard fields

alarm_t
time_t
display_t
control_t
enum_t
valueAlarm_t

structure array

Like structure except that [] is appended.

Appendix II: Convert Facility

pvDataCPP has a Convert Facility. The faclity only supports complete array copies between two scalar arrays of the same type and only does a shallow copy. It also does a shallow copy for union, unionArray, and structureArray fields. It also has a separate facility that does sub-array copies between two arrays of the same type.

This section describes the supported conversions between data types.

interface Convert {
    void getString(StringBuilder buf,PVField pv, int indentLevel);
    void getString(StringBuilder buf,PVField pv);
    void fromString(PVScalar pv,String from);
    void fromString(PVScalarArray pv,String from);
    int fromStringArray(PVScalarArray pv,
         int offset, int len, String[]from, int fromOffset);
    int toStringArray(PVScalarArray pv,
         int offset, int len, String[]to, int toOffset);
    // For the following the pv Type must be PVByte, ...., PVDouble
    int8 toByte(PVScalar pv);
    int16 toShort(PVScalar pv);
    int32  toInt(PVScalar pv);
    int64  toLong(PVScalar pv);
    uint8 toUByte(PVScalar pv);
    uint16 toUShort(PVScalar pv);
    uint32  toUInt(PVScalar pv);
    uint64  toULong(PVScalar pv);
    float toFloat(PVScalar pv);
    double toDouble(PVScalar pv);
    String toString(PVScalar pv);
    void  fromByte(PVScalar pv, int8 from);
    void  fromShort(PVScalar pv, int16 from);
    void  fromInt(PVScalar pv, int32 from);
    void  fromLong(PVScalar pv, int64 from);
    void  fromUByte(PVScalar pv, uint8 from);
    void  fromUShort(PVScalar pv, uint16 from);
    void  fromUInt(PVScalar pv, uint32 from);
    void  fromULong(PVScalar pv, uint64 from);
    void  fromFloat(PVScalar pv, float from);
    void  fromDouble(PVScalar pv, double from);

}

The array methods all return the number of elements copied or converted. This can be less than len if the PVField array contains less than len elements.

newLine is a convenience method for code that implements toString It generates a newline and inserts blanks at the beginning of the newline.

The getString methods dump the data in the metadata syntax described in the pvData project overview. Note that the toString methods of PVField are implemented by calling these convert methods.

convert.h

class Convert;
typedef std::tr1::shared_ptr<Convert> ConvertPtr;

class Convert {
public:
    static ConvertPtr getConvert();
    ~Convert();
    void copy(PVFieldPtr const & from, PVFieldPtr const & to);
    void getString(std::string * buf,PVFieldPtr const & pvField,int indentLevel);
    void getString(std::string * buf,PVFieldPtr const & pvField);
    std::size_t fromString(
        PVStructurePtr const &pv,
        StringArray const & from,
        std::size_t fromStartIndex = 0);
    void fromString(PVScalarPtr const & pv, std::string const & from);
    std::size_t fromString(PVScalarArrayPtr const & pv, std::string const &from);
    std::size_t fromStringArray(
        PVScalarArrayPtr const & pv,
        std::size_t offset, std::size_t length,
        StringArray const & from,
        std::size_t fromOffset);
    std::size_t toStringArray(PVScalarArrayPtr const & pv,
        std::size_t offset,
        std::size_t length,
        StringArray & to,
        std::size_t toOffset);
    int8 toByte(PVScalarPtr const & pv);
    int16 toShort(PVScalarPtr const & pv);
    int32 toInt(PVScalarPtr const & pv);
    int64 toLong(PVScalarPtr const & pv);
    uint8 toUByte(PVScalarPtr const & pv);
    uint16 toUShort(PVScalarPtr const & pv);
    uint32 toUInt(PVScalarPtr const & pv);
    uint64 toULong(PVScalarPtr const & pv);
    float toFloat(PVScalarPtr const & pv);
    double toDouble(PVScalarPtr const & pv);
    std::string toString(PVScalarPtr const & pv);
    void fromByte(PVScalarPtr const & pv,int8 from);
    void fromShort(PVScalarPtr const & pv,int16 from);
    void fromInt(PVScalarPtr const & pv, int32 from);
    void fromLong(PVScalarPtr const & pv, int64 from);
    void fromUByte(PVScalarPtr const & pv,uint8 from);
    void fromUShort(PVScalarPtr const & pv,uint16 from);
    void fromUInt(PVScalarPtr const & pv, uint32 from);
    void fromULong(PVScalarPtr const & pv, uint64 from);
    void fromFloat(PVScalarPtr const & pv, float from);
    void fromDouble(PVScalarPtr const & pv, double from);
}
static inline ConvertPtr getConvert() { return Convert::getConvert(); }

NOTE: PVField and derived classes provide method:

void copy(const PVField& from);

pvSubArrayCopy.h

This supports sub-array copying between arrays that have the same type.

template<typename T>
void copy(
    PVValueArray<T> & pvFrom,
    size_t fromOffset,
    size_t fromStride,
    PVValueArray<T> & pvTo,
    size_t toOffset,
    size_t toStride,
    size_t count);

void copy(
    PVScalarArray & from,
    size_t fromOffset,
    size_t fromStride,
    PVScalarArray & to,
    size_t toOffset,
    size_t toStride,
    size_t count);

void copy(
    PVStructureArray & from,
    size_t fromOffset,
    size_t fromStride,
    PVStructureArray & to,
    size_t toOffset,
    size_t toStride,
    size_t count);

void copy(
    PVArray & from,
    size_t fromOffset,
    size_t fromStride,
    PVArray & to,
    size_t toOffset,
    size_t toStride,
    size_t count);

The last copy is the only one most client need to call. It either throws an error if the element types do not match or calls the other copy functions. The arguments are:

from
The source array.
fromOffset
The offset into the source array.
fromStride
The interval between source elements.
to
The destination array. The element type must be the same as for the source array. If the element type is structure then the introspection interface for the element types must be the same.
toOffset
The offset into the destination array.
toStride
The interval between destination elements.
count
The number of elements to copy.

An exception is thrown if:

type mismatch
The element types for the source and destination differ.
immutable
The destination array is immutable.
capacity immutable
The destination array needs to have it's capacity extended but the capacity is immutable.