ChimeraTK-ControlSystemAdapter-DoocsAdapter  01.12.01
ChimeraTK-ControlSystemAdapter-DoocsAdapter

The ChimeraTK-ControlSystemAdapter-DoocsAdapter implements the ChimeraTK Control System Adapter for DOOCS.

Integrating your control system application into DOOCS

Prerequisites:

  • The application has been writen with the ChimeraTK-ApplicationCore library,
  • a working DOOCS environment (see: http://doocs.desy.de).

To integrate the application into DOOCS, it has to be linked against the ChimeraTK-ControlSystemAdapter-DoocsAdapter library. Simply use the add_dependency() cmake macro coming with the ChimeraTK project template, then add ${ChimeraTK-ControlSystemAdapter-DoocsAdapter_LINK_FLAGS} to the CMAKE_LINK_FLAGS and ${ChimeraTK-ControlSystemAdapter-DoocsAdapter_LIBRARIES} to the libraries your executable links against. It is not necessary to change the include path.

In addition, several configuration files have to be provided to your executable at runtime.

DOOCS configuration file

Firstly, all DOOCS servers require the usual DOOCS servername.conf file. A simple example for this file is this:

eq_conf:
oper_uid: -1
oper_gid: 405
xpert_uid: 1000
xpert_gid: 1000
ring_buffer: 10000
memory_buffer: 500
eq_fct_name: "PLAIN_VARIABLE_CREATION_TEST._SVR"
eq_fct_type: 1
{
SVR.RPC_NUMBER: 700000006
SVR.NAME: "PLAIN_VARIABLE_CREATION_TEST._SVR"
SVR.BPN: 6000
}
eq_fct_name: "INT"
eq_fct_type: 10
{
NAME: "INT"
}
eq_fct_name: "SHORT"
eq_fct_type: 10
{
NAME: "SHORT"
}
eq_fct_name: "FLOAT"
eq_fct_type: 10
{
NAME: "FLOAT"
}
eq_fct_name: "DOUBLE"
eq_fct_type: 10
{
NAME: "DOUBLE"
}
eq_fct_name: "UINT"
eq_fct_type: 10
{
NAME: "UINT"
}
eq_fct_name: "USHORT"
eq_fct_type: 10
{
NAME: "USHORT"
}
eq_fct_name: "CHAR"
eq_fct_type: 10
{
NAME: "CHAR"
}
eq_fct_name: "UCHAR"
eq_fct_type: 10
{
NAME: "UCHAR"
}

Replace the RPC number with the number corresponding to your application. You should also change the uid/gid numbers and the name of the server location according to your needs. Finally, you need to have entries for all locations your server should provide. Since the location is a concept which is introduced by DOOCS, the application does not directly define them. Hence, you need to provide a second configuration file which defines how the variable household provided by your application should be mapped to the DOOCS structure.

All locations have the same eq_fct_type 10. As DOOCS will add the properties inside the locations automatically, you do not have to specify them here.

Missing locations will also be added automatically by the adapter, so it is perfectly fine to just have the server location in the config file. Deflaut eq_fct_type is 10, but you can set a new code corresponding to eq_fct_type, see Specify eq_fct_code in the mapping file.

DOOCS adapter mapping file

The mapping of the application variable household on to the DOOCS structure is done with a XML file. The file has to be called applicationName-DoocsVariableConfig.xml (replace applicationName with the name of your application).

If this file is omitted, all variables will be exported to DOOCS, with the highest hierarchy level becoming the location name, and the other levels being converted into a dot-separated property name (i.e. /Module2/SubModule3/property7 becomes DOOCS property //Module2/SubModule3.property7).

An example for the mapping file is:

<?xml version="1.0" encoding="UTF-8"?>
<device_server xmlns="https://github.com/ChimeraTK/ControlSystemAdapter-DoocsAdapter">
<!--Default settings for a spectrum -->
<location name="INT">
<D_spectrum source="TO_DEVICE_ARRAY"/>
<D_spectrum source="FROM_DEVICE_ARRAY" name="MY_RENAMED_INTARRAY"/>
</location>
<location name="SHORT">
<D_array source="TO_DEVICE_ARRAY"/>
<D_array source="FROM_DEVICE_ARRAY" name="MY_RETYPED_SHORT_ARRAY" type="long"/>
</location>
<location name="DOUBLE">
<D_spectrum source="TO_DEVICE_ARRAY"/>
<!--Custom spectrum settings, fixed axis arguments -->
<D_spectrum source="FROM_DEVICE_ARRAY">
<start>123.</start>
<increment>0.56</increment>
</D_spectrum>
</location>
<location name="FLOAT">
<!--Dynamic axis settings -->
<D_spectrum source="TO_DEVICE_ARRAY">
<startSource>/FLOAT/FROM_DEVICE_SCALAR</startSource>
<incrementSource>/DOUBLE/FROM_DEVICE_SCALAR</incrementSource>
</D_spectrum>
<!--We can reuse the same axis settings -->
<D_spectrum source="FROM_DEVICE_ARRAY">
<startSource>/FLOAT/FROM_DEVICE_SCALAR</startSource>
<incrementSource>/DOUBLE/FROM_DEVICE_SCALAR</incrementSource>
</D_spectrum>
<property name="START" source="/FLOAT/TO_DEVICE_SCALAR"/>
<property name="INCREMENT" source="/DOUBLE/TO_DEVICE_SCALAR"/>
</location>
<location name="UINT">
<D_spectrum source="TO_DEVICE_ARRAY"/>
<!--Dynamic axis settings -->
<D_spectrum source="FROM_DEVICE_ARRAY">
<!-- it is possible to use the same startSource and incrementSource from another location -->
<startSource>/FLOAT/FROM_DEVICE_SCALAR</startSource>
<incrementSource>/DOUBLE/FROM_DEVICE_SCALAR</incrementSource>
</D_spectrum>
</location>
<!-- This should not import the variables used for startSource and startIncrement -->
<import>/</import>
</device_server>

Each location is specified with a location tag.The location tag must have one XML attribute:

  • name: Specifies the name of the location

It is possible to specify the eq_fct_code which must match eq_fct_type in the configuration file, see Specify eq_fct_code in the mapping file.

  • code: Optional, specifies eq_fct_code

Properties can be specified in each location with the property tag, or in case of special properties like a D_spectrum with the respective tag. A list of special properties is found in the next section. Each property tag has the following attributes:

  • source: Mandatory, specify the name of the process variable
  • name: Optional, specify the property name. If omitted, the name is derived from the source name by replacing slashes with dots.

Automatic mapping of many variables

As a shortcut, the import tag can be used to map a large number of properties with a single command. The tag doesn't take any sub-tags but should contain a directory name of process variables, which is to be mapped recursively. If the import tag is specified inside a location tag, the specified process variable directory is mapped into this location. The import tag can also appear in the root tag, in which case the first hierarchy level will become the location name. Note that the import will only map variables which have not been mapped before by explicit mapping or other import tags. This is useful to map a big bulk of automatic mapping variables after picking the special cases, which needs to be mapped individually.

The import tag can take optionally one attribute:

  • directory: Add a prefix to the property names, which is separated with a dot from the rest of the property name.

An example with many different automatic mappings is here:

<?xml version="1.0" encoding="UTF-8"?>
<device_server xmlns="https://github.com/ChimeraTK/ControlSystemAdapter-DoocsAdapter">
<!-- Test "renaming" a location, i.e. import something into an a location name that does not
exist as directory on the input. -->
<location name="MY_RENAMED_INTEGER_LOCATION">
<!-- Test renaming of an array -->
<property source="/INT/CONSTANT_ARRAY" name="RENAMED.CONST_ARRAY"/>
<!-- Test importin in this case into a location with a name different from the import-->
<import>/INT</import>
</location>
<!-- Test "Cherry picking": This location does not have an import but only hand-picked variables are in. -->
<location name="CHERRY_PICKED">
<property name="TO_DEVICE_SHORT" source="/SHORT/TO_DEVICE_SCALAR"/>
</location>
<location name="SHORT">
<!-- Test importing and adding a 'directory', i.e. a dot-separated prefix to the beginning of the property name -->
<import directory="myStuff">/SHORT</import>
</location>
<!-- Set the default for has_history to false in one location -->
<location name="USHORT">
<has_history>false</has_history>
<!-- Turn the history back on for one property, although the default is off.-->
<property source="TO_DEVICE_SCALAR">
<has_history>true</has_history>
</property>
<!-- all imported properties will have the history turned off -->
<import>/USHORT</import>
</location>
<!-- Set the default for is_writeable to false in one location.
Intentionally use another location than for the has_history test to avoid missing
confusion in the parser (e.g. is_writeable allways acts on both, has_history has no effec,
but it's not seen because it's always tested together) -->
<location name="UCHAR">
<is_writeable>false</is_writeable>
<!-- Turn the history back on for one property, although the default is off.-->
<property source="TO_DEVICE_SCALAR">
<is_writeable>true</is_writeable>
</property>
<!-- all imported properties will have the history turned off -->
<import>/UCHAR</import>
</location>
<location name="DOUBLE">
<!-- test renaming a scalar-->
<!-- Also tests relative variable names. The input must be in a directory which is identical
top the ocation name, '/DOUBLE' in this case -->
<property source="DATA_TYPE_CONSTANT" name="RENAMED_CONSTANT">
<!-- test turning off the history (no special default set per location, on by default) -->
<has_history>false</has_history>
</property>
<!-- Test adding a scalar from another directory than the one imported. -->
<property source="/FLOAT/TO_DEVICE_SCALAR" name="I_AM_A_FLOAT_SCALAR"/>
<!-- This variable is not renamed and will end with the property name DOUBLE.TEST_TO_DEVICE_SCALAR, hence the DOUBLE will be the location name AND it will appear in the property name -->
<property source="/DOUBLE/TO_DEVICE_SCALAR">
<!-- Test turning off the writeable flag -->
<is_writeable>false</is_writeable>
</property>
<!-- Test importing a directory which has the same name as the location-->
<import>/DOUBLE</import>
</location>
<!-- Test the global import. The location name is the name of the first directory of the input.
Input variables already mentioned explicitly or already imported will not be added. -->
<import>/</import>
</device_server>

Special configuration

There are a number of configuration parameters which can be set on different scopes to control the exact behaviour of the DOOCS properties. All of the following XML tags can appear either directly in the root tag, or in a location tag, or in a property tag (or any tag for a special property, see Secion Special DOOCS properties).

  • has_history: Can be set to false or true (default) If set to true, the properties will have a history, if the property type supports this.
  • is_writeable: If set to false, the property will be forced to be read-only, even if the process variable is writeable.
  • macro_pulse_number_source: Name of process variable which contains the macro pusle number which should be attached to the properties.
  • data_matching: Possible values are none, exact. This is relevant when macro pulse number source is given. The default is exact, which means the server discards data coming in so late that it's version number is overtaken by that of the macro pulse number.
  • persist: Controls behaviour of DOOCS persistency files. This is only important for writable arrays with more than MAX_CONF_LENGTH entries (usually 20). Possible values are true (the default) - always save the array, where long arrays are saved in separate files below hist/ while short arrays go into the server config file; false - do not save the array; auto - default DOOCS behaviour, only arrays with up to 20 entries are saved, in server config file.

ZeroMQ publication

DOOCS properties can be published via ZeroMQ so that clients can be notified about updates in real time. To enable this one simply has to specifiy the publish_ZMQ tag as shown in the following example:

<?xml version="1.0" encoding="UTF-8"?>
<device_server xmlns="https://github.com/ChimeraTK/ControlSystemAdapter-DoocsAdapter">
<!-- It must be irrelevant whether the macro pulse number is processed before or after the variable which is tested by value;
the test cases cover both cases. -->
<data_matching>exact</data_matching>
<macro_pulse_number_source>/UINT/FROM_DEVICE_SCALAR</macro_pulse_number_source>
<location name="INT">
<property source="/INT/FROM_DEVICE_SCALAR" name="FROM_DEVICE_SCALAR">
<publish_ZMQ>true</publish_ZMQ>
</property>
<property source="/INT/FROM_DEVICE_ARRAY" name="FROM_DEVICE_ARRAY">
<publish_ZMQ>true</publish_ZMQ>
</property>
<import>/INT</import>
</location>
<location name="FLOAT">
<D_spectrum source="/FLOAT/FROM_DEVICE_ARRAY" name="FROM_DEVICE_ARRAY">
<start>123.</start>
<increment>0.56</increment>
<publish_ZMQ>true</publish_ZMQ>
</D_spectrum>
<import>/FLOAT</import>
</location>
<location name="UINT">
<property source="/UINT/TO_DEVICE_SCALAR" name="TO_DEVICE_SCALAR"/>
</location>
</device_server>

If the macro_pulse_number_source tag has been used, the macro pulse number will be added to the ZeroMQ header.

Overriding auto-detected types

If the automatically derived data type of the DOOCS property is not fitting, it is possible to override it using the type attribute on the property and D_array tags. type can be one of

  • auto (default)
  • byte
  • short
  • int
  • long
  • float
  • double

For an example, see above in Section DOOCS adapter mapping file.

Special DOOCS properties

Instead of letting the DOOCS adapter automatically decide which DOOCS data type to use, it is possible to specify a particular type. This needs to be done whenever a special DOOCS property type should be used.

D_spectrum

The D_spectrum tag takes the following arguments through sub-tags:

  • start: The x-axis start as a fixed number
  • increment: The x-axis increment between two samples as a fixed number
  • startSource: Name of process variable which should be used as x-axis start
  • incrementSource: Name of process variable which should be used as x-axis increment
  • numberOfBuffers: Create a buffered D_spectrum with a short-term history (so clients can read consistent data across multiple D_spectrum). Requires a configured macro_pulse_number_source.

The D_spectrum tag takes the following arguments through sub-tags:

  • unit : A description of the respective axis. The axis is chosen with the axis property which can either be x or y. It can also contain a "start" and an "end" for the initial display parameters as well as "logarithmic" for switching the scale accordingly. For an example of this see D_xy

For an example, see above in Section DOOCS adapter mapping file.

D_array

The D_array tag takes the following arguments through XML attributes of the D_array tag:

  • type: Override the data type. Can be one of:
    • auto (default)
    • byte
    • short
    • int
    • long
    • float
    • double

For an example, see above in Section DOOCS adapter mapping file.

D_xy

The D_xy tag takes the following arguments through properties:

  • x_source : Name of process variable which should be used for x-axis values
  • y_source : Name of process variable which should be used for y-axis values
  • name : Name of the mapped property The D_xy tag takes the following arguments through sub-tags:
  • description : A description for the XY plot
  • unit : A description of the respective axis. The axis is chosen with the axis property which can either be x or y
<?xml version="1.0" encoding="UTF-8"?>
<device_server xmlns="https://github.com/ChimeraTK/ControlSystemAdapter-DoocsAdapter">
<location name="FLOAT">
<D_xy name="TEST_XY"
x_source="/FLOAT/FROM_DEVICE_ARRAY"
y_source="/DOUBLE/FROM_DEVICE_ARRAY">
<description>Some XY test</description>
<unit axis="x">mm</unit>
<unit axis="y">µs</unit>
</D_xy>
<import>/FLOAT</import>
</location>
<location name="DOUBLE">
<import>/DOUBLE</import>
</location>
<location name="INT">
<property source="/INT/TO_DEVICE_SCALAR" name="TO_DEVICE_SCALAR"/>
</location>
</device_server>

D_ifff

The D_ifff tag takes the following arguments through attributes:

  • i1_source : Name of process variable which should be used for first integer values
  • f1_source, f2_source, f3_source : Name of process variables which should be used for float values
  • name : Name of the mapped property The four mapped variables must provide data-consistent updates, unless data_matching="none" is specified.
<?xml version="1.0" encoding="UTF-8"?>
<device_server xmlns="https://github.com/ChimeraTK/ControlSystemAdapter-DoocsAdapter">
<location name="CUSTOM">
<D_ifff name="IFFF"
i1_source="/INT/FROM_DEVICE_SCALAR"
f1_source="/FLOAT/FROM_DEVICE_SCALAR"
f2_source="/DOUBLE/FROM_DEVICE_SCALAR"
f3_source="/SHORT/FROM_DEVICE_SCALAR">
</D_ifff>
</location>
<import>/</import>
</device_server>

D_iiii

The D_iiii tag takes the following arguments through attributes:

  • source : Name of process variable which should be used for first integer values.
  • name : Name of the mapped property
<?xml version="1.0" encoding="UTF-8"?>
<device_server xmlns="https://github.com/ChimeraTK/ControlSystemAdapter-DoocsAdapter">
<location name="CUSTOM">
<D_iiii name="IIII"
source="/IIII/FROM_DEVICE">
</D_iiii>
</location>
<import>/</import>
</device_server>

D_imagec

The D_imagec (c for compact image) tag takes the following arguments through attributes:

  • source : Name of process variable which contains the data as array of unsigned char. Data consists of an image header defined as ChimeraTK::ImgHeader followed by the encoded pixel values.
  • description: Used as comment for the image, in the meta data.

If data_matching="exact" is set, the provided macropulse number is set as event id in the meta data.

Error reporting

The special tag set_error is allowed only once per location. XML attributes:

  • statusCodeSource : Path to the process variable which should be used for reading error/status codes.

DoocsAdapter will automatically look for an associated variable with error/status messages, and if present, read both consistently. Errors indicated via the status variable will be published via DOOCS set_error function (of the location), which sets the properties ERROR, ERROR.STR, STS.ERROR, STS.NEWERROR, and also logs into LOG, LOG.LAST, LOG_HTML and LOG_HTML.LAST. Compare DOOCS documentation for error properties and propagation to the overall error counting per server, SVR.ERROR_COUNT.

Specify <tt>eq_fct_code</tt> in the mapping file

It is possible to specify the eq_fct_code which must match eq_fct_type in the configuration file with code in the <location> tag of the mapping file.

If eq_fct_type is set in the configuration file, code must have the same number in the mapping file. If the location in the configuration file is missing, you can set your own new code in the mapping file. But if no code is set, the default code is 10. You can set code multiple times, but code must always be consistent. The code must be integer and > 1, since 1 is reserved for server.

An example configuration file and mapping file with the code specified:

The location DOUBLE has already the code 10 specified in the configuration file. If you set the code in the mapping file, it must have 10 as well.

The location CREATED will be created new with the default code of 10.

The location NEW will be created new with code of 12.

The location FLOAT is only specifed in the configuration file but will be also created with code 11.