编解码插件
编解码插件是供物联网平台调用,可以完成二进制格式与JSON格式相互转换、也可以完成JSON格式之间的转换。
以场景为例,部分设备应用层数据的格式由设备自行定义,不采用流行的JSON格式,而是采用二进制格式。但是,物联网平台与应用侧使用JSON格式进行通信。因此,您需要开发编码插件,供物联网平台调用,以完成二进制格式和JSON格式的转换。
使用JavaScript开发插件
脚本化开发是指使用JavaScript脚本实现编解码的功能。物联网平台支持JavaScript脚本编解码的功能,根据您提交的脚本文件,实现设备二进制格式与JSON格式相互转换或JSON格式之间的转换。本文以温度计、智能门锁、路灯设备为例,介绍如何开发一个支持设备属性上报和命令下发的JavaScript编解码脚本,并介绍JavaScript脚本开发编解码插件的格式转换要求和调试方法。
说明:
- JavaScript语法规则需要遵循ECMAScript 5.1规范。
- 产品部署JavaScript脚本插件后,该产品下所有设备的上下行数据都会进行JavaScript脚本解析。开发者实现JavaScript插件时需要注意实现设备所有的上下行场景。
- 上行数据JavaScript解码后的JSON数据需要符合平台的格式要求。
- 使用JavaScript编码时需要根据平台对应的JSON格式转换为对应的二进制码流或JSON。
- 部署后,JavaScript脚本文件路径为:
/oss/business/{租户ID}/iot-device/{脚本文件ID}.js
对于在编解码代码中常用的一些函数,作为公用参数,不会在每个例子中列举这些代码,但是请注意,在实际运行这些编解码插件时,请将这些通用函数附加到脚本中。
/**
* 读取字节数组中的整数值
*
* @param array 字节数组
* @returns 整数值
*/
function readInt(array) {
var value = 0;
for (var i = 0; i < array.length; i++) {
value = (value * 256) + array[i];
}
return value;
}
/**
* 生成一个随机字符串
* @param length 字符串长度
* @returns
*/
function makeid(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
}
- 温度计设备进行温度上报(解码)
场景说明:有一类温度计设备,因为网络通信能力和数据解析能力有限,只能进行很有限的数据上报,以二进制的方式上报温度到平台
物模型中定义了名为temperature
的属性,每当收到设备上报的二进制数据,并判断其为属性上报的topic时,就将其上报的二进制内容转换成代表温度的数字,并以标准数据上报格式上报到平台:
/* jshint esversion: 6 */
/**
* 设备上报数据到物联网平台时调用此接口进行解码, 将设备的原始数据解码为符合产品模型定义的JSON格式数据。
* 该接口名称和入参已经定义好,开发者只需要实现具体接口即可。
* @param byte[] payload 设备上报的原始码流
* @param string topic MQTT设备上报数据时的topic,非MQTT设备上报数据时不携带该参数
* @return string json 符合产品模型定义的JSON格式字符串
*/
function decode(payload, topic) {
if (topic.endsWith("thing/properties/up")) {
return JSON.stringify({
"id": makeid(32),
"version": "1.0",
"method": "thing.properties.up",
"sys": {
"ack": 1
},
"params": {
"temperature": {
"value": readInt(payload),
"time": Date.now()
}
}
});
}
else{
return JSON.stringify({});
}
}
- 智能门锁告警事件上报(解码)
场景说明:目前有一款智能门锁,能够根据当前运行状态进行事件上报,但是由于通信能力限制,其只能以二进制的格式上报简单的数字内容,其中0代表正常开门,1代表正常关门,2代表门长时间未关闭
我们希望当门锁上报的事件值为2时,向平台上报告警事件,平台定义了一种告警事件,其事件ID为door_alarm_event
,具有参数ID为alarmTime
的告警时间参数
编写如下代码,只有当门锁上报的值为2时,才上报告警事件,否则不做任何处理(当解析结果为空时平台会原报文转送):
/* jshint esversion: 6 */
/**
* 设备上报数据到物联网平台时调用此接口进行解码, 将设备的原始数据解码为符合产品模型定义的JSON格式数据。
* 该接口名称和入参已经定义好,开发者只需要实现具体接口即可。
* @param byte[] payload 设备上报的原始码流
* @param string topic MQTT设备上报数据时的topic,非MQTT设备上报数据时不携带该参数
* @return string json 符合产品模型定义的JSON格式字符串
*/
function decode(payload, topic) {
let result = JSON.stringify({});
if (topic.endsWith("thing/event/up")) {
let value = readInt(payload);
if (value == 2) {
return JSON.stringify({
"id": makeid(32),
"version": "1.0",
"sys": {
"ack": 1
},
"identifier": "door_alarm_event",
"params": {
"value": {
"alarmTime": Date.now()
},
"time": Date.now()
},
"method": "thing.event.up"
});
}
}
return result;
}
3. 为路灯设备设置属性(编码)
场景说明:有一款路灯设备,支持接收设置属性命令,但是其只接收二进制格式的简单命令,不能解析JSON数据,故在数据下发时需要对其数据进行编码,下面的代码将下发数据转换.
/**
* 物联网平台下发指令时,调用此接口进行编码, 将产品模型定义的JSON格式数据编码为设备的原始码流。
* 该接口名称和入参格式已经定义好,开发者只需要实现具体接口即可。
* @param string json 符合产品模型定义的JSON格式字符串
* @return byte[] payload 编码后的原始码流
*/
function encode(json) {
var data = JSON.parse(json)
if (data.params.power) {
return intToBytes(data.params.power);
}
}
function intToBytes(int, byteOrder = 'big') {
const byteArray = new Uint8Array(4);
if (byteOrder === 'big') {
byteArray[0] = (int >>> 24) & 0xFF;
byteArray[1] = (int >>> 16) & 0xFF;
byteArray[2] = (int >>> 8) & 0xFF;
byteArray[3] = int & 0xFF;
} else if (byteOrder === 'little') {
byteArray[0] = int & 0xFF;
byteArray[1] = (int >>> 8) & 0xFF;
byteArray[2] = (int >>> 16) & 0xFF;
byteArray[3] = (int >>> 24) & 0xFF;
} else {
throw new Error('Invalid byte order');
}
return byteArray;
}