更新时间:2024-08-21 GMT+08:00

使用JavaScript开发插件

物联网平台支持JavaScript脚本编解码的功能,根据您提交的脚本文件,实现设备二进制格式与JSON格式相互转换或JSON格式之间的转换。本文以烟感设备为例,介绍如何开发一个支持设备属性上报和命令下发的JavaScript编解码脚本,并介绍JavaScript脚本开发编解码插件的格式转换要求和调试方法。

  • JavaScript语法规则需要遵循ECMAScript 5.1规范
  • 脚本编解码插件只支持es6的let和const,其他不支持,如箭头函数等。
  • JavaScript脚本大小不能超过1M。
  • 产品部署JavaScript脚本插件后,该产品下所有设备的上下行数据都会进行JavaScript脚本解析。开发者实现JavaScript插件时需要注意实现设备所有的上下行场景。
  • 上行数据JavaScript解码后的JSON数据需要符合平台的格式要求,具体格式要求见: 数据解码格式定义
  • 平台下行指令的JSON格式定义见:数据编码格式定义,使用JavaScript编码时需要根据平台对应的JSON格式转换为对应的二进制码流或JSON。
  • 脚本编辑提供自动保存功能,每次保存的间隔时间为10秒,在脚本输入框右上角勾选自动保存即可开启此功能。

烟感设备样例

场景说明

有一款烟感设备,具有如下特征:

  • 具有烟雾报警功能(火灾等级)和温度上报功能。
  • 支持远程控制命令,可远程打开报警功能。比如火灾现场温度,远程打开烟雾报警,提醒住户疏散。
  • 该款烟感设备,设备能力比较弱,无法按照设备接口定义的JSON格式上报数据,只能上报简单的二进制数据。

产品模型定义

在烟感产品的开发空间,完成产品模型定义。
  • level:火灾级别,用于表示火灾的严重程度。
  • temperature:温度,用于表示火灾现场温度。
  • SET_ALARM:打开或关闭告警命令,value=0表示关闭,value=1表示打开。
    图1 模型定义-smokedetector

编解码插件开发

  1. 在烟感产品的详情页面,选择“插件开发”,单击“脚本化开发”。

    图2 插件开发-脚本化开发

  2. 编写脚本,实现二进制数据到JSON数据的转换。脚本需要实现如下两个方法:

    • decode:将设备上报的二进制数据转换为平台产品模型中定义的JSON格式。具体的JSON格式要求见: 数据解码格式定义
    • encode:平台有下行数据发送给设备时,将平台的JSON格式数据转换为设备支持的二进制格式。平台的JSON格式见:数据编码格式定义
    针对当前烟感产品实现的JavaScript样例如下:
      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
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    //上行消息类型
    var MSG_TYPE_PROPERTIES_REPORT = 'properties_report'; //设备属性上报
    var MSG_TYPE_COMMAND_RSP = 'command_response'; //设备返回命令响应
    var MSG_TYPE_PROPERTIES_SET_RSP = 'properties_set_response'; //设备返回属性设置响应
    var MSG_TYPE_PROPERTIES_GET_RSP = 'properties_get_response'; //设备返回属性查询响应
    var MSG_TYPE_MESSAGE_UP = 'message_up'; //设备消息上报
    //下行消息类型
    var MSG_TYPE_COMMANDS = 'commands'; //平台命令下发
    var MSG_TYPE_PROPERTIES_SET = 'properties_set'; //平台下发属性设置请求
    var MSG_TYPE_PROPERTIES_GET = 'properties_get'; //平台下发属性查询请求
    var MSG_TYPE_MESSAGE_DOWN = 'messages'; //平台消息下发
    //MQTT设备上行消息,topic同消息类型的映射表
    var TOPIC_REG_EXP = {
        'properties_report': new RegExp('\\$oc/devices/(\\S+)/sys/properties/report'),
        'properties_set_response': new RegExp('\\$oc/devices/(\\S+)/sys/properties/set/response/request_id=(\\S+)'),
        'properties_get_response': new RegExp('\\$oc/devices/(\\S+)/sys/properties/get/response/request_id=(\\S+)'),
        'command_response': new RegExp('\\$oc/devices/(\\S+)/sys/commands/response/request_id=(\\S+)'),
        'message_up': new RegExp('\\$oc/devices/(\\S+)/sys/messages/up')
    };
    /*
    示例:烟感设备上报属性和回复命令响应时,携带的是二进制码流,通过javascript脚本将二进制码流数据解码为符合产品模型定义的json格式数据
    传入参数:
      payload:[0x00, 0x50, 0x00, 0x5a]
      topic:$oc/devices/cf40f3c4-7152-41c6-a201-a2333122054a/sys/properties/report
    输出结果:
      {"msg_type":"properties_report","services":[{"service_id":"smokerdector","properties":{"level":80,"temperature":90}}]}
    传入参数:
      payload: [0x02, 0x00, 0x00, 0x01]
      topic: $oc/devices/cf40f3c4-7152-41c6-a201-a2333122054a/sys/commands/response/request_id=bf40f0c4-4022-41c6-a201-c5133122054a
    输出结果:
      {"msg_type":"command_response","result_code":0,"command_name":"SET_ALARM","service_id":"smokerdector","paras":{"value":"1"}}
    */
    function decode(payload, topic) {
        var jsonObj = {};
        var msgType = '';
        //如果有topic参数,根据topic参数解析消息类型
        if (null != topic) {
            msgType = topicParse(topic);
        }
        //将payload通过0xFF进行与操作,获取其对应的补码
        var uint8Array = new Uint8Array(payload.length);
        for (var i = 0; i < payload.length; i++) {
            uint8Array[i] = payload[i] & 0xff;
        }
        var dataView = new DataView(uint8Array.buffer, 0);
        //判断是属性上报的话,将二进制数据转换为属性上报格式
        if (msgType == MSG_TYPE_PROPERTIES_REPORT) {
            //设置serviceId参数值,该参数值对应产品模型中的服务类型smokerdector
            var serviceId = 'smokerdector';
            //从码流中获取level值
            var level = dataView.getInt16(0);
            //从码流中获取temperature值
            var temperature  = dataView.getInt16(2);
            //转换为属性上报的JSON格式
            jsonObj = {"msg_type":"properties_report","services":[{"service_id":serviceId,"properties":{"level":level,"temperature":temperature}}]};
        }else if (msgType == MSG_TYPE_COMMAND_RSP) { //判断是命令响应的话,将二进制数据转换为命令响应格式
            //设置serviceId参数值,该参数值对应产品模型中的服务类型smokerdector
            var serviceId = 'smokerdector';
            var command = dataView.getInt8(0); //从二进制码流中获取命令名ID
            var command_name = '';
            if (2 == command) {
                command_name = 'SET_ALARM';
            }
            var result_code  = dataView.getInt16(1); //从二进制码流中获取命令执行结果
            var value = dataView.getInt8(3); //从二进制码流中获取命令执行结果返回值
            //转换为命令响应的JSON格式
            jsonObj = {"msg_type":"command_response","result_code":result_code,"command_name":command_name,"service_id":serviceId,"paras":{"value":value}};
        }
        //转换为JSON格式的字符串数据
        return JSON.stringify(jsonObj);
    }
    /*
    示例数据:命令下发时,通过javascript的encode方法将平台JSON格式的数据,编码为二进制码流
    传入参数 ->
        {"msg_type":"commands","command_name":"SET_ALARM","service_id":"smokerdector","paras":{"value":1}}
    输出结果 ->
        [0x01,0x00, 0x00, 0x01]
    */
    function encode(json) {
        //转换为JSON对象
        var jsonObj = JSON.parse(json);
        //获取消息类型
        var msgType = jsonObj.msg_type;
        var payload = [];
        //将JSON格式数据转换为二进制数据
        if (msgType == MSG_TYPE_COMMANDS) // 命令下发
        {
            payload = payload.concat(buffer_uint8(1)); // 标识命令下发
            if (jsonObj.command_name == 'SET_ALARM') {
                payload = payload.concat(buffer_uint8(0)); // 标识命令名称
            }
            var paras_value = jsonObj.paras.value;
            payload = payload.concat(buffer_int16(paras_value)); // 设置命令属性值
        }
        //返回编码后的二进制数据
        return payload;
    }
    //根据topic名称解析出消息类型
    function topicParse(topic) {
        for(var type in TOPIC_REG_EXP){
            var pattern = TOPIC_REG_EXP[type];
            if (pattern.test(topic)) {
                return type;
            }
        }
        return '';
    }
    //将8位无符号整型转换为byte数组
    function buffer_uint8(value) {
        var uint8Array = new Uint8Array(1);
        var dataView = new DataView(uint8Array.buffer);
        dataView.setUint8(0, value);
        return [].slice.call(uint8Array);
    }
    //将16位无符号整型转换为byte数组
    function buffer_int16(value) {
        var uint8Array = new Uint8Array(2);
        var dataView = new DataView(uint8Array.buffer);
        dataView.setInt16(0, value);
        return [].slice.call(uint8Array);
    }
    //将32位无符号整型转换为byte数组
    function buffer_int32(value) {
        var uint8Array = new Uint8Array(4);
        var dataView = new DataView(uint8Array.buffer);
        dataView.setInt32(0, value);
        return [].slice.call(uint8Array);
    }
    

  3. 在线调试脚本。脚本编辑完成后,在模拟输入下,选择模拟类型,输入模拟数据在线调试脚本。

    1. 模拟设备上报属性数据时将二进制码流转换为JSON数据。
      • 在topic输入框中选择设备上报的topic:$oc/devices/{device_id}/sys/properties/report。
      • 选择模拟类型为“解码”,输入以下模拟的设备数据,然后单击“调试”。
        0050005a
      • 脚本编解码引擎会根据输入的参数和您提交javascript脚本中的decode方法,将二进制码流转换为JSON格式,并将调试结果显示在输入框中。
        图3 脚本化开发-调试解码
      • 检查调试结果是否符合预期,如果不符合预期,则修改代码后重新进行调试。
    2. 模拟将应用下发的命令编码为设备能识别的二进制码流。
      • 选择模拟类型为“编码”,输入需要模拟的命令下发格式,然后单击“调试”。
        1
        2
        3
        4
        5
        6
        7
        8
        9
        {
        	"msg_type": "commands",
        	"request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
        	"command_name": "SET_ALARM",
        	"service_id": "smokerdector",
        	"paras": {
        		"value": "1"
        	}
        }
        
      • 脚本编解码引擎会根据输入的参数和您提交javascript脚本中的encode方法,将JSON格式数据转换为二进制码流,并将调试结果显示在输入框中。
        图4 脚本化开发-调试编码
      • 检查调试结果是否符合预期,如果不符合预期,则修改代码后重新进行调试。

  4. 部署脚本。确认脚本可以正确进行编解码后,单击“部署”,将该脚本提交到物联网平台,以供数据上下行时,物联网平台调用该脚本进行编解码。

    图5 脚本化开发-部署

  5. 使用真实设备调试。正式使用脚本之前,请使用真实设备与物联网平台进行上下行消息通信,以验证物联网平台能顺利调用脚本,解析上下行数据。

JavaScript编解码插件模板

以下为JavaScript编解码插件的模板,开发者需要按照平台提供的模板,实现对应的接口。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * 设备上报数据到物联网平台时调用此接口进行解码, 将设备的原始数据解码为符合产品模型定义的JSON格式数据。
 * 该接口名称和入参已经定义好,开发者只需要实现具体接口即可。
 * @param byte[] payload   设备上报的原始码流
 * @param string topic     MQTT设备上报数据时的topic,非MQTT设备上报数据时不携带该参数
 * @return string json     符合产品模型定义的JSON格式字符串
 */
function decode(payload, topic) {
    var jsonObj = {};
    return JSON.stringify(jsonObj);
}

/**
 * 物联网平台下发指令时,调用此接口进行编码, 将产品模型定义的JSON格式数据编码为设备的原始码流。
 * 该接口名称和入参格式已经定义好,开发者只需要实现具体接口即可。
 * @param string json      符合产品模型定义的JSON格式字符串
 * @return byte[] payload  编码后的原始码流
 */
function encode(json) {
    var payload = [];
    return payload;
}

MQTT设备接入时JavaScript编解码插件样例

以下为MQTT设备JavaScript编解码插件的样例,开发者可以根据样例实现对应场景的二进制和JSON格式的转换。

  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
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//上行消息类型
var MSG_TYPE_PROPERTIES_REPORT = 'properties_report'; //设备属性上报
var MSG_TYPE_COMMAND_RSP = 'command_response'; //设备返回命令响应
var MSG_TYPE_PROPERTIES_SET_RSP = 'properties_set_response'; //设备返回属性设置响应
var MSG_TYPE_PROPERTIES_GET_RSP = 'properties_get_response'; //设备返回属性查询响应
var MSG_TYPE_MESSAGE_UP = 'message_up'; //设备消息上报
//下行消息类型
var MSG_TYPE_COMMANDS = 'commands'; //平台命令下发
var MSG_TYPE_PROPERTIES_SET = 'properties_set'; //平台下发属性设置请求
var MSG_TYPE_PROPERTIES_GET = 'properties_get'; //平台下发属性查询请求
var MSG_TYPE_MESSAGE_DOWN = 'messages'; //平台消息下发
//MQTT设备上行消息,topic同消息类型的映射表
var TOPIC_REG_EXP = {
    'properties_report': new RegExp('\\$oc/devices/(\\S+)/sys/properties/report'),
    'properties_set_response': new RegExp('\\$oc/devices/(\\S+)/sys/properties/set/response/request_id=(\\S+)'),
    'properties_get_response': new RegExp('\\$oc/devices/(\\S+)/sys/properties/get/response/request_id=(\\S+)'),
    'command_response': new RegExp('\\$oc/devices/(\\S+)/sys/commands/response/request_id=(\\S+)'),
    'message_up': new RegExp('\\$oc/devices/(\\S+)/sys/messages/up')
};
/*
示例:烟感设备上报属性和回复命令响应时,携带的是二进制码流,通过javascript脚本将二进制码流数据解码为符合产品模型定义的json格式数据
传入参数:
  payload:[0x00, 0x50, 0x00, 0x5a]
  topic:$oc/devices/cf40f3c4-7152-41c6-a201-a2333122054a/sys/properties/report
输出结果:
  {"msg_type":"properties_report","services":[{"service_id":"smokerdector","properties":{"level":80,"temperature":90}}]}
传入参数:
  payload: [0x02, 0x00, 0x00, 0x01]
  topic: $oc/devices/cf40f3c4-7152-41c6-a201-a2333122054a/sys/commands/response/request_id=bf40f0c4-4022-41c6-a201-c5133122054a
输出结果:
  {"msg_type":"command_response","result_code":0,"command_name":"SET_ALARM","service_id":"smokerdector","paras":{"value":"1"}}
*/
function decode(payload, topic) {
    var jsonObj = {};
    var msgType = '';
    //如果有topic参数,根据topic参数解析消息类型
    if (null != topic) {
        msgType = topicParse(topic);
    }
    //将payload通过0xFF进行与操作,获取其对应的补码
    var uint8Array = new Uint8Array(payload.length);
    for (var i = 0; i < payload.length; i++) {
        uint8Array[i] = payload[i] & 0xff;
    }
    var dataView = new DataView(uint8Array.buffer, 0);
    //判断是属性上报的话,将二进制数据转换为属性上报格式
    if (msgType == MSG_TYPE_PROPERTIES_REPORT) {
        //设置serviceId参数值,该参数值对应产品模型中的服务类型smokerdector
        var serviceId = 'smokerdector';
        //从码流中获取level值
        var level = dataView.getInt16(0);
        //从码流中获取temperature值
        var temperature = dataView.getInt16(2);
        //转换为属性上报的JSON格式
        jsonObj = {
            "msg_type": "properties_report",
            "services": [{"service_id": serviceId, "properties": {"level": level, "temperature": temperature}}]
        };
    } else if (msgType == MSG_TYPE_COMMAND_RSP) { //判断是命令响应的话,将二进制数据转换为命令响应格式
        //设置serviceId参数值,该参数值对应产品模型中的服务类型smokerdector
        var serviceId = 'smokerdector';
        var command = dataView.getInt8(0); //从二进制码流中获取命令名ID
        var command_name = '';
        if (2 == command) {
            command_name = 'SET_ALARM';
        }
        var result_code = dataView.getInt16(1); //从二进制码流中获取命令执行结果
        var value = dataView.getInt8(3); //从二进制码流中获取命令执行结果返回值
        //转换为命令响应的JSON格式
        jsonObj = {
            "msg_type": "command_response",
            "result_code": result_code,
            "command_name": command_name,
            "service_id": serviceId,
            "paras": {"value": value}
        };
    } else if (msgType == MSG_TYPE_PROPERTIES_SET_RSP) {
        //转换为属性设置响应的JSON格式
        //jsonObj = {"msg_type":"properties_set_response","result_code":0,"result_desc":"success"};
    } else if (msgType == MSG_TYPE_PROPERTIES_GET_RSP) {
        //转换为属性查询响应的JSON格式
        //jsonObj = {"msg_type":"properties_get_response","services":[{"service_id":"analog","properties":{"PhV_phsA":"1","PhV_phsB":"2"}}]};
    } else if (msgType == MSG_TYPE_MESSAGE_UP) {
        //转换为消息上报的JSON格式
        //jsonObj = {"msg_type":"message_up","content":"hello"};
    }
    //转换为JSON格式的字符串数据
    return JSON.stringify(jsonObj);
}
/*
示例数据:命令下发时,通过javascript的encode方法将平台JSON格式的数据,编码为二进制码流
传入参数 ->
    {"msg_type":"commands","command_name":"SET_ALARM","service_id":"smokerdector","paras":{"value":1}}
输出结果 ->
    [0x01,0x00, 0x00, 0x01]
*/
function encode(json) {
    //转换为JSON对象
    var jsonObj = JSON.parse(json);
    //获取消息类型
    var msgType = jsonObj.msg_type;
    var payload = [];
    //将JSON格式数据转换为二进制数据
    if (msgType == MSG_TYPE_COMMANDS) {// 命令下发
        //命令下发格式样例: {"msg_type":"commands","command_name":"SET_ALARM","service_id":"smokerdector","paras":{"value":1}}
        //根据命令下发的格式转换为二进制码流
        payload = payload.concat(buffer_uint8(1)); // 标识命令下发
        if (jsonObj.command_name == 'SET_ALARM') {
            payload = payload.concat(buffer_uint8(0)); // 标识命令名称
        }
        var paras_value = jsonObj.paras.value;
        payload = payload.concat(buffer_int16(paras_value)); // 设置命令属性值
    } else if (msgType == MSG_TYPE_PROPERTIES_SET) {
        //属性设置格式样例:{"msg_type":"properties_set","services":[{"service_id":"Temperature","properties":{"value":57}}]}
        //开发者有对应属性设置场景时需要根据该JSON格式转换为对应的二进制码流
    } else if (msgType == MSG_TYPE_PROPERTIES_GET) {
        //属性查询格式样例:{"msg_type":"properties_get","service_id":"Temperature"}
        //开发者有对应属性查询场景时需要根据该JSON格式转换为对应的二进制码流
    } else if (msgType == MSG_TYPE_MESSAGE_DOWN) {
        //消息下发格式样例:{"msg_type":"messages","content":"hello"}
        //开发者对应消息下发场景时需要根据该JSON格式转换为对应的二进制码流
    }
    //返回编码后的二进制数据
    return payload;
}
//根据topic名称解析出消息类型
function topicParse(topic) {
    for (var type in TOPIC_REG_EXP) {
        var pattern = TOPIC_REG_EXP[type];
        if (pattern.test(topic)) {
            return type;
        }
    }
    return '';
}
//将8位无符号整型转换为byte数组
function buffer_uint8(value) {
    var uint8Array = new Uint8Array(1);
    var dataView = new DataView(uint8Array.buffer);
    dataView.setUint8(0, value);
    return [].slice.call(uint8Array);
}

//将16位无符号整型转换为byte数组
function buffer_int16(value) {
    var uint8Array = new Uint8Array(2);
    var dataView = new DataView(uint8Array.buffer);
    dataView.setInt16(0, value);
    return [].slice.call(uint8Array);
}
//将32位无符号整型转换为byte数组
function buffer_int32(value) {
    var uint8Array = new Uint8Array(4);
    var dataView = new DataView(uint8Array.buffer);
    dataView.setInt32(0, value);
    return [].slice.call(uint8Array);
}

NB-IoT设备接入时JavaScript编解码插件样例

以下为NB-IoT设备JavaScript编解码插件的样例,开发者可以根据样例实现NB-IoT设备数据上报和命令下发的编解码插件开发。

  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
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
//上行消息类型
var MSG_TYPE_PROPERTIES_REPORT = 'properties_report'; //设备属性上报
var MSG_TYPE_COMMAND_RSP = 'command_response'; //设备返回命令响应
//下行消息类型
var MSG_TYPE_COMMANDS = 'commands'; //平台命令下发
var MSG_TYPE_PROPERTIES_REPORT_REPLY = 'properties_report_reply'; //设备属性上报的响应消息
//消息类型列表
var MSG_TYPE_LIST = {
    0: MSG_TYPE_PROPERTIES_REPORT,          //码流中0字节标识为设备属性上报
    1: MSG_TYPE_PROPERTIES_REPORT_REPLY,    //码流中1字节标识为设备属性上报的响应消息
    2: MSG_TYPE_COMMANDS,                   //码流中2字节标识为平台命令下发
    3: MSG_TYPE_COMMAND_RSP                 //码流中3字节标识为设备返回命令响应
};
/*
示例:烟感设备上报属性和回复命令响应时,携带的是二进制码流,通过javascript脚本将二进制码流数据解码为符合产品模型定义的json格式数据
传入参数:
  payload:[0x00, 0x00, 0x50, 0x00, 0x5a]
输出结果:
  {"msg_type":"properties_report","services":[{"service_id":"smokerdector","properties":{"level":80,"temperature":90}}]}
传入参数:
  payload: [0x03, 0x01, 0x00, 0x00, 0x01]
输出结果:
  {"msg_type":"command_response","request_id":1,"result_code":0,"paras":{"value":"1"}}
*/
function decode(payload, topic) {
    var jsonObj = {};
    //将payload通过0xFF进行与操作,获取其对应的补码
    var uint8Array = new Uint8Array(payload.length);
    for (var i = 0; i < payload.length; i++) {
        uint8Array[i] = payload[i] & 0xff;
    }
    var dataView = new DataView(uint8Array.buffer, 0);
    //从消息码流中的第一个字节获取消息类型
    var messageId = dataView.getInt8(0);
    //判断是属性上报的话,将二进制数据转换为属性上报格式
    if (MSG_TYPE_LIST[messageId] == MSG_TYPE_PROPERTIES_REPORT) {
        //设置serviceId参数值,该参数值对应产品模型中的服务类型smokerdector
        var serviceId = 'smokerdector';
        //从码流中获取level值
        var level = dataView.getInt16(1);
        //从码流中获取temperature值
        var temperature  = dataView.getInt16(3);
        //转换为属性上报的JSON格式
        jsonObj = {"msg_type":"properties_report","services":[{"service_id":serviceId,"properties":{"level":level,"temperature":temperature}}]};
    }else if (MSG_TYPE_LIST[messageId] == MSG_TYPE_COMMAND_RSP) { //判断是命令响应的话,将二进制数据转换为命令响应格式
        var requestId = dataView.getInt8(1);
        var result_code  = dataView.getInt16(2); //从二进制码流中获取命令执行结果
        var value = dataView.getInt8(4); //从二进制码流中获取命令执行结果返回值
        //转换为命令响应的JSON格式
        jsonObj = {"msg_type":"command_response","request_id":requestId,"result_code":result_code,"paras":{"value":value}};
    }
    //转换为JSON格式的字符串数据
    return JSON.stringify(jsonObj);
}
/*
示例数据:命令下发时,通过javascript的encode方法将平台JSON格式的数据,编码为二进制码流
传入参数 ->
    {"msg_type":"commands","request_id":1,"command_name":"SET_ALARM","service_id":"smokerdector","paras":{"value":1}}
输出结果 ->
    [0x02, 0x00, 0x00, 0x00, 0x01]
示例数据:设备上报属性时返回响应消息,通过javascript的encode方法将平台JSON格式的数据,编码为二进制码流
传入参数 ->
    {"msg_type":"properties_report_reply","request":"000050005a","result_code":0}
输出结果 ->
    [0x01, 0x00]
*/
function encode(json) {
    //转换为JSON对象
    var jsonObj = JSON.parse(json);
    //获取消息类型
    var msgType = jsonObj.msg_type;
    var payload = [];
    //将JSON格式数据转换为二进制数据
    if (msgType == MSG_TYPE_COMMANDS) { // 命令下发
        payload = payload.concat(buffer_uint8(2)); // 标识命令下发
        payload = payload.concat(buffer_uint8(jsonObj.request_id)); // 命令ID
        if (jsonObj.command_name == 'SET_ALARM') {
            payload = payload.concat(buffer_uint8(0)); // 标识命令名称
        }
        var paras_value = jsonObj.paras.value;
        payload = payload.concat(buffer_int16(paras_value)); // 设置命令属性值
    } else if (msgType == MSG_TYPE_PROPERTIES_REPORT_REPLY) { // 设备属性上报的响应消息
        payload = payload.concat(buffer_uint8(1)); // 标识属性上报的响应消息
        if (0 == jsonObj.result_code) {
            payload = payload.concat(buffer_uint8(0)); // 标识属性上报消息处理成功
        }
    }
    //返回编码后的二进制数据
    return payload;
}
//将8位无符号整型转换为byte数组
function buffer_uint8(value) {
    var uint8Array = new Uint8Array(1);
    var dataView = new DataView(uint8Array.buffer);
    dataView.setUint8(0, value);
    return [].slice.call(uint8Array);
}
//将16位无符号整型转换为byte数组
function buffer_int16(value) {
    var uint8Array = new Uint8Array(2);
    var dataView = new DataView(uint8Array.buffer);
    dataView.setInt16(0, value);
    return [].slice.call(uint8Array);
}
//将32位无符号整型转换为byte数组
function buffer_int32(value) {
    var uint8Array = new Uint8Array(4);
    var dataView = new DataView(uint8Array.buffer);
    dataView.setInt32(0, value);
    return [].slice.call(uint8Array);
}

JavaScript编解码插件格式要求

数据解码格式定义

数据解析场景,平台收到设备侧的数据时,平台会将设备侧payload中的二进制码流,通过decode方法传到javascript脚本,脚本的decode方法需要实现数据的解码,解码为平台能识别的产品模型中定义的JSON格式,平台对解析后的JSON要求如下:

  • 设备属性上报
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    {
        "msg_type": "properties_report",
        "services": [{
            "service_id": "Battery",
            "properties": {
                "batteryLevel": 57
            },
            "event_time": "20151212T121212Z"
        }]
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    属性上报的消息类型,固定为:properties_report

    services

    必选

    List<ServiceProperty>

    设备服务数据列表(具体结构参考下表ServiceProperty定义表)。

    ServiceProperty结构定义:

    字段名

    必选/可选

    类型

    参数描述

    service_id

    必选

    String

    设备的服务ID。

    properties

    必选

    Object

    设备服务的属性列表,具体字段在设备关联的产品模型中定义。

    event_time

    可选

    String

    设备采集数据UTC时间(格式:yyyyMMddTHHmmssZ),如:20161219T114920Z。

    设备上报数据不带该参数或参数格式错误时,则数据上报时间以平台时间为准。

  • 平台设置设备属性的响应消息
    1
    2
    3
    4
    5
    6
    {
       "msg_type": "properties_set_response",
       "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
       "result_code": 0,
       "result_desc": "success"
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    属性上报的消息类型,固定为:

    properties_set_response

    request_id

    可选

    String

    用于唯一标识这次请求,设备侧收到的消息带该参数时,响应消息需要将该参数值返回给平台。如果解码后的消息不带该字段,则以topic中带的request_id为准。

    result_code

    可选

    Integer

    命令的执行结果,0表示成功,其他表示失败。不带默认认为成功。

    result_desc

    可选

    String

    属性设置的响应描述。

  • 平台查询设备属性的响应消息
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    {
    "msg_type": "properties_get_response",
    "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
        "services": [
            {
                "service_id": "analog",
                "properties": {
                    "PhV_phsA": "1",
                    "PhV_phsB": "2"
                },
                "event_time": "20190606T121212Z"
            }
        ]
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:properties_get_response

    request_id

    可选

    String

    用于唯一标识这次请求,设备侧收到的消息带该参数时,响应消息需要将该参数值返回给平台。如果解码后的消息不带该字段,则以topic中带的request_id为准。

    services

    必选

    List<ServiceProperty>

    设备服务数据列表(具体结构参考下表ServiceProperty定义表)。

    ServiceProperty结构定义:

    字段名

    必选/可选

    类型

    参数描述

    service_id

    必选

    String

    设备的服务ID。

    properties

    必选

    Object

    设备服务的属性列表,具体字段在设备关联的产品模型中定义。

    event_time

    可选

    String

    设备采集数据UTC时间(格式:yyyyMMddTHHmmssZ),如:20161219T114920Z。

    设备上报数据不带该参数或参数格式错误时,则数据上报时间以平台时间为准。

  • 平台命令下发的响应消息
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    {
      "msg_type": "command_response",
      "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
       "result_code": 0,
      "command_name": "ON_OFF",
      "service_id": "WaterMeter",
      "paras": {
        "value": "1"
      }  
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:command_response

    request_id

    可选

    String

    用于唯一标识这次请求,设备侧收到的消息带该参数时,响应消息需要将该参数值返回给平台。如果解码后的消息不带该字段,则以topic中带的request_id为准。

    result_code

    可选

    Integer

    标识命令的执行结果,0表示成功,其他表示失败。不带默认认为成功。

    response_name

    可选

    String

    命令的响应名称,在设备关联的产品模型中定义。

    paras

    可选

    Object

    命令的响应参数,具体字段在设备关联的产品模型中定义。

  • 设备消息上报
    1
    2
    3
    4
    {
      "msg_type": "message_up",
      "content": "hello"
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:message_up

    content

    可选

    String

    消息内容。

数据编码格式定义

数据解析场景,平台指令下发时,平台会将产品模型定义的JSON格式数据,通过encode方法传给javascript脚本,脚本的encode方法需要实现数据的编码将JSON格式的数据,编码为设备可以识别的二进制码流,编码时平台传递到脚本的JSON格式如下:

  • 设备命令下发
    1
    2
    3
    4
    5
    6
    7
    8
    9
    { 
      "msg_type": "commands", 
       "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
      "command_name": "ON_OFF", 
      "service_id": "WaterMeter", 
      "paras": { 
        "value": 1
      } 
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:commands

    request_id

    必选

    String

    用于唯一标识这次请求,该标识会通过topic下发给设备。

    service_id

    可选

    String

    设备的服务ID。

    command_name

    可选

    String

    设备命令名称,在设备关联的产品模型中定义。

    paras

    可选

    Object

    设备命令的执行参数,具体字段在设备关联的产品模型中定义。

  • 平台设置设备属性
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    { 
    "msg_type": "properties_set",
    "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
        "services": [{ 
                "service_id": "Temperature", 
                "properties": { 
                    "value": 57 
                } 
            }, 
            { 
                "service_id": "Battery", 
                "properties": { 
                    "level": 80 
                } 
            } 
        ] 
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:properties_set

    request_id

    必选

    String

    用于唯一标识这次请求,设备侧收到的消息带该参数时,响应消息需要将该参数值返回给平台。

    services

    必选

    List<ServiceProperty>

    设备服务数据列表。

    ServiceProperty结构定义:

    字段名

    必选/可选

    类型

    参数描述

    service_id

    必选

    String

    设备的服务ID。

    properties

    必选

    Object

    设备服务的属性列表,具体字段在产品模型里定义。

  • 平台查询设备属性
    1
    2
    3
    4
    5
    { 
       "msg_type": "properties_get",
       "request_id": "42aa08ea-84c1-4025-a7b2-c1f6efe547c2",
       "service_id": "Temperature" 
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:properties_get

    request_id

    必选

    String

    用于唯一标识这次请求,该标识会通过topic下发给设备。

    service_id

    可选

    String

    设备的服务ID。

  • 属性上报的响应消息(NB-IoT设备接入时属性上报对应的响应)
    1
    2
    3
    4
    5
    { 
      "msg_type": "properties_report_reply",
      "request": "213355656",
      "result_code": 0
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:properties_report_reply

    request

    可选

    String

    属性上报的BASE64编码字符串。

    result_code

    可选

    Integer

    属性上报的执行结果。

    has_more

    可选

    Boolean

    是否存在缓存命令。

  • 设备消息下发
    1
    2
    3
    4
    { 
      "msg_type": "messages",
      "content": "hello"
    }
    

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:messages

    content

    可选

    String

    消息下发的内容。