sensorconnect

The technical documentation of the microservice sensorconnect, which reads out sensor values through ifm gateways.

The microservice sensorconnect automatically detects ifm gateways in the specified network and reads out their sensor values in the highest possible data frequency (or the chosen data frequency). It provides plug-and-play access to IO-Link sensors connected to ifm gateways. Digital input mode is also supported. A typical setup contains multiple sensors connected via LAN to your server infrastructure. The sensorconnect microservice constantly monitors a given IP range for gateways. Once a gateway is found, it automatically starts requesting, receiving and processing sensor data in short intervals. The received data is preprocessed based on a database including thousands of sensor definitions. And because we strongly believe in open industry standards, sensorconnect brings the data via MQTT or Kafka to your preferred software solutions (for example, features of the United Manufacturing Hub or the cloud).

Get Started

Here is a quick tutorial on how to start up a basic configuration or, respectively, a basic docker-compose stack, for development purposes.

docker-compose -f ./deployment/sensorconnect/docker-compose.yml up -d --build

Underlying functionality

Sensorconnect downloads relevant IODD files automatically after installation from the IODDfinder webpage. If an unknown server is connected later, sensorconnect will automatically download the file. We will also provide a folder to manually deposit IODD-files, if the automatic download doesn’t work (e.g. no internet connection).

REST API POST requests from sensorconnect to the gateways

Sensorconnect scans the IP range for new ifm gateways (used to connect the IO-Link devices to). To do that, sensorconnect iterates through all the possible IP addresses in the specified IP address range (“http://"+url, payload, timeout=0.1). It stores the IP addresses with the product codes and the individual serial numbers.

Scanning with the following payload: (Information send during a POST request to the ifm gateways)

{
  "code":"request",
  "cid":-1, // The cid (Client ID) can be chosen.
  "adr":"/getdatamulti",
  "data":{
    "datatosend":[
      "/deviceinfo/serialnumber/","/deviceinfo/productcode/"
      ]
    }
}

Example answer from gateway

{
    "cid": 24,
    "data": {
        "/deviceinfo/serialnumber/": {
            "code": 200,
            "data": "000201610192"
        },
        "/deviceinfo/productcode/": {
            "code": 200,
            "data": "AL1350"
        }
    },
    "code": 200
}

All port modes of the connected gateways are requested. Depending on the productcode, the total number of ports on the gateway can be determined and iterated through.

Requesting port modes with following payload: (information sent during a POST request to the ifm gateways)

{
  "code":"request",
  "cid":-1,
  "adr":"/getdatamulti",
  "data":{
    "datatosend":[
      "/iolinkmaster/port[1]/mode",
      "/iolinkmaster/port<i>/mode" //looping through all ports on gateway
      ]
    }
}

Example answer from gateway

{
    "cid": -1,
    "data": {
        "/iolinkmaster/port[1]/mode": {
            "code": 200,
            "data": 3
        },
        "/iolinkmaster/port[2]/mode": {
            "code": 200,
            "data": 3
        }
    }
}

If the mode == 1: port_mode = “DI” (Digital Input)

If the mode == 2: port_mode = “DO” (Digital Output)

If the mode == 3: port_mode = “IO_Link”

All values of accessible ports are requested as fast as possible (ifm gateways act as a bottleneck).

Requesting IO_Link port values with following payload: (information sent during a POST request to the ifm gateways)

{
  "code":"request",
  "cid":-1,
  "adr":"/getdatamulti",
  "data":{
    "datatosend":[
      "/iolinkmaster/port[1]/iolinkdevice/deviceid",
      "/iolinkmaster/port[1]/iolinkdevice/pdin",
      "/iolinkmaster/port[1]/iolinkdevice/vendorid",
      "/iolinkmaster/port[1]/pin2in",
      "/iolinkmaster/port[<i>]/iolinkdevice/deviceid",//looping through all connected ports on gateway
      "/iolinkmaster/port[<i>]/iolinkdevice/pdin",
      "/iolinkmaster/port[<i>]/iolinkdevice/vendorid",
      "/iolinkmaster/port[<i>]/pin2in"
      ]
  }
}

Example answer from gateway

{
    "cid": -1,
    "data": {
        "/iolinkmaster/port[1]/iolinkdevice/deviceid": {
            "code": 200,
            "data": 278531
        },
        "/iolinkmaster/port[1]/iolinkdevice/pdin": {
            "code": 200,
            "data": "0101" // This string contains the actual data from the sensor. In this example it is the data of a buttonbar. The value changes when one button is pressed. Interpreting this value automatically relies heavily on the IODD file of the specific sensor (information about which partition of the string holds what value (type, value name etc.)).
        },
        "/iolinkmaster/port[1]/iolinkdevice/vendorid": {
            "code": 200,
            "data": 42
        },
        "/iolinkmaster/port[1]/pin2in": {
            "code": 200,
            "data": 0
        }
    },
    "code": 200
}

IODD file management

Based on the vendorid and the deviceid (extracted out of the received data from the ifm gateway), sensorconnect looks in its persistent storage if an IODD file is available. If there is no IODD file stored in the specific sensor, it tries to download a file online and saves it. If this also is not possible, sensorconnect doesn’t preprocess the pdin data entry and forwards it as is.

Data interpretation (key:pdin) with IODD files

The IODD files are in xml format and often contain multiple thousand You can find extensive documentation on the (IO-Link website)[https://io-link.com/en/Download/Download.php]. Especially relevant areas of the IODD files are for our use case:

  • IODevice/DocumentInfo/version: version of IODD files.
  • IODevice/ProfileBody/DeviceIdentity: deviceid, vendorid, etc.
  • IODevice/DeviceFunction/ProcessDataCollection/ProcessData/ProcessDataIn: contains information about the data structure received from the sensor. Datatypes and data references are given.
  • IODevice/DeviceFunction/DatatypeCollection: if used, contains datatypes references by the ProcessDataCollection.
  • IODevice/ExternalTextCollection: contains translation for textIDs

Digital input data management

The gateways are also able to receive digital input data (not IO-Link). This data is also requested and forwarded.

Data delivery to MQTT or Kafka

For delivery of the data, sensorconnect converts the data into a JSON containing the preprocessed data, timestamps, serialnumbers etc. and sends in via MQTT to the MQTT broker or via Kafka to the Kafka broker. You can change the environment variables to choose your preferred protocol.

Environment variables

Variable nameDescriptionTypePossible valuesExample value
LOGGING_LEVELDefines which logging level is used, mostly relevant for developers. If logging level is not DEVELOPMENT, default logging will be usedstringanyDEVELOPMENT
USE_KAFKAIf enabled, uses Kafka to broker messages(true or 1 both enables it)stringtrue, 1,any1
USE_MQTTIf enabled, uses MQTT to broker messages(true or 1 both enables it)stringtrue,1, any1
MQTT_CERTIFICATE_NAMESet to NO_CERT to allow non-encrypted MQTT accessstringany, NO_CERTNO_CERT
MQTT_BROKER_URLThe MQTT broker URLstringIP, DNA nameunited-manufacturing-hub-vernemq-local-service:1883
MY_POD_NAMEName of the docker pod, used for identification at the MQTT brokerstringanyMQTT-Kafka-Bridge
KAFKA_BOOTSTRAP_SERVERURL of the kafka broker, port is requiredstringvalid URLskafka:9092
LOWER_POLLING_TIME_MSTime in milliseconds to define the lower bound of time between sensor polling, defaults to 20 msintany20
SUB_TWENTY_MSSet to 1 to allow LOWER_POLLING_TIME_MS of under 20 ms. This is not recommended as it might lead to the gateway becoming unresponsive until a manual rebootint1, any1
UPPER_POLLING_TIME_MSTime in milliseconds to define the upper bound of time between sensor polling, defaults to 1000 msintany1000
POLLING_SPEED_STEP_UP_MSTime in ms added to polling interval time after a failed polling, defaults to 20 msintany20
POLLING_SPEED_STEP_DOWN_MSTime in ms subtracted from polling interval time after a successful polling, defaults to 1 msintany1
SENSOR_INITIAL_POLLING_TIME_MSAllotted time before sensorconnect begins retrieving sensor data, should be higher than LOWER_POLLING_TIME_MS, defaults to 100 msintany100
ADDITIONAL_SLEEP_TIME_PER_ACTIVE_PORT_MSAdditional allotted sleep time between pollings for each additional active port, defaults to 0.0floatany0.0
DEVICE_FINDER_TIME_SECTime in s before finding new devices, defaults to 20 sintany20
DEVICE_FINDER_TIMEOUT_SECTime in s for an HTTP timeout, defaults to 1 sintany1
MAX_SENSOR_ERROR_COUNTAmount of errors before a sensor is temporarily disabled, defaults to 50intany50
ADDITIONAL_SLOWDOWN_MAPJSON map of values, allows to slow down and speed up the polling time of specific sensorsJSONany valid JSON map[{“serialnumber”:“000200610104”,“slowdown_ms”:-10},{“url”:“http://192.168.0.13”,“slowdown_ms”:20},{“productcode”:“AL13500”,“slowdown_ms”:20.01}]
TRANSMITTERIDID of the sensorconnect, part of the topic structurestringallifmgateway1
IPRANGEIP range sensor connect is scanning in for sensorsstringany192.169.0
IODD_FILE_PATHIODD file pathstringany valid unix path/ioddfiles
Last modified October 5, 2022: Historian article (#107) (5f30dc0)