设备接入 IoTDA设备接入 IoTDA

计算
弹性云服务器 ECS
裸金属服务器 BMS
云手机 CPH
专属主机 DeH
弹性伸缩 AS
镜像服务 IMS
函数工作流 FunctionGraph
云耀云服务器 HECS
VR云渲游平台 CVR
特惠算力专区
存储
对象存储服务 OBS
云硬盘 EVS
云备份 CBR
弹性文件服务 SFS
存储容灾服务 SDRS
云硬盘备份 VBS
云服务器备份 CSBS
数据快递服务 DES
专属企业存储服务
云存储网关 CSG
专属分布式存储服务 DSS
CDN与智能边缘
内容分发网络 CDN
智能边缘云 IEC
智能边缘小站 IES
智能边缘平台 IEF
人工智能
AI开发平台ModelArts
华为HiLens
图引擎服务 GES
图像识别 Image
文字识别 OCR
自然语言处理 NLP
内容审核 Moderation
图像搜索 ImageSearch
医疗智能体 EIHealth
园区智能体 CampusGo
企业级AI应用开发专业套件 ModelArts Pro
人脸识别服务 FRS
对话机器人服务 CBS
视频分析服务 VAS
语音交互服务 SIS
知识图谱 KG
人证核身服务 IVS
IoT物联网
设备接入 IoTDA
设备管理 IoTDM(联通用户专用)
全球SIM联接 GSL
IoT数据分析
路网数字化服务 DRIS
IoT边缘 IoTEdge
设备发放 IoTDP
开发与运维
软件开发平台 DevCloud
项目管理 ProjectMan
代码托管 CodeHub
流水线 CloudPipeline
代码检查 CodeCheck
编译构建 CloudBuild
部署 CloudDeploy
云测 CloudTest
发布 CloudRelease
移动应用测试 MobileAPPTest
CloudIDE
Classroom
开源镜像站 Mirrors
应用魔方 AppCube
云性能测试服务 CPTS
应用管理与运维平台 ServiceStage
云应用引擎 CAE
视频
实时音视频 SparkRTC
视频直播 Live
视频点播 VOD
媒体处理 MPC
视频接入服务 VIS
管理与监管
统一身份认证服务 IAM
消息通知服务 SMN
云监控服务 CES
应用运维管理 AOM
应用性能管理 APM
云日志服务 LTS
云审计服务 CTS
标签管理服务 TMS
资源管理服务 RMS
应用身份管理服务 OneAccess
区块链
区块链服务 BCS
可信跨链服务 TCS
可信分布式身份服务
智能协作
IdeaHub
开发者工具
SDK开发指南
API签名指南
DevStar
HCloud CLI
Terraform
Ansible
云生态
云市场
合作伙伴中心
华为云培训中心
其他
管理控制台
消息中心
产品价格详情
系统权限
我的凭证
客户关联华为云合作伙伴须知
公共问题
宽限期保留期
奖励推广计划
活动
容器
云容器引擎 CCE
云容器实例 CCI
容器镜像服务 SWR
应用编排服务 AOS
多云容器平台 MCP
基因容器 GCS
容器洞察引擎 CIE
云原生服务中心 OSC
容器批量计算 BCE
容器交付流水线 ContainerOps
应用服务网格 ASM
网络
虚拟私有云 VPC
弹性公网IP EIP
弹性负载均衡 ELB
NAT网关 NAT
云专线 DC
虚拟专用网络 VPN
云连接 CC
VPC终端节点 VPCEP
数据库
云数据库 RDS
数据复制服务 DRS
文档数据库服务 DDS
分布式数据库中间件 DDM
云数据库 GaussDB (for openGauss)
云数据库 GaussDB(for MySQL)
云数据库 GaussDB NoSQL
数据管理服务 DAS
数据库和应用迁移 UGO
大数据
MapReduce服务 MRS
数据湖探索 DLI
表格存储服务 CloudTable
可信智能计算服务 TICS
推荐系统 RES
云搜索服务 CSS
数据可视化 DLV
数据湖治理中心 DGC
数据接入服务 DIS
数据仓库服务 GaussDB(DWS)
应用中间件
微服务引擎 CSE
分布式消息服务Kafka版
分布式消息服务RabbitMQ版
API网关 APIG
分布式缓存服务 DCS
分布式消息服务RocketMQ版
企业应用
域名注册服务 Domains
云解析服务 DNS
云速建站 CloudSite
网站备案
商标注册
华为云WeLink
会议
隐私保护通话 PrivateNumber
语音通话 VoiceCall
消息&短信 MSGSMS
云管理网络
SD-WAN 云服务
边缘数据中心管理 EDCM
云桌面 Workspace
应用与数据集成平台 ROMA Connect
ROMA资产中心 ROMAExchange
API全生命周期管理 ROMA API
安全与合规
安全技术与应用
DDoS防护 ADS
Web应用防火墙 WAF
云防火墙 CFW
应用信任中心 ATC
企业主机安全 HSS
容器安全服务 CGS
云堡垒机 CBH
数据库安全服务 DBSS
数据加密服务 DEW
数据安全中心 DSC
云证书管理服务 CCM
SSL证书管理 SCM
漏洞扫描服务 VSS
态势感知 SA
威胁检测服务 MTD
管理检测与响应 MDR
安全治理云图 Compass
认证测试中心 CTC
迁移
主机迁移服务 SMS
对象存储迁移服务 OMS
云数据迁移 CDM
专属云
专属计算集群 DCC
解决方案
高性能计算 HPC
SAP
混合云灾备
华为工业云平台 IMC
价格
成本优化最佳实践
专属云商业逻辑
用户服务
帐号中心
费用中心
成本中心
资源中心
企业管理
工单管理
客户运营能力
国际站常见问题
支持计划
专业服务
合作伙伴支持计划
更新时间:2021-12-24 GMT+08:00
分享

使用JavaScript开发插件

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

  • JavaScript语法规则需要遵循ECMAScript 5.1规范
  • JavaScript脚本大小不能超过1M。
  • 产品部署JavaScript脚本插件后,该产品下所有设备的上下行数据都会进行JavaScript脚本解析。开发者实现JavaScript插件时需要注意实现设备所有的上下行场景。
  • 上行数据JavaScript解码后的JSON数据需要符合平台的格式要求,具体格式要求见: 数据解码格式定义
  • 平台下行指令的JSON格式定义见:数据编码格式定义,使用JavaScript编码时需要根据平台对应的JSON格式转换为对应的二进制码流。

烟感设备样例

场景说明

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

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

产品模型定义

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

编解码插件开发

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

  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格式,并将调试结果显示在输入框中。

      • 检查调试结果是否符合预期,如果不符合预期,则修改代码后重新进行调试。
    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. 部署脚本。确认脚本可以正确进行编解码后,单击“部署”,将该脚本提交到物联网平台,以供数据上下行时,物联网平台调用该脚本进行编解码。

  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

    可选

    byte[]

    属性上报的二进制码流。

    result_code

    可选

    Integer

    属性上报的执行结果。

    has_more

    可选

    Boolean

    是否存在缓存命令。

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

    字段名

    必选/可选

    类型

    参数描述

    msg_type

    必选

    String

    固定为:messages

    content

    可选

    String

    消息下发的内容。

分享:

    相关文档

    相关产品

关闭导读