Skip to main content
Skip table of contents

Adapter Protocol (sMQTT)

1.1 Adapters

Adapters link OT-Device protocols and the MQTT-based messaging within the SICON.OS. Adapters can either run as software modules within the SICON.OS (“internal adapters”) or as distributed modules in the OT-devices themselves (“external adapters”).

1.2 Devices

Every adapter represents one or more devices in a hierarchical structure. The root device is called “main”.

Device Descriptions are used in 2 different formats:

  • IODD: for IO-Link devices

  • SDD: the proprietary SICON.OS device description format, can be used to

    • describe a non-IO-Link device completely

    • describe additional information for IO-Link devices that is not contained in the IODD

2. MQTT Protocol

2.1 General recommendations for MQTT clients

Since the development of this specification is still ongoing and requirements are expected to change somewhat, all MQTT clients should be implemented with a good level of tolerance towards incoming data. In particular:

  • Messages on unknown or unsupported subtopics should be ignored without further reaction

  • Messages with zero-length payload should be ignored without further reaction

  • Missing or incorrectly specified data in a message: whenever possible, an internal default value for that data should be used and the message processed anyway. If no reasonable default value can be defined for a required parameter, the message should be ignored.

  • When waiting for a certain type of message, there should be a way to exit this wait condition in case the message never arrives, usually a timeout with fallback to a previous or idle state.

2.2 Connection Settings

Unless otherwise noted, the following methods and settings will be used by all mqtt clients:

  • Connections to the broker are started with QoS = 0 and cleanSession = true

  • The keepAlive feature shall be used with the broker with a timeout of 10 seconds. This feature allows both broker and client to detect disconnections and react accordingly. Specifically, upon client disconnect the Last Will and Testament (LWT) shall be used as well.

2.3 Topic Trees

Overview of the topic trees used in SICON.OS

  • mqtt/status/+ – Status information of internal services

  • services/[recipient]/[sender]/# - Certain commands between services

  • adapterConfig/[recipient]/[sender]/+ - Management of adapters

  • adapter/[recipient]/[sender]/+ - Management of devices

  • device/[DevID]/+ - Public device data

2.4 JSON

All MQTT messages in this protocol use JSON in the message body.

2.5 Data Types

The values of parameter objects are always represented as strings in JSON. However within these strings, we use a set of data types derived from the IO-Link specification:

DataType Name

Format

Example

BooleanT

Fixed values: “True” and “False”, length 8 bit

”True”

IntegerT

Signed integer as decimal, length 2 to 64 bit

”-688”

UIntegerT

Unsigned integer as decimal, length 2 to 64 bit

”5322”

Float32T

IEEE 754-1985 32-bit single precision

As described in XML schema

”-12.78e-2”

TimeT

yyyy-mm-dd[Thh:mm:ss[.fff]] (where fff = fraction of a second, up to millisecond), length 64 bit

“2019-01-24T17:06:30”

TimespanT

[+-]?PT\d+(\.\d{1,3})?S, length 64 bit

“-PT3.412S”

StringT

ASCII format, 0-232 bytes

”Hello world!”

HexString

Stream of hex-bytes without any punctuation or spaces (2 characters per byte, letters are caps) Byte order is dependent on target device.

”00AECF34”

OctetStringT

String of hex-bytes in “0x…” format, comma-separated, see IODD-spec.

”0x00, 0xAE, 0xCF, 0x34”

The complex data types “ArrayT” and “RecordT” from the IODD specification are not used in this protocol. When they occur in a device, the data are represented by the individual members as subindices or the whole object as a HexString.

2.6 Data Formatting

In addition to a data type, data objects can have additional attributes that govern how the raw data from the OT devices are to be represented within SICON.OS and to the user:

  • Gradient, Offset: If present they are represented as Float32T and are used to scale the device data in the following way:

<Data format in gateway> = Gradient x <Raw data from device> + Offset

  • Resolution: Dec|Dec.1|Dec.2|Dec.3|Hex|Bin

  • Unit: to represent the physical unit of a value, given as a string. E.g. “unit”:”mbar”.

Data Formatting: allowed combinations of DataType, DisplayFormat, Gradient and Offset

2.7 Acknowledgment of message receipt

A number of mqtt messages, mainly the commands to control adapters, shall be acknowledged by the recipient. This is also used as a handshake to control sequential message flow.

Acknowledgment messages are formed using the following scheme when the mapper sends a request to an adapter:

Command topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/[command]

Acknowledgment topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/[command]

Acknowledgment payload:

{“Value”:”ack|nak”}

 

In the remainder of this document, the term “requires an acknowledgment message” shall refer to using this scheme.

2.8 Return codes

The error codes for reading and writing stat data are defined based on the “additional code” values of ISDU responses in IO-Link. That means in most cases an adapter for an IO-Link-Master can just forward the value it has received from the IO-Link device.

Code (dec)

Meaning

0

OK

17

Index not available

18

Subindex not available

35

Access denied (index not writable or device is locked etc.)

48

Value out of range

49

Value greater than limit

50

Value less than limit

51

Value too long (size of data)

52

Value too short (size of data)

53

Function not available

54

Function temporarily not available

65

Parameter set inconsistent

998

Request timed out

999

General error / unknown cause

2.9 Security

The broker requires a username:password from every client except for read/write to device/#-topics.

2.10 Status of internal mqtt clients

The internal mqtt clients in SICON.OS (mapper, mqtt2db, etc.) will post their status on a specific topic tree and use LWT; so a watchdog-type service can monitor for crashes and restart them.

Topic tree will look like this:

  • “mqtt/status/[clientName]”, message {“Status”:”on|off|disconnected”}

The mapper (clientName = Mapper) will – as an exception – set its status with retail=true.

3. Adapter Management

  • Every instance of an adapter is assigned a unique identification called “InterfaceID” within SICON.OS (known as AdapterInstanceID in the database). The InterfaceID is an integer value.

  • After an adapter has received its InterfaceID, it gets started by the backend. This causes the adapter to initiate the resetting of old device entries in the database as well as preregistering its “main” device.

  • The adapter then remains dormant until it is chosen by the user for full device registration.

The overall sequence with all possible steps is shown here:

3.1 Assigning the InterfaceID

3.1.1 Internal / External Adapters

The term “internal adapters” refers to a set of software modules that share the same mqtt client and run as services in SICON.OS.

The term “external adapters” refers to adapters that come with their own mqtt client and are separated from the internal set of adapters. They may be running on SICON.OS as well, but still communicate like external adapters. External adapters need to be preconfigured with the broker IP-address and port. A useful default value could be defined (e.g. 192.168.0.250).

An adapter that has not been assigned an InterfaceID yet shall make its presence known upon startup by publishing the regAdapter message.

regAdapter

(retain = true)

Topic:

adapterConfig/idAssigner/[MACaddress]/regAdapter

e.g. adapterConfig/idAssigner/01:02:03:04:05:06/regAdapter

Payload example:

{ "IPAddress":"1.2.3.4", "VendorID":234, "VendorName":"J. Schmalz GmbH", "VendorText":"J. Schmalz GmbH", "DeviceID":999998, "ProductID":"5768", "ProductName":"SICON.PLUG", "ProductText":"Plug Adapter", "FirmwareRevision":"1.00", "ArticleNumber":"214215291" }

Attribute

Mult*

DataType

Description

IPAddress

1

String

The IP address on which the adapter software is running

VendorID

1

Integer

 

VendorName

0..1

String

 

VendorText

0..1

String

 

DeviceID

1

Integer

 

ProductID

0..1

String

 

ProductName

0..1

String

 

ProductText

0..1

String

 

FirmwareRevision

0..1

String

Software version of the adapter

ArticleNumber

0..1

String

 

StopOnProblems

0..1

Boolean

If `true`, the adapter gets stopped directly if an error occurs while connecting it for the first time

isSelfRegistering

0..1

Boolean

 

(* “Mult” = multiplicity of the attribute)

According to chapter 2, this message is published with the mqtt option “retainFlag = true” so the broker saves this message as the current state in case the mapper comes online after the adapter. An LWT is not to be used here.

The ID-Assigner responds to this by sending an assignID message.

assignID

(retain = false)

Topic:

adapterConfig/[MACaddress]/assignID

Example: adapterConfig/01:02:03:04:05:06/assignID

Payload example:

{"ID":15}

Attribute

Mult

DataType

Description

ID

1

Number

New InterfaceID for the adapter

 

Upon reception, the adapter shall

  1. Store the InterfaceID persistently so the next system startup can be done without assignment.

  2. Clear the retained status-message on ”adapterConfig/idAssigner/[adapter MAC address]/regAdapter” (this is done by sending an empty message (size 0) with retainFlag = true to this topic)

  3. Disconnect from the broker so a proper LWT can be set on the status topic (see next chapter).

3.2 Persistent adapter status

External adapters are in one of 4 different connection states and publish their current state persistently using the status message.

status

For internal adapters: retain = false

For external adapters: retain = true

Topic:

adapterConfig/configService/[InterfaceID]/status

Payload example:

{"Status":"on"}

Attribute

Mult

DataType

Description

Status

1

String

“disconnected|off|reset|on”

 

State

Description

off

Initial state after starting the adapter, resulting state of stopAdapter

Devices on subinterfaces are not registered and no data are sent out

reset

Waiting for acknowledgement of resetDevices

Devices on subinterfaces are not registered and no data are sent out

on

Active state, devices on subinterfaces are registered and unregistered

Data (dynamic, static, events, reporting) are sent out according to requests received

disconnected

Last Will and Testament message, indicates network disconnection or software crash (KeepAlive interval exceeded)

3.3 Starting and stopping adapters

Adapters are in the state “off” upon startup, i.e. they do not register devices with the mapper.

To switch the adapter between on and off states, the commands startAdapter and stopAdapter are used.

startAdapter

(retain = false)

Topic:

adapterConfig/[InterfaceID]/configService/startAdapter

Payload:

{}

Attribute

Mult

DataType

Description

-

 

 

 

The adapter switches to state “reset” (without publishing this status) and sends out the “resetDevices” message as described in in 3.4.

stopAdapter

(retain = false)

Topic:

adapterConfig/[InterfaceID]/configService/stopAdapter

Payload:

{}

Attribute

Mult

DataType

Description

-

 

 

 

The adapter shall unregister all its attached devices by sending disDevice for each of them. It also sets its status to “off” and publishes this as described in 3.2. While in the off-state, it shall not register any new devices.

3.4 Resetting devices

After receiving the startAdapter message, the adapter shall go to the state “reset” and send the resetDevices message to the mapper (“Status”:”reset” is not published though).

resetDevices

(retain = false)

Topic:

adapterConfig/configService/[InterfaceID]/resetDevices

Payload

{}

Attribute

Mult

DataType

Description

-

 

 

 

 

Acknowledge resetDevices

(retain = false)

Topic:

adapterConfig/[InterfaceID]/configService/resetDevices

Payload

{“Value”:”ack|nak”}

Attribute

Mult

DataType

Description

Value-

1

String

 

Upon reception of the “ack” response, the adapter shall go to status “on”, publish its status as described in 3.2 and preregister its main device as described in 4.1.

In case of “nak” response the adapter stays in the state reset and publishes this on the status topic. In reset state, no devices will be registered. In the reset state, the adapter keeps waiting for a new startAdapter command.

3.5 Status of first connection attempt

After successfully resetting devices, the adapter shall try to connect the main device and if StopOnProblems was true broadcast the result of this first connection attempt.

firstConnect

(retain = false)

Topic:

adapterConfig/configService/[InterfaceID]/firstConnect

Payload

{"Status":"success"}

or

{"Status":"failed", "Error":"some error text / description"}

Attribute

Mult

DataType

Description

Status

1

String

“success|failed”

Error

0..1

String

description of the occured error

SICON.OS reacts to this message and either sets the StopOnProblems flag to false (status=success) or deactivates the adapter in the database (status=failed).

3.6 Starting full device registration

startDevices

(retain = false)

Topic:

adapterConfig/[InterfaceID]/configService/startDevices

Payload:

{}

Attribute

Mult

DataType

Description

-

 

 

 

When switched from off to on state, the adapter shall only pre-register its main device. Only upon receipt of startDevices shall further subinterfaces be registered as described in 4.1.; starting by registering the main device without the prereg-Attribute set.

4. Device Management

  • Every adapter is subdivided into one or more Subinterfaces. The SubinterfaceIDs are predefined by each particular adapter and shall adhere to the following regular expression ^[a-zA-Z0-9]{1,4}$.

  • Every adapter has to have a subinterface called “main”. In case of simple, non-modular devices “main” can be the only subinterface present.

  • For IO-Link ports, the SubinterfaceIDs are p1, p2, p3 etc. adhering to ^p[1-9]{1}[0-9]{0,2}$.

  • The mapper has 2 different sub-instances designed to deal with different types of devices:

    • [mapper] = mapper_iodd: for IO-Link devices. They can be mapped using an IODD

    • [mapper] = mapper_sdd: for non-IO-Link devices that come with an SDD file for data mapping

4.1 Registering devices

Adapters recognize any devices connected to their subinterfaces and subscribe to the mapper with command regDevice:

regDevice

(retain = false)

Adapter topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/regDevice

Device topic:

device/[DevID]/regDevice

or

device/[DevID]/preregDevice

Payload example:

{"VendorID":"234", "DeviceID":"100610", “PDbitLength”:{“ProcessDataIn”:16, “ProcessDataOut”:0}, "VendorName":"J. Schmalz GmbH", “VendorText”:”www.schmalz.com”, "ProductName":"VSi-D", "ProductID":"VSi-D", “ProductText”:”VSi V D M12-5”, "SerialNumber":"999000001", “HardwareRevision”:”02”, “FirmwareRevision”:”1.13”, “prereg”:false}

Attribute

Mult*

DataType

Description

VendorID

1

String

Vendor ID within the respective namespace (IODD or SDD), decimal formatted number

DeviceID

1

String

Device ID, decimal formatted number

PDbitLength

0..1

Object

Process data lengths of connected device

PDbitLength.ProcessDataIn

0..1

Number

Length of input process data in bits

PDbitLength.ProcessDataOut

0..1

Number

Length of output process data in bits

VendorName

0..1

String

may be present but empty

VendorText

0..1

String

may be present but empty

ProductName

0..1

String

may be present but empty

ProductText

0..1

String

may be present but empty

ProductID

0..1

String

may be present but empty

FirmwareRevision

0..1

String

may be present but empty

HardwareRevision

0..1

String

may be present but empty

SerialNumber

0..1

String

may be present but empty

ParentSubinterface

0..1

String

SubinterfaceID of the hierarchical parent device

prereg

0..1

Boolean

Defaults to false

If true => only the main device is registered

While processing the registration, the device takes different registration stati:

0

self preregistered

1

preregistered w/o xDD

2

xDD provisioning in progress

3

parsing

4

preregistered with xDD

5

registration in progress

6

registered

7

disconnected

These stati get broadcasted on the device-topic:, e.g.:

device/[DevID]/registration_status
{"OldRegStatusID":2,"NewRegStatusID":3,"AncestorMainDevID":8}

Once the device has been registered SICON.OS broadcasts a message on device/[DevID]/regDevice or device/[DevID]/preregDevice, forwarding all info about the device.

4.2 Unregistering devices

If a device gets disconnected from the interface of the adapter the adapter sends a disDevice to the mapper. This also means that internal adapters for IO-Link masters shall send disDevice for each port if they lose connection to the IO-Link master.

disDevice

(retain = false)

Topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/disDevice

Payload example:

{"VendorID":"234", "DeviceID":"100610", "VendorName":"J. Schmalz GmbH", "ProductName":"VSi-D", "ProductID":"VSi-D", "SerialNumber":"999000001"}

Attribute

Mult*

DataType

Description

VendorID

1

String

Vendor ID, decimal formatted number

DeviceID

1

String

Device ID, decimal formatted number

PDbitLength

0..1

Object

Process data lengths of connected device

PDbitLength.ProcessDataIn

0..1

Number

Length of input process data in bits

PDbitLength.ProcessDataOut

0..1

Number

Length of output process data in bits

VendorName

0..1

String

may be present but empty

ProductName

0..1

String

may be present but empty

ProductID

0..1

String

may be present but empty

SerialNumber

0..1

String

may be present but empty

The SICON.OS forwards this message also to device/[DevID]/disDevice.

The disconnection of a device shall cause all active processes (like sending reporting data) and states (like sending events when they occur) to be reset to their default / idle states. The adapter shall not store any information about previously connected devices.

4.3 Retriggering device registration

The adapter can be made to reinitialize a subinterface by using the restartSubinterface command:

restartSubinterface

(retain = false)

Topic:

adapterConfig/[InterfaceID]/configService/restartSubinterface

Payload example:

{"Subinterface":"p1”}

Attribute

Mult*

DataType

Description

Subinterface

1

String

SubinterfaceID

The adapter shall treat this as if the connection to the device was lost and then reestablished. Thus, a disDevice message followed by a new regDevice shall be sent to the mapper.

4.4 Setting the device id

Certain messages from the adapters are subscribed directly by the services and therefore require a device-specific ID based on their unique “DevID” within the system. As soon as this “DevID” has been determined within the database, the mapper shall transmit the information to the adapter:

setDevID

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/setDevID

Payload example:

{"ID":15}

Attribute

Mult*

DataType

Description

ID

1

Number

The DevID for this particular device.

The adapter shall acknowledge with an acknowledge message as described in 2.7.

The adapter shall store this DevID for each subinterface until either the device is unregistered, the adapter stopped or a new setDevID command has been received.

4.5 Setting the device location info

The mapper then informs the adapter about the set location info:

setDevLocation

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/setDevLocation

Payload example:

{"LocationTag":"UndefinedTag","LocationPos":"UndefinedPos","AssetID":"t2twcgg4k"}

Attribute

Mult*

DataType

Description

LocationTag

1

String

LocationTag

LocationPos

1

String

LocationPos

AssetID

1

String

AssetID

The adapter shall acknowledge with an acknowledge message as described in 2.7.

4.6 Forwarding the assigned SDD

The SDD-Mapper forwards the assigned SDD file completely to the adapter, as there might be some additional info which is essential for the adapter:

setDevSDD

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/mapper_sdd/setDevSDD

Payload example:

{"base64data":"ewogICJEb2N1bWVudCI6IHsKICAgICJTRERSZXZpc2lvbiI6ICIxLjEiCiAgfSwKICAiU291cmNlI … TAxMDIsCiAgICAgICAgIk1vZGUiOiAiQVBQRUFSUyIKICAgICAgfQogICAgXQogIH0KfQ=="}

Attribute

Mult*

DataType

Description

base64data

1

String

base64-encoded SDD file content

4.7 Date Update

Certain messages like dynamic data and events require a timestamp and thus all adapters shall receive date information from the mapper before these kind of messages are requested.

The mapper shall send a dateUpdate message with the server date in a raw millisecond format of 48-Bit length. This counts the milliseconds since 1st Jan 1970, 0:00 AM. The adapter shall respond with an acknowledge message when the time stamp has been updated.

dateUpdate

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/dateUpdate

Payload example:

{"ms":"015FE62C8C00"}

Attribute

Mult

DataType

Description

ms

1

String

Timestamp in milliseconds since 1st Jan 1970, 0:00 AM. Formatted as HexString of 12 characters (= 6 byte of data).

The adapter shall acknowledge with an acknowledge message as described in 2.7.

This timestamp format shall then be used for all further time information, like the time stamp of dynamic data, reporting data and events.

If no dateUpdate message has been received, the adapter shall use one of these methods as timestamp:

  • If internal real-time clock is available: use own time

  • Otherwise: the time since its power-up.

5. Static Data

Static data are accessible as acyclic parameters in the IOT devices and generally represent data with a low rate of change. Typically this includes identification data and device settings. Static data are referenced by a numeric key called index. For IODD-Devices, the index is suffixed by a dot and a numeric subindex (range 0…255) where subindex 0 represents summary access to the whole object (all subindices are transmitted together).

5.1 Reading Static Data

5.1.1 Data Flow

Upon device registration, all static data (as found in the IODD or SDD) are read by the mapper using the getStatData message. The corresponding postStatData message is then received by the mapper and the values get stored in the database.

5.1.2 getStatData

getStatData

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/getStatData

Payload example:

{"16":{"DataType":"StringT","Gradient":null,"Offset":null,"Resolution":null,"Unit":null,"BitLength":512,"BitOffset":0},"17":{"DataType":"StringT","Gradient":null,"Offset":null,"Resolution":null,"Unit":null,"BitLength":512,"BitOffset":0}}

Attribute

Mult*

DataType

Description

<Index(.Subindex)>

1..*

Object

Index(.Subindex) is used as reference to the statData object. If Subindex is missing, it is implied 0. If Subindex is 0, the whole index is read as HexString.

In each <Index(.Subindex)> object:

DataType

1

String

Data Types

Gradient

1

String

Data Formatting

Offset

1

String

Data Formatting

Resolution

1

String

Data Formatting

Unit

1

String

 

BitLength

1

Number

Size in bits

BitOffset

1

Number

Offset in bits

Label

0..1

String

If the label has to be read per OPCUA on a nodepath, the nodepath has to be set here – otherwise the label itself

Value

0..1

String

If the value has to be read per OPCUA on a nodepath, the nodepath has to be set here – otherwise the value itself

DefaultValue

0..1

String

 

Range

0..1

String

Allowed range of value, may be single values or ranges e.g.

„1,2-5,7-12,13,15“

Access

0..1

String

Accessible for read and/or write-requests

e.g. „rw“

Static data can also be requested by using the device-topic, in which case SICON.OS creates the full getStatData message described above automatically.

getStatData

(retain = false)

Topic:

device/[DevID]/getStatData

Payload example:

{"Indices":["16"]}

Attribute

Mult*

DataType

Description

Indices

1

Array

List of Index(.Subindex) to be read

5.1.3 postStatData

postStatData

(retain = false)

Topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/postStatData

Payload example:

{"16":{"Value":"J. Schmalz GmbH","DataType":"StringT","Gradient":null,"Offset":null,"Resolution":null,"Unit":null,"BitLength":512,"BitOffset":0},"17":{"Value":"http://www.schmalz.com ","DataType":"StringT","Gradient":null,"Offset":null,"Resolution":null,"Unit":null,"BitLength":512,"BitOffset":0}

Attribute

Mult*

DataType

Description

<Index> or

<Index(.Subindex)>

1..*

Object

Index(.Subindex) is used as reference to the statData object. If Subindex is missing, it is implied 0.

In each <Index(.Subindex)> object:

 

 

 

 

Value

1

String

Result of read

DataType

1

String

Data Types

Gradient

0..1

String

Data Formatting

Offset

0..1

String

Data Formatting

Resolution

0..1

String

Data Formatting

Unit

0..1

String

 

BitLength

0..1

Number

Size in bits

BitOffset

0..1

Number

Offset in bits

Label

0..1

String

 

DefaultValue

0..1

String

 

Range

0..1

String

 

Access

0..1

String

 

The adapter is allowed to generate more than one response message to a getStatData request.

In case of an error while reading (usually due to a missing key or blocked access), the ISDU response codes from IOL are used. In IO-Link these codes are called “additional error code”, see chapter 5.2. The adapter shall react to each key request with either the data or an error code. This way, the mapper can monitor whether the response is finished or not:

  • respond with key + result as string

  • respond with key + error code (number instead of string) as negative response,

e.g. “13”:17 => key not found

The postStatData message is automatically forwarded to the device-topic by SICON.OS:

device/[DevID]/postStatData

5.2 Writing static data

5.2.1 Data Flow

Requests for writing static data (i.e. device settings) usually originate at an IT-service using a device/DevID topic. The MQTT-OT-IT-converter receives these requests and forwards them to the appropriate adapter-instance topic.

The response to a write request of static data is first sent to the MQTT-OT-IT-converter who updates the new value in the database and then forwards the response to the IT-services again.

5.2.2 IT request

putStatData (IT)

(retain = false)

Topic:

device/[DevID]/putStatData

Payload example:

{

"24":"VSi-NPT",

"79":"1"

}

Attribute

Mult*

DataType

Description

<key>

1..*

Object

<key> gives Index.Subindex

<Value> is new value to be written

5.2.3 Adapter request

Translated request from the MQTT-OT-IT-converter to the adapter:

putStatData

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/putStatData

Payload example:

{

"24":{"value":"Test","BitLength":256,"DataType":"StringT","Gradient":null,"Offset":null,"Resolution":null},

"79":{"value":"1","BitLength":8,"DataType":"UintegerT","Gradient":null,"Offset":null,"Resolution":null}

}

Attribute

Mult*

DataType

Description

<key>

1..*

Object

<key> gives Index.Subindex representation

For each key-Object

 

<key>.”value”

1

String

New value to be written

<key>.”DataType”

1

String

Data Types

<key>.”BitLength”

1

Number

Size in bits

<key>.”BitOffset”

1

Number

Offset in bits

<key>.”Gradient”

1

Number

Data Formatting

<key>.”Offset”

1

Number

Data Formatting

<key>.”Resolution”

1

String

Data Formatting

<key>.”Unit”

1

String

 

<key>.”Range”

1

String

 

5.2.4 Adapter response

wrStatData

(retain = false)

Topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/wrStatData

Payload example:

{"24":{"value":"Test","result":0},"79":{"value":"1","result":0}}

Attribute

Mult*

DataType

Description

<key>

1..*

Object

<key> gives Index.Subindex representation

For each key-Object

 

<key>.”value”

1

String

New value that was attempted to be written

<key>.”result”

1

Number

Return code of the write attempt (see chap 5.3)

 In response, the adapter shall transmit an error code for each key, as well as echo the value that was written (or was attempted to be written).

The error code and value are grouped as a JSON object for each key. The error codes are the same as for IOL ISDU write access, “additional code” values, and thus the same as in the NFC app. Error code = 0 signifies “no error”.

The adapter may generate more than one response message but should try to use as few messages as possible to reduce network overhead. However, the mapper must be able to handle the case that each key arrives as a separate message and in different sequence than the request.

5.2.5 IT response

wrStatData

(retain = false)

Topic:

device/[DevID]/wrStatData

Payload example:

{"24":{"value":"Test","result":0},"79":{"value":"1","result":0}}

Attribute

Mult*

DataType

Description

<key>

1..*

Object

<key> gives Index.Subindex representation

For each key-Object

 

<key>.”value”

1

String

New value that was attempted to be written

<key>.”result”

1

Number

Return code of the write attempt (see chap 5.3)

5.3 Updating static data

Certain static data can change during operation of the device. To get the data base updated to new values SICON.OS defines a mechanism of periodic transmission of certain static data indices by the adapter.

The mechanism is defined and triggered by the mapper during device registration:

startStatDataUpdater

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/

startStatDataUpdater

Payload example:

{"Interval":60000,"Indices":[{"idxStr":"36.0","DataType":"UIntegerT","Gradient":null,"Resolution":null,"Offset":null,"Unit":null,"BitLength":8,"BitOffset":0}]}

Attribute

Mult*

DataType

Description

Interval

1

Number

Sampling rate in ms between stat data updates

Indices

1

Array

One entry for each Index/Subindex

idxStr

1

String

Index.Subindex representation

Value

0..1

String

If the value has to be read per OPCUA on a nodepath, the nodepath has to be set here

DataType

1

String

Data Types

BitLength

0..1

Number

Size in bits

BitOffset

0..1

Number

Offset in bits

Gradient

0..1

String

Data Formatting

Offset

0..1

String

Data Formatting

Resolution

0..1

String

Data Formatting

Unit

0..1

String

 

Range

0..1

String

 

As a result, the adapter shall send a statDataUpdate message periodically according to the attributes received:

updateStatData

(retain = false)

Topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/

updateStatData

Payload example:

[{"IdxStr":"36.0", "Value":"1"}]

Attribute

Mult*

DataType

Description

Array with one entry for each requested Index/Subindex

idxStr

1

String

Index.Subindex representation

Value

1

String

The actual value of this index

6. Dynamic Data

6.1 Description of Dynamic Data

Dynamic data is cyclically transmitted data that usually corresponds to a device’s process data. As such, the transmission of dynamic data via MQTT is also done cyclically with a given sampling rate.

Dynamic data for a subinterface consists of 2 separate channels:

  • The input channel “ProcessDataIn” is the data flowing from the field device to the controller, e.g. sensor values, threshold bits etc.

  • The output channel “ProcessDataOut” is the data flowing from the controller to the field device, e.g. actor control, target values etc.

In the SICON system, the dynamic data mechanism is for observation of both channels of process data. For forcing output process data directly from SICON.OS, see Forcing output process data.

6.2 Requesting Dynamic Data

The process data are represented as individual objects of given data type. Both process data channels can be requested in the same message:

getDynData

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/getDynData

Payload example:

{"SamplingRate":0,"BufferSize":1,"Parameters":{

"InPartDetection":{

"PDChannel":"ProcessDataIn", "BitLength":1, "BitOffset":120, "Gradient":null, "Offset":null, "Resolution":null, "Unit":null, "DataType":"BooleanT”},

"OutPartDetectionOff":{

"PDChannel":"ProcessDataOut", "BitLength":1, "BitOffset":24, "Gradient":null, "Offset":null, "Resolution":null, "Unit":null, "DataType":"BooleanT"}

}}

Attribute

Mult*

DataType

Description

SamplingRate

0..1

Number

Time in ms between 2 subsequent process data samples. Default: 0

BufferSize

0..1

Number

Amount of data points to be collected and sent in a single mqtt message. Default: 1

Parameters

1

Object

Contains the individual descriptions of the process data items

For each entry in Parameters:

 

<MQTTName>

1

String

Definition of an “MQTTName” for the described parameter. Constructed by Channename (“In”/”Out”) and Label

PDChannel

1

String

“ProcessDataIn|ProcessDataOut”

DataType

1

String

Data Types

BitLength

0..1

Number

Size in bits

BitOffset

0 or 1

Number

Offset in bits

Gradient

0..1

String

Data Formatting

Offset

0..1

String

Data Formatting

Resolution

0..1

String

Data Formatting

Unit

1

String

as defined in chapter 1.3

Range

1

String

 

DefaultValue

1

String

 

In response, the adapter shall send out dynamic data messages periodically:

PDin

PDout

(retain = false)

Topic:

device/[DevID]/PDin

device/[DevID]/PDout

Payload example:

(PDin:) {"InPartDetection”:{“Unit”:null, “Value”:”False”}, "ms":"01648D62F609", "SamplingRate":1000}

(PDout:) {“OutPartDetectionOff”:{“Unit”:null, “Value”:”False”}, "ms":"01648D62F609", "SamplingRate":1000}

Attribute

Mult*

DataType

Description

SamplingRate

1

Number

The actual sampling rate that the adapter is using

ms

1

String

Timestamp of the first sample in the data array (in HexString format)

For each entry:

 

 

 

<MQTTName>

1..*

String

The “MQTTName” for the described parameter

<MQTTName>.Unit

1

String

as defined in chapter 1.3

<MQTTName>.Value

1

String

The formatted value of the parameter as a string

 Remarks on SamplingRate:

  • A sampling rate of 0 causes the adapter to use its internally defined default sampling rate, typically 1000ms.

  • A sampling rate smaller than the adapter’s minimum sampling rate (but != 0) causes the adapter to use its internally defined minimum sampling rate.

  • Because the actually used sampling rate can thus differ from what was requested, the adapter shall include the actual sampling rate in the postDynData message.

Remarks on BufferSize:

  • For regular, slow updates of process data, a buffer size of 1 is used. This causes the adapter to send a single data point per message with its respective timestamp.

  • In order to log faster changes in data with reasonable network overhead, a buffer size > 1 can be chosen. In this case, the adapter collects the amount of samples internally and sends them out in a single message as an array. In this case the timestamp gives the time of the first sample.

6.3 Stopping dynamic data

To stop the adapter from sending periodic dynamic data messages of any kind (both process data channels), the mapper can send this message:

stopDynData

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/stopDynData

Payload example:

{}

Attribute

Mult*

DataType

Description

-

 

 

 

 The adapter shall respond with an acknowledge message.

6.4 Forcing output process data

The output process data of a device can be forced via mqtt messages. The data flow follows the pattern of “putStatData”, i.e. the request is first submitted to the  MQTT-OT-IT-converter via

“device/[DevID]/putPDout”

putPDout (IT)

(retain = false)

Topic:

device/[DevID]/putPDout

Payload example:

{

"Suction":"True",

"SupplyPressure":"5.2"

}

Attribute

Mult*

DataType

Description

<key>

1..*

Object

<key> gives MQTTLabel

<Value> is new value to be written

Between mapper and adapter, topics based on InterfaceID and SubinterfaceID are used.

To simplify the use of this feature for the user, the adapter shall allow that only a certain subset of process data are transmitted. For this, the adapter shall store a copy of the full process data internally and insert the new data into it before transmitting to the device. The internal process data copy is initialized with all zeros upon registration of the device.

The topic used between mapper and adapter is

“adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/putPDout”

and the message format is like that of “getDynData” with the following attributes (min.):

  • “BitLength” and “BitOffset”: Position of the data within PDout

  • “DataType”, “Gradient” – as for getDynData

  • “Value” formatted according to the above 3

Topic:

device/[DevID]/putPDout

Message:

{“Suction”:{"BitLength":1,"BitOffset":8,"Gradient":"1","DataType":"BooleanT","Value":"True”},

"SupplyPressure":{"BitLength":7,"BitOffset":0,"Gradient":"0.1",”DataType":"UIntegerT",”Value”:”5.2”}}

In case of PDout, the gradient works “backwards” as compared to the transmission of dynamic data, so in the example for the parameter SupplyPressure, the value of 5.2 would have to be divided by the gradient, resulting in “52” and sent as such on the specified OT-topic for PDout (lower 7 bits of MSB).

All the other data objects in PDout that are not updated with such a message, shall be left in their previous state before being sent to the device.

7. XConfig

7.1 Requesting XConfig

The ”XConfig” configures the X_x values, which will be send with Fehler: Verweis nicht gefunden and Events and has to be send before requesting reporting data or starting events.

setXConfig

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/setXConfig

Payload example:

{"parameters":{"X_1":{"DataType":"UIntegerT","Gradient":null,"Resolution":null,"Offset":null,"Unit":null,"BitLength":8,"BitOffset":0,"Range":"0,1,2,3,4,5-255","index":"36.0"}},"AutomaticReadForEvents":true,"AutomaticReadForReporting":true}

Attribute

Mult*

DataType

Description

AutomaticReadForEvents

1

Boolean

If the X-values should be read automatically by the adapter, when sending out an event

AutomaticReadForReporting

1

Boolean

If the X-values should be read automatically by the adapter, when sending out reporting data

parameters

1

Object

List of individual stat data parameters that shall be sent

Objects in parameter list:

 

“X_1”,”Y_2”,…”X_4”

1..30

Object

 

Objects for each X-parameter:

 

index

1

String

The stat data index to be sent out as Y_x, given in decimal “index.subindex” notation

Unit

1

String

as defined in chapter 1.3

can be replaced by a node path ?

DataType

1

String

Data Types

BitLength

0..1

Number

Size in bits

BitOffset

0 or 1

Number

Offset in bits

Gradient

0..1

String

Data Formatting

Offset

0..1

String

Data Formatting

Resolution

0..1

String

Data Formatting

Range

1

String

 

8. Reporting data

8.1 Requesting reporting data

The ”reporting data” mechanism of the protocol is a cyclic or trigger-base read-out of a certain set of static data. After receiving a request for startReporting, the adapter shall monitor the trigger or the time and automatically read statData from the device and send it out over mqtt. There is only 1 trigger active in a subinterface at any given time and the reception of a new startReporting message shall cancel and overwrite the old trigger.

8.1.1 Triggers
  • There are several different trigger mechanisms to define when the  reporting data are to be sent:Time-based trigger (“Type”:”time”): The first epc message is sent out right after receipt of startReporting and updates are sent periodically thereafter.

    • “SamplingRate”:<time in ms> - Update rate for the EPC data

  • Event-based trigger (“Type”:”event”): Waits for the occurance of a specific device event. Whenever the specified event code is received with the specified incidence, the reporting data shall be sent.

    • “Code”:<event_code> - decimal coded event number (as in section 8.2)

    • “Mode”:”SINGLESHOT|APPEARS|DISAPPEARS” – event incidence mode, see section 8.2. So the trigger could be defined to react on a disappearing event as well.

  • Self-triggered (“Type”:”self-triggered”): In this case the adapter has certain application knowledge built-in and reacts to an internal condition that shall trigger the sending of reporting data.

Setting up the trigger condition:

startReporting

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/startReporting

Payload example:

{"trigger":{"type":"event", "code":"35872", "mode":"APPEARS"},

"parameters":{"Y_2":{"index":"141.0","Gradient":null,"Resolution":null,"Offset":null,"Unit":null,"DataType":"UIntegerT","BitLength":32,"BitOffset":0,"MQTTName":"CounterCc2"},"Y_1":{"index":"140.0","Gradient":null,"Resolution":null,"Offset":null,"Unit":null,"DataType":"UIntegerT","BitLength":32,"BitOffset":0,"MQTTName":"CounterCc1"}}

}

Attribute

Mult*

DataType

Description

trigger

1

Object

The trigger to start reporting

Parameters of trigger-object:

 

type

1

String

“time|event|self-triggered”

SamplingRate

0..1

Number

Present if and only if Type == time

code

0..1

String

Event code as decimally formatted string

Present if and only if Type == event

mode

0..1

String

Event incidence: “APPEARS|DISAPPEARS|SINGLESHOT”

Present if and only if Type == event

parameters

1

Object

List of individual stat data parameters that shall be sent

Objects in parameter list:

 

“Y_1”,”Y_2”,…”Y_30”

1..30

Object

 

Objects for each Y-parameter:

 

index

1

String

The stat data index to be sent out as Y_x, given in decimal “index.subindex” notation

Unit

1

String

as defined in chapter 1.3

can be replaced by a node path ?

DataType

1

String

Data Types

BitLength

0..1

Number

Size in bits

BitOffset

0 or 1

Number

Offset in bits

Gradient

0..1

String

Data Formatting

Offset

0..1

String

Data Formatting

Resolution

0..1

String

Data Formatting

MQTTName

1

String

 

Range

1

String

 

The adapter broadcasts the reporting data:

postReport

(retain = false)

Topic:

device/[DevID]/postReport

Payload example:

{"Y_2":"0","Y_1":"1","X_1":"1","X_2":"0"}

Attribute

Mult*

DataType

Description

ms

1

String

Timestamp of the first sample in the data array (in HexString format)

<Y_x>

1..30

String

mapped entries for the reporting-DB with the values of the requested data

<X_x>

0..4

String

mapped entries requested by command ‘setXConfig’

8.2 Stopping reporting data

To stop the sending of reporting data, the following message exchange is used:

stopreportingData

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/stopReportingData

Payload:

{}

 This shall be acknowledged by the adapter.

9. Events

9.1 Starting and stopping events

The sending of events can be switched on or off with these messages:

startEvents

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/startEvents

Payload:

{}

stopEvents

(retain = false)

Topic:

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/stopEvents

Payload:

{}

Both types of message shall be acknowledged by the adapter.

9.2 Sending Events

The adapters don’t have all the information about an event that is required in the frontend or on the IT-Service side. So an event message is first transmitted from adapter to mapper using an “adapter”-topic. The mapper enriches the message with information from the database (from the IODD and SDD) as well as an unique ID for  each event and forwards it to the respective device-topic.

Event message are not acknowledged in any way by the recipient.

Event (OT)

(retain = false)

Topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/event

Payload example:

{"code":16, "mode":"DISAPPEARS", "type":"Error", "timestamp":"2018-07-12T13:31:46.058Z", “XValues":{"X_1":"1","X_2":"0"}}

Attribute

Mult*

DataType

Description

timestamp 

1

String

Timestamp in ISO format

code

1

Number

Event code

mode

1

String

“APPEARS|DISAPPEARS|SINGLESHOT”

type

1

String

“Error|Warning|Notification”

XValues

1

Object of Strings

mapped entries requested by command ‘setXConfig’

 

Event (IT)

(retain = false)

Topic:

device/[DevID]/event

Payload example:

{"code":16, "mode":"DISAPPEARS", "type":"Error", "timestamp":"2018-07-12T13:31:46.058Z", “XValues":{"X_1":"1","X_2":"0"}, "message":null, "timestampAppears":"2018-07-12T13:31:24.895Z", "DeltaCounter":null, "ID":6}

Attribute

Mult*

DataType

Description

timestamp 

1

String

Timestamp in ISO format

code

1

Number

Event code

mode

1

String

“APPEARS|DISAPPEARS|SINGLESHOT”

type

1

String

“Defect/Fault|Warning|Notification”

message

1

String

Human-readable message text

TimestampAppears

0..1

String

Timestamp when the event appeared in ISO format (only if mode=DISAPPEARS)

DeltaCounter

0..1

Number

Delta of Counter between this event & appeared event (only if mode=DISAPPEARS)

ID

1

Number

ID of event instance in database

XValues

1

Object of Strings

mapped entries requested by command ‘setXConfig’

EventStrings

1

Object of Strings or null

Name, Remark, Description, Cause, Impact, Solution

10. Commands

Devices often have some specific commands like “Reset to factory defaults”, “Sensor calibration”, Teach-In etc. These commands are coded as integer numbers and are defined in analogy to the SystemCommand of IO-Link.

An IT-Service can request a command on the device-topic, which gets translated to the adapter-topic by the MQTT-OT-IT-converter.

putCommand

(retain = false)

Topic:

device/[DevID]/putCommand

adapter/[InterfaceID]_[SubinterfaceID]/[mapper]/putCommand

Payload example:

{"Value":168}

Attribute

Mult*

DataType

Description

Value

1

Number

Command code to be executed

The result of the command is sent back from the adapter first to the MQTT-OT-IT-converter who forwards it to the device topic:

wrCommand

(retain = false)

Topic:

adapter/[mapper]/[InterfaceID]_[SubinterfaceID]/wrCommand

device/[DevID]/wrCommand

Payload example:

{"Value":0}

Attribute

Mult*

DataType

Description

Value

1

Number

Result code (see 5.3)

For IO-Link devices, “putCommand” is always an ISDU write to index 2, subindex 0, UIntegerT with bitlength 8 and the <command_code> as data. This is handled internally in the adapter.

11. Services

For messages between build in SICON.OS services there are topics following the pattern:

services/[reciever]/[sender]/[command]

Today the following topcis/messages exist:

wrCommand

(retain = false)

Topic:

services/preregscanner/restapi/start

Payload example:

{}

 Send when the Prereg-Scanner is started by the restapi.

wrCommand

(retain = false)

Topic:

services/restapi/preregscanner/finished

Payload example:

{}

Send when the Prereg-Scanner finishes. 

wrCommand

(retain = false)

Topic:

services/preregscanner/restapi/start

Payload example:

{}

Attribute

Mult*

DataType

Description

Value

1

Number

Result code (see 5.3)

 

wrCommand

(retain = false)

Topic:

services/preregscanner/restapi/start

Payload example:

{}

Attribute

Mult*

DataType

Description

Value

1

Number

Result code (see 5.3)

12. Appendix

12.1 Data Formatting: allowed combinations of DataType, DisplayFormat, Gradient and Offset

Quoted from the IODD specification version 1.1:

13. Document revision

 

13.11.2017

First document

21.01.2020

All occurrances of “size” as message attribute renamed to “BitLength”

getStatData/postStatData without the distinction Ident/Para/Observ/Diag

15.12.2020

Adaptation to actual messages

 

 

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.