MDSplus EPICS interface
The MDSplus interface for EPICS is composed of three main components:
- A IOC record which allow using MDSplus functionality from within EPICS Input/Output Controllers;
- Waveform device support for synchronization with MDSplus events;
- A Channel archiver for MDSplus, for storing data generated within EPICS IOCs (and more in gereral by any Channel Access Server (CAS) application) exported using the Channel Access protocol into MDSplus trees;
- A Channel Access Server for exporting MDSplus configuration data to IOC records using the Channel Access protocol.
MDSplus Records for EPICS I/O Controllers
In EPICS control and supervision is carried out by I/O Controllers (IOCs) . Every I/O controller is an application which executes a set of interconnected components called Records. Every record carries out a specific set of actions and can propagate data to other interconnected records. The behavior of a IOC is therefore defined by the associated records, and such configuration is stored as a text file. Graphical tools exist for the proper record programming and interconnection. Every record defines a set of fields which define its behavior. Records can be executed either periodically or when the the records connected via incoming links are executed. The basic set of EPICS records has been extended to provide MDSplus functionality within IOCs, via the mdsexpr record, for evaluating MDSplus expressions. MDSplus expressions represent a very flexible way for retrieving data or executing actions, including saving data in MDSplus trees. The corresponding expression is evaluated every time that record is processed in the EPICS IOC.
When processed, record mdsexpr will provide the evaluation of the specified MDSplus expression. Since in MDSplus expressions represent a very general concept, evaluating a MDSplus expression may involve many different actions. If the expression is used in the traditional way, it will perform the computation specified by field EXPR, possibly taking up to 8 arguments, specified by fields INP1-8 (links to data arguments) and FT1-8 (types of data arguments). The result of the evaluated expression is stored in field VAL, converted to the type specified in field FTVL. Field NORD will contain the number of returned data items (>1 if an array is the result of the expression evaluation). The expression may also contain calls to routines of shareable libraries, so this record can also be used to trigger external computation, possibly taking inputs from the records connected to the mdsexpr record.
The evaluation of the expression can be carried out either locally or remotely, on any node running a mdsip server. In the latter case, the possible arguments are sent over the network and the result is sent back, using the mdsip protocol for remote data access.
The expression may also contain references to MDSplus trees: in this case fields EXP and SHOT specify the name and the shot of the tree to which data item in the expression refer to. If field EXP is empty it is assumed that the expression does not refer MDSplus pulse files (trees) and no tree is open during record initialization.
In order to specify external arguments to the expression specification, use $ arguments in the textual expression definition (field EXPR). For example, the evaluation of expression 2 * $ + $ will take the first argument specified in field INP1, multiply it for 2 and then add the second argument, specified by field INP2. Array arguments are supported since MDSplus is able to handle multidimensional elements in expression evaluation.
The specific fields of mdsexpr record are:
- DTYP Device type, must be devExprSoft;
- LOC Local/Remote switch. If remote, the expression is evaluated on the machine whose address is specified in DSIP;
- DSIP Address of the mdsip server which will evaluate the expression;
- EXPR Textual specification of the expression. Refer to MDSplus documentation for syntax description and examples;
- INP1 - INP8 Input specifications, typically links to other records, they are associated with the $ argument specification in the textual expression description in EXPR;
- FT1 - FT8 Type specification of the input fields;
- FTVL Output type. The result of the expression is converted to the specified type;
- NORD Number of returned elements, > 1 if the evaluation of the expression is an array;
- NELM Maximum number of elements: used to dimension the internal buffers. Must be not less than the maximum number of samples for the inputs and the computed value;
- EXP Tree name in case a tree has to be open during expression evaluation (in the case the expression contains references to data item stored in MDSplus trees). When containing an empty string no tree is open;
- SHOT Shot number of the tree to be open.
- ERRM Error message string. After processing it will contain the error message in case of errors.
The result of the expression is then stored in field VAL
It is possible to use this record also to store data in pulse files. Suppose that the record, when processed, needs to store the value received in its input link in the pulse file. In this case the required steps are:
- Connect the record with the data input. This is reflected in the source record name in field INP1
- Define the type of the data input in field FTI1
- In EXPR field define expression TreePutRecord('<node name>', $1)
Waveform device support
A new Device type can be associated with Waveform record in order to synchronize the record with the occurrence of a MDSplus event. When the event is received, its VAL field will contain the (raw) value associated with the event generation. The required configuration steps are:
- define devMeSoft as DTYP field. If running VDCT, this option can be selected in the pulldown menu.
- define the event name in field INP. A timeout in seconds when waiting for the event can be optionally specified. The syntax if the INP field is @<event_name>[:<timeout>]
- define fields NELM and FTVL to the number of elements and type of the data item associated with the event, respectively. Usually the event is generated by command setevent <event name> [<optional data as string>]. In this case define FTVL as STRING and NELM as the length of the passed string.
The files required to install the records in EPICS are contained in <MDSplus root>/epics/mdsrecord.
Basic installation is performed in following steps:
- Create a EPICS directory tree named mdsplusSup using the EPICS procedure MakeBaseApp starting from root <ApplicationRoot>
- Copy the files in <MDSplus root>/epics/mdsrecord into the directory created: <ApplicationsRoot>/m-mdsplusSup/src/main/epics/mdsplusSupApp/src/
- Build it with the EPICS mvn compile command
In order to use mdsexpr record in a EPICS IOC (named <AppName>), the following actions are requied in the IOC specific EPICS directory tree:
- Copy all the dbd files from <MDSplus root>/epics/mdsrecord into <AppName>/src/main/epics/<AppName>App/src/
- Modify Makefile in that directory to include the following lines:
#=========================== # MDSplus record support <AppName>_DBD += mdsexprRecord.dbd <AppName>_DBD += devMeSoft.dbd <AppName>_DBD += devExprSoft.dbd <AppName>_LIBS += mdsplusSup mdsplusSup_DIR += <ApplicationsRoot>/m-mdsplusSup/target/main/epics/lib/linux-x86_64 mdsplusSup_LIBS += MdsObjectsCppShr mdsplusSup_LIBS += MdsIpShr MdsObjectsCppShr_DIR += /usr/local/mdsplus/lib/ MdsIpShr_DIR += /usr/local/mdsplus/lib/
- Build the application with the EPICS command mvn compile
MDSplus Channel Archiver for EPICS
The MDSplus channel archiver allows connecting to a set Process Variables (PVs) that are exported via Channel Access, and to store their values in a MDSplus tree. Every channel can be acquired in either of the following modes:
- Scan mode The channel is read periodically, at a programmable read rate;
- Monitor mode The channel is acquired only when its actual value changes and is therefore exported via the monitor functionality of Channel Access. This is the default and suggested mode of operation;
Data items are stored in the corresponding nodes in the MDSplus tree using segmented data. Received data is buffered in memory until a preset number of samples (defined by the parameter BUF_SIZE) has been received. The number of samples to be stored in memory before being written in the pulse file depends on the rate at which PV values are updated. For PV changing at a low rate it is preferred to store every sample in the pulse file as soon as it is received, that is, define BUF_SIZE equals to 1. For PVs changing at higher rate, using a buffer size greater than 1 improves overall performance since it avoids writing samples individually in the pulse file. The buffer size can be set at any level by defining a node named BUF_SIZE. BUF_SIZE definition is valid for every PV defined in the same tree level and corresponding subtrees, unless overridden by another BUF_SIZE node below. The default value of buffer size is 300 samples.
The command syntax for ChannelArchiver is:
java ChannelArchiver <MDSplus tree> <shot> [buffer_size]
The command requires the specification of a tree from which the program will retrieve all the required information on the groups and the channels to be acquired. It is necessary to include <MDSplus root>/java/classes/mdsobjects.jar in env variable CLASSPATH.
The optional argument buffer_size defines the buffer size unless overridden by the presence of data items named BUF_SIZE.
The definition of the PVs to be monitored is implicitly defined in the target MDSplus tree. ChannelArchiver expects a given structure (subtree) containing a set of items (some mandatory, some optional). The subtree defining a given PV can be anywhere in the pulse file. When launched, ChannelArchiver scans the whole tree in order to recognize subtrees defining PVs to be monitored.
An example of tree struture defining a PV is shown below
In this figure the subtree with root CY01 specifies a PV. The specification is provided by the following nodes:
- REC_NAME (Text, Mandatory) Name of the PV;
- SCAN_MODE (Text, Mandatory) Can be either "SCAN" for cyclic readout or "MONITOR" for monitored data collection;
- VAL (Signal, Mandatory) Acquired values of the data item;
- ALARM (Signal, Mandatory) Alarm severity for the data item. Severity values are stored only when changed;
- EGU (Text, Optional) Engineering units for that data item (typically the value of an IOC record);
- HOPR (Numeric, Optional) High operating range for the data item;
- LOPR (Numeric, Optional) Low operating range for the data item;
- PERIOD (Numeric, Optional) Acquisition period (meaningful only if mode is SCAN);
- BUF_SIZE (Numeric, Optional) Buffer size for this PV.
At any level in the tree data items named BUF_SIZE can be defined. If a value can be read from a node names BUF_SIZE, that value will be used as buffer size for all the PVs defined at the same level or below in the tree hierarchy, unless overridden by another definition of BUF_SIZE at a lower level in the tree hierarchy.
By default, ChannelArchiver operates on local pulse files. If the pulse files are not local, the distributed client configuration allows operating on remote pulse files without any change. However, unless the network is vary fast, there is a performance penalty due to the large number of network transactions for a large number of PVs. The number of network transactions is greatly reduced when operating in the Thin Client configuration. This configuration is enabled in the Channel Archiver by defining the command line option -D mdsip=<mdsip address>[:port].
By default, Channel Archiver opens the specified pulse file and add incoming samples. If new pulse file must be creates, define the command line option -Dcreate-pulse=yes.
Directory <MDSplusRoot>/epics/archiver contains also two jar files (caj-<version>.jar and jca-<version>.jar)implementing the EPICS Channel Access protocol. In order to compile ChannelArchiver.java you need to include these two jar files in CLASSPATH together with the jar file <MDSplusRoot>/java/classes/mdsobjects.jar. Make sure that your version of EPICS is compatible with the version if the two jar files (in case you need to get the compatible versions from the EPICS site).
When ChannelArchiver is running, it is possible to issue the following commands:
- q to quit ChannelArchiver
- i to get information about the currently connected PVs, including the length of the data queues.
More debug messages can be enabled with the command option -Ddebug=yes
MDSplus Channel Access server for EPICS
The MDSplus Channel Access Server exports data contained in pulse files over Channel Access. It is intended to ease the usage of MDSplus for storing configuration data and to let such data be natively available in IOCs. It is also possible to use any EPICS tool (e.g. from CSS) for the graphical configuration set-up, using a MDSplus pulse file as data repository. In this case the presence of the pulse file becomes transparent (both the interface and the IOC records access data over Channel Access), but allows for a unique repository of configuration data, following the data centric philosophy of MDSplus.
The MDSplus Channel Access server can operate in two modes: append and non append. In non append mode data written through Channel Access overwrites previous data for that Process Variable in the pulse file. In append mode, previous data is not deleted, so that the history of that Process Variable is maintained in the pulse file. In the latter case MDSplus segments are used, and the old values together with their associated times (i.e. the EPICS time at which they have been set) are available in the pulse files.
The command line syntax of the MDSplus ChannelAccess server is:
casmds <experiment_name> <shot> [append]
When started, the server scans the pulse file in order to find the defined tag names. It is expected that data associated with a single process variable will be contained in a subtree. The only mandatory data item for this subtree are PV_NAME containing the name of the Process Variable and VAL, containing the actual value of the corresponding PV. If the usage of node VAL is TEXT, the PV will be exported as a text PV, otherwise it is exported as a numeric PV. The other (optional) nodes of the subtree associated with a given Process Variable are:
- DIMS: specifies whether the numeric PV is a scalar or a (multidimensional) array. It is an integer array: if empty or missing, the PV is assumed to be scalar, otherwise it contains for each dimension the corresponding number of elements
- HOPR: operating range definition
- LOW_ALARM: alarm threshold definition
- LOW_WARN: warning threshold definition
- LOW_CTRL: control threshold definition
- LOW_GRAPH: graphical display limits
- UNITS: the units for the PV
- ENUMS : enumerated state strings
Except for VAL, the other PV data items are optional and are read at startup. They are used to provide additional information in the Channel Access protocol as well as for setting the appropriate Alarm and severity definition when PVs are monitored.
The MDSplus Channel Access server is implemented as a set of C++ classes which inherit from the EPICS Channel Access Portable Server. The source files are in <mdsplus_distr_root>/epics/cas. In order to build the MDSplus Channel Access Server the following steps are required:
- Using the EPICS MakeBaseApp perl script build the directory tree and the associated configuration file. Call the application casmds. The command is:
<epics root>/epics/base/bin/<arch>/makeBaseApp.pl -b $EPICS_BASE -t caServer casmds
where <epics root> and <arch> refer to the root directory of EPICS distribution and the used architecture, respectively.
- Copy the source files in <mdsplus_distr_root>/epics/cas to <appRoot>/casmdsApp
- Add the following lines to the Makefile defined in <appRoot>/casmdsApp (where it is assumed that the MDSplus shared libraries are in /usr/local/mdsplus/lib64), replacing the lines starting with casexampleSRCS +=:
SRCS += main.cc SRCS += mdsServer.cc SRCS += mdsPV.cc SRCS += mdsChannel.cc SRCS += pvEntry.cc PROD_LIBS += MdsObjectsCppShr PROD_LIBS += MdsIpShr MdsObjectsCppShr_DIR += /usr/local/mdsplus/lib MdsIpShr_DIR += /usr/local/mdsplus/lib USR_INCLUDES += -I/usr/local/mdsplus/include
- Replace in the Makefile line
PROD_HOST = casexample
PROD_HOST = casmds
within <appRoot>/casmdsApp call make