产品定价 立即试用
云平台
欧洲地区
文档 > 集成 > UDP
入门
指南 API 常见问题
目录

UDP集成

文档信息图标
ThingsBoard PE 功能

专业版支持Platform Integrations功能。
请使用ThingsBoard Cloud自行安装平台实例。

UDP集成可从采用UDP协议的设备向ThingsBoard流式传输数据,并将这些设备的负载转换为ThingsBoard格式。

文档信息图标

请注意:UDP集成只能以远程集成方式启动。可在运行TB实例的同一台机器上启动,也可在能通过网络访问TB实例的另一台机器上启动。

请参阅集成示意图了解更多。

image

前置条件

本教程将使用:

  • ThingsBoard Professional Edition实例 — eu.thingsboard.cloud;
  • 在外部运行且已连接ThingsBoard Cloud的UDP集成;

  • echo命令,用于显示一行文本并将其输出重定向到netcatnc)工具;
  • netcatnc)工具,用于建立UDP连接、接收数据并传输;

假设我们有一台正在发送当前温度和湿度读数的传感器。 传感器SN-001将数据发送到运行UDP集成的机器的11560端口。

为便于演示,我们假设设备能够以4种不同负载类型发送数据。 可根据设备能力和业务场景选择负载类型:

此情况下,payload 格式如下:

1
SN-001,default,temperature,25.7,humidity,69

此情况下,payload 格式如下:

1
2
3
4
5
6
{
  "deviceName": "SN-001",
  "deviceType": "default",
  "temperature": 25.7,
  "humidity": 69
}

此情况下,payload 格式如下:

1
\x53\x4e\x2d\x30\x30\x31\x64\x65\x66\x61\x75\x6c\x74\x32\x35\x2e\x37\x36\x39

该 payload 中各字节说明如下:

  • 0-5 字节 - \x53\x4e\x2d\x30\x30\x31 - 设备名称,转为文本为 SN-001
  • 6-12 字节 - \x64\x65\x66\x61\x75\x6c\x74 - 设备类型,转为文本为 default
  • 13-16 字节 - \x32\x35\x2e\x37 - 温度遥测,转为文本为 25.7
  • 17-18 字节 - \x36\x39 - 湿度遥测,转为文本为 69

此情况下 payload 为十六进制字符串:

1
534e2d30303164656661756c7432352e373639

该 payload 中各字节说明如下:

  • 0-5 字节 - 534e2d303031 - 设备名称,转为文本为 SN-001
  • 6-12 字节 - 64656661756c74 - 设备类型,转为文本为 default
  • 13-16 字节 - 32352e37 - 温度遥测,转为文本为 25.7
  • 17-18 字节 - 3639 - 湿度遥测,转为文本为 69
文档信息图标

请注意
在运行UDP集成的机器上,必须开放11560端口以接收入站连接——nc工具需能连接到UDP socket。若在本地运行,一般无需额外修改。

添加UDP集成

1.基本设置

进入“Integrations center”的“Integrations”页面,点击“plus”按钮开始添加新集成。选择“UDP”类型并点击“Next”;

image


2.上行数据转换器

上行转换器是用于解析并将UDP集成接收的数据转换为ThingsBoard格式的脚本。 deviceNamedeviceType为必填,attributes和telemetry为可选。attributes和telemetry为扁平键值对象,不支持嵌套对象。

选择设备负载类型以配置解码器:

可使用 TBEL(TBEL)或 JavaScript 开发用户自定义函数。 建议使用 TBEL,其在ThingsBoard 中的执行效率远高于 JS。

请复制以下 TBEL 脚本:

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

// decode payload to string
var strArray = decodeToString(payload);
var payloadArray = strArray.replaceAll("\"", "").replaceAll("\\\\n", "").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 'decodeToString' and 'decodeToJson' are already built-in **/

return result;


若使用 JavaScript decoder function,请使用以下脚本:

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
/** 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;


将复制的脚本粘贴到 decoder function 区域,然后点击「Next」;

image

文档信息图标

NOTE
Debug 模式对开发和故障排查很有用,但在生产环境中启用会显著增加数据库占用的磁盘空间,因为所有调试数据都会存储其中。强烈建议调试完成后关闭 Debug 模式。

可使用 TBEL(TBEL)或 JavaScript 开发用户自定义函数。 建议使用 TBEL,其在ThingsBoard 中的执行效率远高于 JS。

请复制以下 TBEL 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** 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 'decodeToString' and 'decodeToJson' are already built-in **/

return result;


若使用 JavaScript decoder function,请使用以下脚本:

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;


将复制的脚本粘贴到 decoder function 区域,然后点击「Next」;

image

文档信息图标

NOTE
Debug 模式对开发和故障排查很有用,但在生产环境中启用会显著增加数据库占用的磁盘空间,因为所有调试数据都会存储其中。强烈建议调试完成后关闭 Debug 模式。

可使用 TBEL(TBEL)或 JavaScript 开发用户自定义函数。 建议使用 TBEL,其在ThingsBoard 中的执行效率远高于 JS。

请复制以下 TBEL 脚本:

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
/** 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 'decodeToString' and 'decodeToJson' are already built-in **/

return result;


若使用 JavaScript decoder function,请使用以下脚本:

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
/** 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;


将复制的脚本粘贴到 decoder function 区域,然后点击「Next」;

image

文档信息图标

NOTE
Debug 模式对开发和故障排查很有用,但在生产环境中启用会显著增加数据库占用的磁盘空间,因为所有调试数据都会存储其中。强烈建议调试完成后关闭 Debug 模式。

可使用 TBEL(TBEL)或 JavaScript 开发用户自定义函数。 建议使用 TBEL,其在ThingsBoard 中的执行效率远高于 JS。

请复制以下 TBEL 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/** 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 **/

// Hexadecimal string to string
function hexToString(hex) {
    return bytesToString(hexToBytes(hex));
}

return result;


若使用 JavaScript decoder function,请使用以下脚本:

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
/** 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;


将复制的脚本粘贴到 decoder function 区域,然后点击「Next」;

image

文档信息图标

NOTE
Debug 模式对开发和故障排查很有用,但在生产环境中启用会显著增加数据库占用的磁盘空间,因为所有调试数据都会存储其中。强烈建议调试完成后关闭 Debug 模式。

3.下行数据转换器

在添加下行转换器步骤,可选择已有或新建下行转换器。此处保持“Downlink data converter”为空。点击“Skip”;

image


4.连接

如前所述,“Execute remotely”选项已勾选且不可修改——UDP集成只能为remote类型。

默认情况下UDP集成使用11560端口,您可根据需要改为任意可用端口。

请记录Integration keyIntegration secret——后续在远程UDP集成配置中将使用这些值。

Enable broadcast - integration will accepts broadcast address packets选项保持默认。该标识表示集成将接受发往广播地址的UDP包。


选择Handler Configuration的设备负载类型:

请将 Handler Type 选择为 TEXT

image

为正确解析 payload,请确保设置以下值:

  • Charset Name:入站字节将使用指定 charset 转为字符串;本示例保持默认 UTF-8 即可。

点击「Add」完成 integration 添加。

image

请将 Handler Type 选择为 JSON

image

点击「Add」完成 integration 添加。

image

请将 Handler Type 选择为 BINARY

image

点击「Add」完成 integration 添加。

image

请将 Handler Type 选择为 HEX

image

点击「Add」完成 integration 添加。

image

安装并运行外部UDP集成

请参阅远程集成指南,在本地或单独机器上安装UDP集成服务。

使用上文中的Integration keyIntegration secret配置您的UDP集成。

发送上行消息

创建ThingsBoard UDP集成后,UDP服务启动并等待设备数据。

选择设备负载类型以发送上行消息:

进入“Devices”页面,应能看到由UDP集成配置的SN-001设备。 点击设备,进入“Latest telemetry”标签可查看“temperature”键及其值(25.7)以及“humidity”键及其值(69)。

image

高级用法:下行

要从ThingsBoard向设备发送下行消息,需定义下行转换器。

添加下行转换器

可使用 TBEL(TBEL)或 JavaScript 开发用户自定义函数。 建议使用 TBEL,其在ThingsBoard 中的执行效率远高于 JS。

将下行数据转换器添加到UDP集成的步骤:

  • 进入“Integrations”页面,点击UDP集成打开详情,点击“pencil”图标进入编辑模式;

  • 输入下行数据转换器名称并点击“Create new converter”;

  • 将脚本粘贴到encoder function区域,点击“Add”;

  • 应用更改。

文档信息图标

可选配置Cache SizeCache time to live in minutes——用于在存储连接时避免内存泄漏(仅UDP下行支持)。
Cache Size — UDP客户端消息的最大数量。
Cache time to live in minutes — 消息存储时长(分钟)。

修改Root Rule Chain

集成配置就绪后,需进入“Rule Chains”页面并配置“Root Rule Chain”,使“Attributes updated”和“Post attributes”消息转发到下行数据转换器:

  • 在Root Rule Chain编辑器中找到“integration downlink”节点并拖入规则链;

  • 命名为“UDP Downlink”,指定“UDP integration”,点击“Add”;

  • 从“message type switch”节点拖拽连线到“UDP integration”节点,标签为“Attributes updated”和“Post attributes”。保存所有更改;

测试下行

要测试下行,请在设备上创建shared attribute

  • 进入“Devices”页面。点击设备,进入“Attributes”标签。选择“Shared attributes”,点击“plus”图标;

  • 输入属性名及其值(例如键名为“firmware”、值为“v1.1”)并点击“Save”;

要接收下行消息,需设置响应超时-w10(该选项决定等待响应的时长)并再次发送上行消息:

1
echo -e 'SN-001,default,temperature,25.7,humidity,69' | nc -w10 -u 127.0.0.1 11560

终端中应能看到ThingsBoard的如下响应:

image

文档信息图标

注意
使用UDP集成且连接建立较长时间时,您将只收到一条下行消息。其余消息将保存在服务端,并在下次上行时发送。

下一步