Stand with Ukraine flag
Try it now Pricing
PE Edge
Getting Started
Devices Library Installation Architecture API FAQ
On this page

UDP Integration

Doc info icon

Edge UDP Integration is implemented in a similar way, as UDP Integration. The only difference is in the way, how integration is created and provisioned. Please make sure that you have knowledge of UDP Integration before proceed.

Overview

UDP Integration allows to stream data from devices which use a UDP transport protocol to ThingsBoard Edge and converts payloads of these devices into the ThingsBoard Edge format.

Doc info icon

UDP Integration can be started only as Remote Integration. It could be started on the same machine, where TB Edge instance is running, or you can start in on another machine, that has access over the network to the TB Edge instance.

Please review the integration diagram to learn more.

image

Prerequisites

In this tutorial, we will use:

  • ThingsBoard PE Edge;
  • UDP Integration, running externally and connected to the ThingsBoard Edge instance;
  • echo command which intended to display a line of text, and will redirect it’s output to netcat (nc) utility;
  • netcat (nc) utility to establish UDP connections, receive data from there and transfer them;

Let’s assume that we have a sensor which is sending current temperature and humidity readings. Our sensor device SN-001 publishes it’s temperature and humidity readings to UDP Integration on 11560 port to the machine where UDP Integration is running.

For demo purposes we assume that our device is smart enough to send data in 3 different payload types:

  • Text - in this case payload is SN-001,default,temperature,25.7,humidity,69
  • JSON - in this case payload is
1
2
3
4
5
6
7
8
[
  {
    "deviceName": "SN-001",
    "deviceType": "default",
    "temperature": 25.7,
    "humidity": 69
  }
]
  • Binary - in this case payload is: \x53\x4e\x2d\x30\x30\x31\x64\x65\x66\x61\x75\x6c\x74\x32\x35\x2e\x37\x36\x39 (in HEX string). Here is the description of the bytes in this payload:
    • 0-5 bytes - \x53\x4e\x2d\x30\x30\x31 - device name. If we convert it to text - SN-001;
    • 6-12 bytes - \x64\x65\x66\x61\x75\x6c\x74 - device type. If we convert it to text - default;
    • 13-16 bytes - \x32\x35\x2e\x37 - temperature telemetry. If we convert it to text - 25.7;
    • 17-18 bytes - \x36\x39 - humidity telemetry. If we convert it to text - 69;
  • Hex - in this case payload is hexadecimal string 534e2d30303164656661756c7432352e373639. Here is the description of the bytes in this payload:
    • 0-5 bytes - 534e2d303031 - device name. If we convert it to text - SN-001;
    • 6-12 byte - 64656661756c74 - device type. If we convert it to text - default;
    • 13-16 byte - 32352e37 - temperature telemetry. If we convert it to text: - 25.7;
    • 17-18 byte - 3639 - humidity telemetry. If we convert it to text: - 69;

You can select payload type based on your device capabilities and business cases.

Doc info icon

On the machine, where remote UDP Integration is running, port 11560 must be opened for incoming connections - nc utility must be able to connect to UDP socket. In case you are running it locally, it should be fine without any additional changes.

Create Converter templates

Converter and Integration templates are created on the Cloud, so please log in as Tenant administrator to cloud instance.

Before creating the Integration template, you need to create an Uplink and Downlink converter templates in Converters templates page. Uplink is necessary in order to convert the incoming data from the device into the required format for displaying them in ThingsBoard Edge. Click on the ‘plus’ and on ‘Create new converter’. To view the events, enable Debug. In the function decoder field, specify a script to parse and transform data.

Doc info icon

While Debug mode is very useful for development and troubleshooting, leaving it enabled in production mode can significantly increase the disk space used by the database since all the debug data is stored there. It is highly recommended turning the Debug mode off after debugging is complete.

Choose device payload type to for decoder configuration:

Now copy & paste the following script to the Decoder function section:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/** Decoder **/

// decode payload to string
var strArray = decodeToString(payload);
var payloadArray = strArray.replace(/\"/g, "").replace(/\s/g, "").replace(/\\n/g, "").split(',');

var telemetryPayload = {};
for (var i = 2; i < payloadArray.length; i = i + 2) {
    var telemetryKey = payloadArray[i];
    var telemetryValue = parseFloat(payloadArray[i + 1]);
    telemetryPayload[telemetryKey] = telemetryValue;
}

// Result object with device attributes/telemetry data
var result = {
    deviceName: payloadArray[0],
    deviceType: payloadArray[1],
    telemetry: telemetryPayload,
    attributes: {}
  };

/** Helper functions **/

function decodeToString(payload) {
   return String.fromCharCode.apply(String, payload);
}

return result;

The purpose of the decoder function is to parse the incoming data and metadata to a format that ThingsBoard can consume. deviceName and deviceType are required, while attributes and telemetry are optional. attributes and telemetry are flat key-value objects. Nested objects are not supported.

Now copy & paste the following script to the Decoder function section:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/** Decoder **/

// decode payload to JSON
var data = decodeToJson(payload);

// Result object with device/asset attributes/telemetry data

var deviceName = data.deviceName;
var deviceType = data.deviceType;
var result = {
   deviceName: deviceName,
   deviceType: deviceType,
   attributes: {},
   telemetry: {
       temperature: data.temperature,
       humidity: data.humidity
   }
};

/** Helper functions **/

function decodeToString(payload) {
   return String.fromCharCode.apply(String, payload);
}

function decodeToJson(payload) {
   // covert payload to string.
   var str = decodeToString(payload);

   // parse string to JSON
   var data = JSON.parse(str);
   return data;
}

return result;

The purpose of the decoder function is to parse the incoming data and metadata to a format that ThingsBoard can consume. deviceName and deviceType are required, while attributes and telemetry are optional. attributes and telemetry are flat key-value objects. Nested objects are not supported.

Now copy & paste the following script to the Decoder function section:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/** Decoder **/

// decode payload to string
var payloadStr = decodeToString(payload);

// decode payload to JSON
// var data = decodeToJson(payload);

var deviceName = payloadStr.substring(0,6);
var deviceType = payloadStr.substring(6,13);

// Result object with device/asset attributes/telemetry data
var result = {
   deviceName: deviceName,
   deviceType: deviceType,
   attributes: {},
   telemetry: {
       temperature: parseFloat(payloadStr.substring(13,17)),
       humidity: parseFloat(payloadStr.substring(17,19))
   }
};

/** Helper functions **/

function decodeToString(payload) {
   return String.fromCharCode.apply(String, payload);
}

function decodeToJson(payload) {
   // covert payload to string.
   var str = decodeToString(payload);

   // parse string to JSON
   var data = JSON.parse(str);
   return data;
}

return result;

The purpose of the decoder function is to parse the incoming data and metadata to a format that ThingsBoard can consume. deviceName and deviceType are required, while attributes and telemetry are optional. attributes and telemetry are flat key-value objects. Nested objects are not supported.

Now copy & paste the following script to the Decoder function section:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/** Decoder **/

// decode payload to JSON
var data = decodeToJson(payload).reports[0].value;

// Result object with device telemetry data
var result = {
    deviceName: hexToString(data.substring(0, 12)),
    deviceType: hexToString(data.substring(12, 26)),
    telemetry: {
        temperature: parseFloat(hexToString(data.substring(26, 34))),
        humidity: parseFloat(hexToString(data.substring(34, 38))),
    }
};

/** Helper functions **/

function decodeToString(payload) {
    return String.fromCharCode.apply(String, payload);
}

// Hexadecimal string to string
function hexToString(hex) {
    var str = '';
    for (var i = 0; i < hex.length; i += 2) {
        var notNullValue = parseInt(hex.substr(i, 2), 16);
        if (notNullValue) {
            str += String.fromCharCode(notNullValue);
        }
    }
    return str;
}

function decodeToJson(payload) {
    // convert payload to string.
    var str = decodeToString(payload);

    // parse string to JSON
    var data = JSON.parse(str);
    return data;
}

return result;

The purpose of the decoder function is to parse the incoming data and metadata to a format that ThingsBoard can consume. deviceName and deviceType are required, while attributes and telemetry are optional. attributes and telemetry are flat key-value objects. Nested objects are not supported.

You can change the decoder function while creating the converter or after creating it. If the converter has already been created, then click on the ‘pencil’ icon to edit it. Copy the configuration example for the converter (or your own configuration) and insert it into the decoder function. Save changes by clicking on the ‘checkmark’ icon.

Create Downlink in Converter templates page as well. To see events select Debug checkbox.

You can customize a downlink according to your configuration. Let’s consider an example where we send an attribute update message. An example of downlink converter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Encode downlink data from incoming Rule Engine message

// msg - JSON message payload downlink message json
// msgType - type of message, for ex. 'ATTRIBUTES_UPDATED', 'POST_TELEMETRY_REQUEST', etc.
// metadata - list of key-value pairs with additional data about the message
// integrationMetadata - list of key-value pairs with additional data defined in Integration executing this converter

var result = {

    // downlink data content type: JSON, TEXT or BINARY (base64 format)
    contentType: "JSON",

    // downlink data
    data: JSON.stringify(msg),

    // Optional metadata object presented in key/value format
    metadata: {
    }
};

return result;

Create Integration template

Now that the Uplink and Downlink converter templates have been created, it is possible to create an integration. Go to Integration templates section and click Add new integration button. Name it UDP Integration, select type UDP, turn the Debug mode on and from drop-down menus add recently created Uplink and Downlink converters.

As you mentioned Execute remotely is checked and can not be modified - UDP Integration can be only remote type.

Please note down Integration key and Integration secret - we will use these values later in the configuration on the remote UDP Integration itself.

By default UDP Integration will use 11560 port, but you can change this to any available port in your case.

We leave other options by default, but there is brief description of them:

  • Enable broadcast - integration will accepts broadcast address packets - a flag indicating that integration will accept UDP packets that were sent to broadcast address;
  • Size of the buffer for inbound socket - the size in KBytes of the socket data receive buffer;

Choose device payload type for Handler Configuration:

Please select Handler Type as TEXT.

image

To parse the payload properly, please make sure that next values are set:

  • Charset Name - incoming bytes will be converted to string using provided charset; Leave it by default for this demo - UTF-8;

Click “Add” to finish adding integration.

image

Please select Handler Type as JSON.

image

Click “Add” to finish adding integration.

image

Please select Handler Type as BINARY.

image

Click “Add” to finish adding integration.

image

Please select Handler Type as HEX.

image

Click “Add” to finish adding integration.

image

Click Add to save the Integration.

We can send a downlink message to the device from Rule chain using the rule node. To be able to send downlink over integration we need to modify ‘Edge Root Rule chain’ on the cloud. For example, create an integration downlink node and set the ‘Attributes updated’ link to it. When changes are made to device attribute, the downlink message will be sent to the integration.

Assign Integration to Edge

Once converter and integration templates are created, we can assign Integration template to Edge.

  • Click Manage Integrations button of Edge entity
  • Assign Integration to the Edge
  • Login to your ThingsBoard Edge instance and open Integrations page

Installing and running external UDP Integration

Please refer to the Remote Integration guide and install UDP Integration service locally or on separate machine.

Please use Integration key and Integration secret from the above section for your UDP Integration configuration.

Once ThingsBoard UDP Integration has been created, the UDP server starts, and then it waits for data from the devices.

Choose device payload type to send uplink message:

The created device with data can be seen in the section Device groups -> All on the Edge:

Received data can be viewed in the Uplink converter. In the ‘In’ and ‘Out’ blocks of the Events tab:

Now let’s check downlink functionality.

Now we’ll need to send again message to UDP integration to see downlink response. Please use the same command that was used before, but replace parameter q1 to q120. With these changes nc utility will wait 120 seconds for downlink message. Additionally, please remove w1 parameter.

After you’ll send uplink command, you have 120 seconds to add firmware shared attribute:

To make sure that downlink message sent to integration you can check ‘Events’ tab of integration:

An example of sent message and a response from ThingsBoard Edge in the terminal:

Next steps