3. MAL ICD Generation

Document ID:

Revision:

1.7

Last modification:

March 18, 2024

Status:

Release

Repository:

https://gitlab.eso.org/cii/info/cii-docs

File:

mal_icd.rst

Project:

ELT CII

Owner:

Marcus Schilling

Document History

Revision

Date

Changed/ reviewed

Section(s)

Modification

0.1

2019-02-21

dkumar

All

Created.

1.0

2019-02-26

dkumar

All

Review, updated missing sections.

1.1

2019-04-02

mvitorovic

6

Added description for topics.

1.2

2019-04-10

msekoranja, dkumar

All

Review, updated ICD limitations

1.3

2019-04-24

dkumar

6.3, 6.4

Updated topics namespace names.

1.4

2019-06-06

msekoranja

4.9

Referencing types from other packages note added.

1.5

2023-03-15

mschilli

3.5

Info about icd-gen splitter

1.6

2023-03-30

rleao

3.4.8

arrays in different middlewares

1.7

18.03.2024

mschilli

0

Public doc

Confidentiality

This document is classified as Public.

Scope

This document is a manual for the Interface Control Document language of the ELT Core Integration Infrastructure software.

Audience

This document is aimed at Users and Maintainers of the ELT Core Integration Infrastructure software.

Glossary of Terms

API

Application Programmers Interface

CII

Core Integration Infrastructure

MAL

Middleware Abstraction Layer

ICD

Interface Control Document

References

  1. Cosylab, ELT CII MAL Transfer document, CSL-DOC-18-168015, version 1.8

  2. Cosylab, ELT CII MAL API User’s Manual, CSL-DOC-17-150198, version 2.1

  3. Cosylab, Interface Control Document, Specification, CSL-DOC-17-147262, version 1.6

  4. Cosylab, Data Addressing Specification, CSL-DOC-17-147264, version 1.2

3.1. Overview

This document is a user manual for developing Interface Control Documents, specifically Type Definition Documents holding ICD types.

3.2. Installation

See ELT CII MAL Transfer document [1], Chapter 1.2 on how to build and install elt-mal.

3.2.1. Prerequisites

In order to use icd generation the following prerequisites must be fulfilled:

  • CII MAL prerequisites, see ELT CII MAL Transfer document [1], Chapter 1.1.

  • Installed elt-mal.

3.3. Editing ICD file in Eclipse

Developing Interface Control Documents involves writing XML documents. Developer is encouraged to use a XML editor that has support for XML content assist and support for a schema validation. Eclipse that is part of ESO ELT Development Environment has support for editing XML files with XML content assist and schema validation.

See more at https://help.eclipse.org/oxygen/index.jsp?topic=%2Forg.eclipse.wst.xmleditor.doc.user%2Ftopics%2FcworkXML.html.

For the purposes of this user guide, complete the following steps which will enable support for XML content assist and schema validation for icdDemo.xml within Eclipse:

  1. Open Eclipse (/opt/eclipse/oxygen/eclipse/eclipse)

  2. Click File > New > Project.

  3. Select General > Project and click Next.

  4. Enter icd-demo as ‘Project name’ and click Finish.

  5. To import the ICD XML schemas into the workbench, click File > Import.

  6. Select General > File System and click Next.

  7. Click Browse on the next page of the wizard to select the directories from which you would like to add the XML schemas (i.e. $INTROOT/interface/schemas)

  8. Select check box on ‘schemas’ which will import all schemas under the directory $PREFIX/interface/schemas.

  9. Make sure that option ‘Create top-level folder’ is selected and then click Finish.

  10. Next step will create a Waf package named icd containing icdDemo.xml. Open the terminal and execute the following commands:

mkdir -p ~/icd-demo/icd/src

echo '<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">
</types>' > ~/icd-demo/icd/src/icdDemo.xml

  echo 'from wtools.module import declare_malicd
declare_malicd()' > ~/icd-demo/icd/wscript
  1. XML content assist and schema validation for icdDemo.xml will work within Eclipse only when the file icdDemo.xml is beside directory schemas/ in the Eclipse project. A soft link needs to be created in <user_eclipse_worskpace>/icd-demo, pointing to the icdDemo.xml that is part of Waf package. Open the terminal and execute the following commands (replace user_eclipse_workspace with a real path):

cd <user_eclipse_workspace>/icd-demo/

ln -s ~/icd-demo/icd/src/icdDemo.xml .
  1. Refreshing the Eclipse project (pressing F5) should show the icdDemo.xml as part of the icd-demo Eclipse project.

Support for the XML content assist should work by placing the cursor into the type’s element body and pressing Ctrl + Space. The schema validity for icdDemo.xml is being checked as you type or it can be activated manually by Right-clicking on your file in the Navigator view and selecting Validate. Figure 1 is showing the XML content assist and a schema validation error (invalid package name) when editing the icdDemo.xml.

image7

Figure 1: XML content assist and schema validation on icdDemo.xml

3.4. ICD Building blocks

Interface Control Document defines two types of XML documents [3], and this document is describes Type definition document ([3], 1.1) that contains structured and interface types in chapters 4 and 5. Topic and interface definition document ([3], 1.2) is described in chapter 6.

ICD Type definition document is composed of:

  1. Packages that group related types and prevent naming conflicts on similarly named types.

  2. Structures that group data elements together under one name. These data elements, known as members, can be a primitive type or other complex types such as structures and unions.

  3. Basic types are primitive programming language types (including string) and standard ICD types (blob, timestamp).

  4. Enumerations that are distinct types whose value is restricted to a range of values that include several explicitly named constants (“enumerators”).

  5. Unions are a special types that can hold only one of its data members at a time.

  6. Interfaces describe related methods belonging to the same interface.

  7. Exceptions define exceptional events that occur during the execution of interface methods.

  8. Constants which are values used in the elements and attributes where a primitive value would be used.

Within one package types with duplicate names are not allowed. In addition some keywords are reserved (see [3], section 1.1.8.1)

3.4.1. Package

All ICD types belong to a package. There are no package-less types. Package has a non-empty unqualified name (i.e. must not contain other package names delimited with scope resolution operator ::). Package can include other packages but only the most inner package can hold types. ICD XML schema makes sure that the package constraints are maintained in the generation phase but also while the developer is creating the ICD in IDE (i.e. Eclipse).

Listing 1 and Listing 2 contain an example of a single and a nested package.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">
  <package name="elt">
    <!-- type definition content -->
  </package>
</types>

Listing 1: Single package

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">
    <package name="icdDemo">
      <!-- type definition content -->
    </package>
  </package>
</types>

Listing 2: Nested package

See Interface Control Document Specification for an example how package is mapped to Java and C++ ([3], 1.3.5).

3.4.2. Basic types

Basic types define:

  1. Primitive types of members in structures and unions.

  2. Types of union discriminators.

  3. Define method arguments of primitive types or constant types.

Only basic types and enums can be keys in structures.

Basic types are:

  • boolean, boolean primitive type holding true or false.

  • int8_t, signed integer type with width of exactly 8 bits.

  • int16_t, signed integer type with width of exactly 16 bits.

  • int32_t, signed integer type with width of exactly 32 bits.

  • int64_t, signed integer type with width of exactly 64 bits.

  • uint8_t, unsigned integer type with width of exactly 8 bits.

  • uint16_t. signed integer type with width of exactly 16 bits.

  • uint32_t, unsigned integer type with width of exactly 32 bits.

  • uint64_t, unsigned integer type with width of exactly 64 bits.

  • float, single precision floating point type IEEE-754, 32 bit.

  • double, double precision floating point type. IEEE-754 64 bit.

  • string, string of characters. Length upper limit is 256 Bytes.

  • blob, stream of bytes.

  • timestamp, timestamp.

Listing 3 is showing a usage of basic types in different structured types and constants.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">
  <package name="elt">

      <struct name="SimpleStruct">
     <member name="boolval" type="boolean"/>
     <member name="int8val" type="int8_t" key="true"/>
     <member name="uint8val" type="uint8_t" key="true"/>
   </struct>

   <const name="int8Const" type="int8_t" value="1"/>
   <const name="floatConst" type="float" value="6.4523424"/>

   <union name="SimpleUnion">
        <discriminator type="uint8_t"/>
    <case>
      <caseDiscriminator value="0"/>
      <member name="foo" type="string"/>
    </case>
    <case>
      <caseDiscriminator value="1"/>
      <member name="bar" type="int8_t"/>
    </case>
  </union>
 </package>
</types>

Listing 3: Usage of basic types for members in a structure, in constants and member of unions

3.4.3. Constants

Constants define values used in the elements and attributes where a primitive value would be used.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">
     <const name="boolconst" type="boolean" value="true"/>
     <const name="int8const" type="int8_t" value="1"/>
     <const name="uint8const" type="uint8_t" value="2"/>
     <const name="int16const" type="int16_t" value="-3"/>
     <const name="uint16const" type="uint16_t" value="100"/>
     <const name="int32const" type="int32_t" value="-3200"/>
     <const name="uint32const" type="uint32_t" value="100"/>
     <const name="floatconst" type="float" value="100.0"/>
  <const name="stringconst" type="string" value="batman"/>
</package>
</types>

Listing 4: Defining constants

3.4.4. Enumeration (Enum)

Enumeration is a distinct type whose value is restricted to a range of values explicitly named constants (enumerators). Enumeration has a non-empty unqualified name and at least one enumerator. The enumeration type is a building block for unions and can be included as a member of a structure and member of a union.

Listing 5 is showing an example of simple command modeled as an enumeration.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">
      <enum name="Command">
     <enumerator name="START_COMMAND"/>
     <enumerator name="STOP_COMMAND"/>
   </enum>
 </package>
</types>

Listing 5: Enumerator Command

See Interface Control Document Specification for an example how enumeration is mapped to Java and C++ ([3], 1.3.1).

3.4.5. Union

Union is a special type that can hold only one of its data members at a time. The discriminator sets which member holds a value. Only numeric primitives and enums can be union discriminators. Union members can be: primitive types, unions, structures and enums. No arrays are allowed as union members.

Listing 6 and Listing 7 are showing examples of a union with a primitive type discriminator and a union with an enumerator as a union discriminator.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">
  <package name="elt">
   <union name="SimpleUnion">
        <discriminator type="uint8_t"/>
    <case>
      <caseDiscriminator value="0"/>
      <member name="foo" type="string"/>
    </case>
    <case>
      <caseDiscriminator value="1"/>
      <member name="bar" type="int8_t"/>
    </case>
  </union>
 </package>
</types>

Listing 6: Union with numeric primitive type discriminator

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">


      <enum name="Command">
     <enumerator name="START_COMMAND"/>
     <enumerator name="STOP_COMMAND"/>
   </enum>

   <union name="CommandData">
        <discriminator type="nonBasic" nonBasicTypeName="Command"/>
    <case>
      <caseDiscriminator value="START_COMMAND"/>
      <member name="startCommandData" type="string"/>
    </case>
    <case>
      <caseDiscriminator value="STOP_COMMAND"/>
      <member name="stopCommandData" type="int8_t"/>
    </case>
  </union>
 </package>
</types>

Listing 7: Union with enum discriminator

See Interface Control Document Specification for an example how union is mapped to Java and C++ ([3], 1.3.3).

3.4.6. Structure (struct)

Structure groups data elements (members) together under one name. Structure member can have a basic type or other structure type, union or enumeration type. Every structure can be assigned a key. A key is a set of fields (of primitive types) that uniquely identifies one instance. This allows programmers to publish/retrieve/filter data based on their instance. Only basic types and enums can be keys in structures. Structure can be extended. Extending structure means COPY (not inheritance!) from extended, including the keys.

Listing 8, Listing 9, Listing 10 and Listing 11 show typical type definitions of a structure.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">

      <struct name="SimpleStruct">
     <member name="boolval" type="boolean"/>
     <member name="int8val" type="int8_t" key="true"/>
     <member name="uint8val" type="uint8_t" key="true"/>
     <member name="int16val" type="int16_t"/>
     <member name="uint16val" type="uint16_t"/>
     <member name="int32val" type="int32_t"/>
     <member name="uint32val" type="uint32_t"/>
   </struct>
</package>
</types>

Listing 8: Structure with basic types as members

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">

   <enum name="Command">
     <enumerator name="START_COMMAND"/>
     <enumerator name="STOP_COMMAND"/>
   </enum>

      <struct name="ArrayStruct">
     <member name="boolvalArray" type="boolean" arrayDimensions="(16)"/>
     <member name="int8valArray" type="int8_t" arrayDimensions="(16)"/>
     <member name="CmdArray" type="nonBasic"
             nonBasicTypeName="Command" arrayDimensions="(20)"/>
   </struct>
</package>
</types>

Listing 9: Structure with arrays as members

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">

   <struct name="SimpleStruct">
     <member name="boolval" type="boolean"/>
     <member name="int8val" type="int8_t" key="true"/>
   </struct>

      <struct name="ComplexStruct">
     <member name="boolval" type="boolean"/>
     <member name="int8val" type="int8_t"/>
     <member name="nestedStruct" type="nonBasic"
             nonBasicTypeName="SimpleStruct"/>
   </struct>
</package>
</types>

Listing 10: Structure holding another structure as a member.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">

   <struct name="BaseStruct">
     <member name="boolval" type="boolean"/>
     <member name="int8val" type="int8_t" key="true"/>
   </struct>

      <struct name="ExtendedStruct" baseType="BaseStruct">
     <member name="boolval" type="boolean"/>
     <member name="int8val" type="int8_t"/>
     <member name="nestedStruct" type="nonBasic"
             nonBasicTypeName="SimpleStruct"/>
   </struct>
</package>
</types>

Listing 11: Extending a structure.

See Interface Control Document Specification for an example how structure is mapped to Java and C++ ([3], 1.3.2).

3.4.7. Interface and Exception

A server exposes to the network one or more instances of ICD-defined interface (a service). A client connects to the server and invokes one or more methods (method element) on that service. One reserved method name is “serviceDescription” - that method is implemented by the ICD and cannot be declared in an ICD interface definition. Methods defined in ICD Interface can throw (throws attribute) exceptions raising exceptional events during the execution of methods. Exception can have optional members with additional exception data. Exception type cannot publicly extend other exception types, while the interface can be extended (extends element). Extending interface means copying from the extended interface. Methods that are part of the interface can have zero or more arguments (argument attribute). Methods return results (returnType attribute). When multiple responses (results) are needed, asynchronous method invocation (AMI) MAL support can be used (methodType attribute). Declaring the AMI method with a void return-type is banned and it will produce a compilation error.

Listing 12 shows a typical service definition with different types of methods.

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">

   <struct name="SpeedArray" trace="true">
     <member name="values" type="float" arrayDimensions="(10)"/>
   </struct>

   <enum name="Command">
     <enumerator name="START_COMMAND"/>
     <enumerator name="STOP_COMMAND"/>
   </enum>

   <exception name="TooFast">
     <member name="speed" type="float"/>
   </exception>

   <interface name="Logger">
  <method name="setLevel" returnType="void">
       <argument name="level" type="uint8_t"/>
     </method>
   </interface>

      <interface name="RobotControl">

     <extends interfaceName="Logger"/>

     <method name="command" returnType="void">
       <argument name="com" type="nonBasic" nonBasicTypeName="Command"/>
     </method>

     <method name="setSpeed" returnType="float" throws="TooFast">
       <argument name="value" type="float" />
     </method>
     <method name="getSpeed" returnType="float" />
     <method name="validSpeedValues" returnType="boolean">
       <argument name="values" type="float" arrayDimensions="(10)" />
     </method>

     <method name="systemCheck" returnType="string" methodType="ami"/>

     <method name="setStrVec" returnType="void">
       <argument name="strvec" type="string" arrayDimensions="(5)"/>
     </method>

     <method name="getStrVec" returnType="string" arrayDimensions="(5)"/>

   </interface>
</package>
</types>

Listing 12: RobotControl service definition

See Interface Control Document Specification for an example how an exception and an interface are mapped to Java and C++ ([3], 1.3.4 and 1.3.6).

3.4.8. Arrays

Arrays are specified with an attribute arrayDimensions on:

  • Member of structured type (struct, union, exception): member of a structured type is an array.

  • Method return type: return type of method is an array.

  • Method parameter: method parameter is an array

Arrays are one of:

  • BOUNDED: arrayDimensions=”(dim1, dim2, …, dimN)” where dim1, dim2, …, dimN > 0

  • FIXED: arrayDimensions=”[dim1, dim2, …, dimN]” where dim1, dim2, …, dimN > 0

Fixed array is sent over the wire in full capacity, regardless how many elements are actually stored the array. On the other hand, in a bounded array, only currently stored elements will be sent, however the middleware might reserve entire capacity to avoid reallocation at runtime. Setting boundaries too big might cause in high memory usage.

It is also relevant to warn that some types of communication will not comply with the Bounded/Fixed array types and it’s dimensional definitions. That is the case of ZPB communication method, because the actual array will be a repeated field in the protobuf. The following table shows how the array behave in a ZPD and DDS protocols:

Protocol/Pattern

4 Passed

2 Passed

1 Passed

Empty

ZPB RR Bounded (2)

4 Received

2 Received

1 Received

Empty

ZPB RR Fixed [2]

4 Received

2 Received

1 Received

Empty

ZPB PS Bounded (2)

4 Received

2 Received

1 Received

Empty

ZPB PS Fixed [2]

4 Received

2 Received

1 Received

Empty

DDS PS Bounded (2)

4 Received

2 Received

1 Received

Empty

DDS PS Fixed [2]

Exc on Publish

2 Received

Exc on Publish

Exc on Publish

Next is an ICD XML example file that shows how to declare an array:

<?xml version="1.0" encoding="UTF-8"?>
<types xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_type_definition.xsd">

  <package name="elt">

   <struct name="SpeedArray" trace="true">
     <member name="values" type="float" arrayDimensions="(10)"/>
   </struct>

   <struct name="SampleMultidimension">
     <member name="matrixValue" type="string" arrayDimensions="[3,2]"/>
   </struct>

  </package>
</types>

Listing 13: Example of a Structure Array Specification

3.5. ICD Generation

When the ICD Type definition documents are written, MAL agnostic and MAL middlelayer specific types need to be generated based on the types defined in them. The ICD generator (icd-gen tool installed in $PREFIX/bin) must never be used directly by the user. ICD generation has been integrated into waf/wtools.

User needs to create a waf package composed of ICD Type definition document stored in src/ directory and use declare_malicd() wtools support in package wscript file. During installation process all ICDs gets installed in $PREFIX/interface/icd directory so that they can be included by other ICDs.

During the generation process, the icd generator splits ICD files into smaller chunks. This was added as an optimisation for memory allocation and compilation duration, and is fully transparent to the users. Should there ever be a need, you can enable debug-logs from the splitter, set the environment variable ICD_PYTHON_CPP_SPLITTER_DEBUG to non-empty. To prevent the splitting, set the environment variable ICD_WITHOUT_PYTHON_CPP_SPLITTER to non-empty.

See ELT CII MAL API User’s Manual [2], Chapter 7.1 on how to create a CII application using waf/wtools named icd-demo (containing icdDemo.xml) that was created in Chapter 3.

3.6. Topic and interface definition document

The ICD generation tool can also be used to parse the Topic and interface definition document and generate language specific source files that expose various parameters of the definition to the developer as constant values that can be used application source code.

This type of document defines the following elements per each subsystem:

  1. Messaging pattern that may be publish/subscribe topics or method definitions for interfaces.

  2. Quality of Service parameters for both of the above.

  3. Performance characteristics for both of the above.

  4. Type and interface names; these must be defined in the type definition document.

  5. Middleware mappings; the document lists only the names of the protocols that apply.

  6. Address URI as defined in [4].

In order to enable topic and interface definition generation use –topic (-t) command-line option when calling icd-gen.

3.6.1. Subsystems

Each document lists on or multiple subsystems. At the moment the only subsystem type supported is device.

<?xml version="1.0" encoding="UTF-8"?>
<topics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_topic_definition.xsd">
  <device name="Dev1">
    <!-- subsystem definition content -->
  </device>
  <device name="Dev2">
    <!-- subsystem definition content -->
  </device>
</topics>

Listing 16: Subsystems (devices)

3.6.2. Messaging pattern

Each subsystem may contain one or multiple publish/subscribe topics or service interface definitions. The element for publish/subscribe topic is named pubsub_topic, and the element for the service interface definition is named service.

<?xml version="1.0" encoding="UTF-8"?>
<topics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_topic_definition.xsd">
  <device name="Dev1">
    <pubsub_topic>
      <!-- topic definition content -->
    </pubsub_topic>
  </device>
  <device name="Dev2">
    <service name="MSA1" interface="MSAzimuth">
      <!-- subsystem definition content -->
    </service>
  </device>
</topics>

Listing 17: Topic and service definition

3.6.3. Publish subscribe topic

The publish/subscribe topic definition contains the following required elements:

  1. topic_name – this element defines the name of the topic.

  2. topic_type – this element defines the type name of the structure defined in the type definition document (see chapter 4).

  3. address_uri – this element contains the MAL address URI.

  4. qos – this element defines the Quality of Service attributes.

  5. performance - this element defines the performance attributes.

  6. mal – this element defines provider specific elements, however it is not processed by the tool.

For a detailed description the elements and their attributes please see [3].

Based on the XML definition from Listing 18 the tool generates the code shown in Listing 19, Listing 20 and Listing 21.

<?xml version="1.0" encoding="UTF-8"?>
<topics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_topic_definition.xsd">
  <device name="Dev1">
    <pubsub_topic>
      <topic_name>Az:Pos_Actual</topic_name>
      <topic_type>Pos_Actual</topic_type>
      <address_uri>dds.ps://m1/Pos_Actual?p1=v1&amp;p2=v2</address_uri>
      <qos latency_ms="0.1" deadline_ms="20" />
      <performance rate_hz="0.2" latency_ms="25" synchronous="false" />
      <mal>
        <dds />
      </mal>
    </pubsub_topic>
  </device>
</topics>

Listing 18: Topic definition (full)

For all Java classes the package name is predefined. The device is a public class with static class members for all defined topics (and service interfaces). The name of the topic class is derived from the topic_name element with the PubSub suffix. The class member constants are derived from the other elements listed above.

package elt.icd.topicdefinition;

public class Dev1 {

    public static class AzPosActualPubSub {
        public static String TYPE = "Pos_Actual";
        public static String ADDRESS_URI = "dds.ps://m1/Pos_Actual?p1=v1&p2=v2";
        public static double QOS_LATENCY_MS = 0.1;
        public static double QOS_DEADLINE_MS = 20.0;
        public static double PERFORMANCE_RATE_HZ = 0.2;
        public static double PERFORMANCE_LATENCY_MS = 25;
        public static boolean PERFORMANCE_SYNCHRONOUS = false;
    } // AzPosActualPubSub

} // Dev1

Listing 19: Topic Java code

For C++ the tool generates only the header file. The top 3 namespaces are predefined. The device is a namespace with namespace members for all defined topics (and service interfaces). The name of the topic namespace is derived from the topic_name element with the PubSub suffix. The constants are derived from the other elements listed above.

#ifndef __DEV_1_HPP
#define __DEV_1_HPP


namespace elt
{
namespace icd
{
namespace topicdefinition
{

namespace Dev1
{

  namespace AzPosActualPubSub
  {
    constexpr char[] type = "Pos_Actual";
    constexpr char[] addressUri = "dds.ps://m1/Pos_Actual?p1=v1&p2=v2";
    constexpr double qosLatencyMs = 0.1;
    constexpr double qosDeadlineMs = 20.0;
    constexpr double performanceRateHz = 0.2;
    constexpr double performanceLatencyMs = 25;
    constexpr bool performanceSynchronous = false;
  } // namespace AzPosActualPubSub

} // namespace Dev1

} // namespace topicdefinition
} // namespace icd
} // namespace elt

#endif // __DEV_1_HPP

Listing 20: Topic C++ code

For Python the tool generates a class for each device with class members for all defined topics (and service interfaces). The name of the topic class is derived from the topic_name element with the PubSub suffix. The members are derived from the other elements listed above.

class Dev1:

  class AzPosActualPubSub:
    type = "Pos_Actual";
    addressUri = "dds.ps://m1/Pos_Actual?p1=v1&p2=v2";
    qosLatencyMs = 0.1;
    qosDeadlineMs = 20.0;
    performanceRateHz = 0.2;
    performanceLatencyMs = 25;
    performanceSynchronous = False;

  # end AzPosActualPubSub

# end Dev1

Listing 21: Topic Python code

3.6.4. Service interface

The attributes of each service definition are the service instance name and the interface type name. It contains the following required elements:

  1. address_uri – this element contains the MAL address URI.

  2. performance – this element defines the performance attributes.

  3. qos – this element defines the Quality of Service attributes.

  4. is_configuration – the configuration has no defined performance constraints and represents aspects of the Local Control System software which must be controllable externally from the CCS. This element is optional.

  5. mal – this element defines provider specific elements, however it is not processed by the tool.

  6. methods – this element contains all the method definitions for this service.

The methods element contains one or many method elements. Each element has a name attribute specifying the method name. Each method contains the following optional elements which override the values listed above:

  1. performance – this element overrides the performance attributes.

  2. qos – this element overrides the Quality of Service attributes.

  3. is_configuration – this element overrides the configuration setting.

<?xml version="1.0" encoding="UTF-8"?>
<topics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schemas/icd_topic_definition.xsd">
  <device name="Dev2">
    <service name="MSA1" interface="MSAzimuth">
      <address_uri>zpb.rr://m4lsv.pl.eso.org:5002</address_uri>
      <performance rate_hz="0.2" latency_ms="25" synchronous="false" />
      <qos connection_timeout_sec="0.1" reply_timeout_sec="20" />
      <mal>
        <zpb />
      </mal>
      <methods>
        <method name="SomeMethodThatIsPartOfMSAzimuth">
          <performance rate_hz="10" latency_ms="2" synchronous="false" />
          <qos connection_timeout_sec="0.1" reply_timeout_sec="20" />
        </method>
        <method name="GetLogLevel">
          <is_configuration>true</is_configuration>
        </method>
      </methods>
    </service>
  </device>
</topics>

Listing 22: Service definition (full)

For all Java classes the package name is predefined. The device is a public class with static class members for all defined service interfaces (and topics). The name of the service class is derived from the service name attribute with the Service suffix. The Methods class name is also predefined. The class member constants are derived from the other elements listed above.

package elt.icd.topicdefinition;


public class Dev2 {

    public static class MSA1Service {
        public static String INTERFACE = "MSAzimuth";
        public static String ADDRESS_URI = "zpb.rr://m4lsv.pl.eso.org:5002";
        public static double PERFORMANCE_RATE_HZ = 0.2;
        public static double PERFORMANCE_LATENCY_MS = 25;
        public static boolean PERFORMANCE_SYNCHRONOUS = false;
        public static double QOS_CONNECTION_TIMEOUT_SEC = 0.1;
        public static double QOS_REPLY_TIMEOUT_SEC = 20.0;
        public static class Methods {
            public static class SomeMethodThatIsPartOfMSAzimuth {
                public static double QOS_CONNECTION_TIMEOUT_SEC = 0.1;
                public static double QOS_REPLY_TIMEOUT_SEC = 20.0;
                public static double PERFORMANCE_RATE_HZ = 10.0;
                public static double PERFORMANCE_LATENCY_MS = 2;
                public static boolean PERFORMANCE_SYNCHRONOUS = false;
            } // SomeMethodThatIsPartOfMSAzimuth
            public static class GetLogLevel {
                public static boolean IS_CONFIGURATION = true;
            } // GetLogLevel
        } // Methods
    } // MSA1Service

} // Dev2

Listing 23: Service Java code

For C++ the tool generates only the header file. The top 3 namespaces are predefined. The device is a namespace with namespace members for all defined service interfaces (and topics). The name of the service namespace is derived from the service name attribute with the Service suffix. The Methods namespace is also predefined. The constants are derived from the other elements listed above.

#ifndef __DEV_2_HPP
#define __DEV_2_HPP


namespace elt
{
namespace icd
{
namespace topicdefinition
{

namespace Dev2
{

  namespace MSA1Service
  {
    constexpr char[] interface = "MSAzimuth";
    constexpr char[] addressUri = "zpb.rr://m4lsv.pl.eso.org:5002";
    constexpr double performanceRateHz = 0.2;
    constexpr double performanceLatencyMs = 25;
    constexpr bool performanceSynchronous = false;
    constexpr double qosConnectionTimeoutSec = 0.1;
    constexpr double qosReplyTimeoutSec = 20.0;

    namespace Methods
    {
      namespace SomeMethodThatIsPartOfMSAzimuth
      {
        constexpr double performanceRateHz = 10.0;
        constexpr double performanceLatencyMs = 2;
        constexpr bool performanceSynchronous = false;
        constexpr double qosConnectionTimeoutSec = 0.1;
        constexpr double qosReplyTimeoutSec = 20.0;
      } // namespace SomeMethodThatIsPartOfMSAzimuth
      namespace GetLogLevel
      {
        constexpr bool isConfiguration = true;
      } // namespace GetLogLevel
    } // namespace Methods
  } // namespace MSA1Service

} // namespace Dev2

} // namespace topicdefinition
} // namespace icd
} // namespace elt

#endif // __DEV_2_HPP

Listing 24: Service C++ code

For Python the tool generates a class for each device with class members for all defined service interfaces (and topics). The name of the service class is derived from the service name attribute with the Service suffix. The Methods class name is also predefined. The members are derived from the other elements listed above.

class Dev2:

  class MSA1Service:
    interface = "MSAzimuth";
    addressUri = "zpb.rr://m4lsv.pl.eso.org:5002";
    performanceRateHz = 0.2;
    performanceLatencyMs = 25;
    performanceSynchronous = False;
    qosConnectionTimeoutSec = 0.1;
    qosReplyTimeoutSec = 20.0;

    class Methods:
      class SomeMethodThatIsPartOfMSAzimuth:
        performanceRateHz = 10.0;
        performanceLatencyMs = 2;
        performanceSynchronous = False;
        qosConnectionTimeoutSec = 0.1;
        qosReplyTimeoutSec = 20.0;

      class GetLogLevel:
        isConfiguration = True;

    # end Methods
  # end MSA1Service

# end Dev2

Listing 25: Topic Python code