# 用户指南
说明:本用户指南分为两部分 基础功能和高级功能
基础功能:用户开发的网关、设备协议符合当前平台模板的协议格式,此时,用户可以参照平台基础功能说明部分进行网关、设备接入平台。基础功能相对高级功能的网关、设备接入过程,能够简化较多开发步骤。平台模板的协议格式说明如下:
- TCP
- 网关连接平台时,上报第一个数据为网关编号,必须平台唯一,如网关imei号
- 网关连接成功后,进行DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU等设备数据的透传
- 网关和平台连接期间,网关可定时上报心跳包到平台以维持正常连接
- UDP
- 与平台通信时,网关数据格式为:“网关编号”+“@”+“设备数据”的16进制ASCII码数据,如:“383637373235303330333734333935”+“40”+“76030400000064FCDF”
- 其中“40”符合前面部分为网关编号的,后面部分为设备数据,设备数据支持以下格式:DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU
- MQTT
- mqtt网关的clientid作为网关的编号,必须平台唯一
- mqtt发送设备数据时,payload内容为DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU格式的数据
- COAP
- 与平台通信时,uri第一部分作为网关的编号,必须平台唯一,如:“/864388040039566/reportTemperature”
- body数据格式:DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU
- HTTP
- 与平台通信时,uri第一部分作为网关的编号,必须平台唯一,如:“/864388040039566/reportTemperature”
- body数据格式:DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU
高级功能:用户开发的网关、设备协议不符合当前平台模板的协议格式,使用平台模板无法正常解析时,可使用脚本解析方式进行解析。此时,用户进行网关或设备协议配置时,【模板类型】选项选择【自有模板】,除网关协议或设备协议配置需要编写脚本外,其他配置参照平台基础功能说明部分进行配置即可实现网关、设备接入平台。
# 接入了解
数据包处理流程
原始数据 -> 平台预处理 -> 网关解析 -> 设备解析 -> 解析后处理
# 原始数据
网关或设备通过2G/3G/4G,nb-iot,wifi,有线网络连接到平台传输的数据。
# 平台预处理
从硬件端传输到平台的数据差异性很大,需要平台先对数据做预处理操作,根据不同的通讯协议封装成不同格式。
- TCP或UDP通讯协议
说明:
通过TCP或UDP通讯协议传输到平台的数据,平台统一解码成十六进制字符串再封装。
出参格式:
{
"source_data":"原始数据16进制ASCII码字符串",
"mduProtocolCode":"协议编号",
"channel":"连接通道"
}
2
3
4
5
- MQTT通讯协议
说明:
clientid作为网关编号,payload数据作为原始数据,topic,options存放到options对象中。
出参格式:
{
"source_data": "payload数据",
"module_code": "网关编号",
"options": {
"topic": "主题",
"option1": "选项1"
}
}
2
3
4
5
6
7
8
- Http、Coap通讯协议
说明:
url第一部分作为网关编号,payload数据作为原始数据,options存放到options对象中。
格式:
{
"source_data": "payload数据",
"module_code": "网关编号",
"options": {
"option1": "选项1"
}
}
2
3
4
5
6
7
# 网关解析
平台预处理后会包装成固定的json格式数据,然后将其交由对应的网关协议进行解析。
- 解析类型
- 平台已有模板解析--通过配置可完成解析,接入方便,只能解析标准协议
- 自有模板解析--编写脚本进行解析,接入有难度,能适配各种协议
- 解析完成后出参
{
"success": "解析状态",
"err_msg": "信息",
"module_code": "网关Code",
"device_code": "设备Code",
"packet_code": "包标识",
"source_data": "原始数据",
"remain_data": "剩余数据",
"reply_data": "回复信息的16进制ascii编码",
"event_time": "完成时间"
}
2
3
4
5
6
7
8
9
10
11
# 设备解析
网关协议解析后会包装成固定的json格式数据,然后将其交由对应的设备协议进行解析。
- 解析类型
- 平台已有模板解析--通过配置可完成解析,接入方便,适用于固定的数据格式协议。
- 自有模板解析--编写脚本进行解析,接入有难度,能适配各种协议
- 解析完成后出参(示例)
- analysis方法
{
"status": "解析状态",
"err_msg": "信息",
"reply_data": "回复信息的16进制ascii编码",
"device_code": "设备Code",
"packet_code": "包标识Code",
"data": {
"temperature": 30,
"humidity": 47
}
}
2
3
4
5
6
7
8
9
10
11
- assembleDownCmd方法
{
"status": "解析状态",
"err_msg": "信息",
"cmd ": "下发命令16进制ascii编码"
}
2
3
4
5
# 解析完成后平台处理
通过网关协议和设备协议解析后平台会进一步对数据进行处理,主要是为数据加上一些业务字段,方便进行数据分析,推送和存储。
最终结果:
{
"status": "解析状态",
"err_msg": "信息",
"reply_data": "回复信息",
"device_id": "设备Id",
"device_code": "设备Code",
"packet_code": "包标识Code",
"data": {
"temperature": 30,
"humidity": 47
}
}
2
3
4
5
6
7
8
9
10
11
12
# 基础接入功能
# TCP协议
这个例子只是供用户参考开发,用户需要结合自己设备的特点进行更多扩展开发,并不仅限本例子。
本次模拟设备是modbus水表设备接入网关上报数据
- 连接之后上报注册包 (网关编号),如:
867725030374398 - 定时上报心跳包“心跳包的值”,如:
00 - 平台定时发送采集数据指令到设备,“采集指令内容”,如modbus协议则发送采集指令为:
01 03 02 00 01 79 84 - 水表收到采集指令后,上报modbus数据给网关,网关透传水表modbus数据到平台, “水表modubs数据”,如:
76030400000064FCDF
# 操作流程
总体流程为:创建网关协议 -> 创建网关 -> 创建设备协议 -> 创建设备 -> 观察设备状态
# 登录物联网平台
# 选择TCP协议标签

# 创建网关协议

关键参数说明:
- 网关协议名称:为网关协议命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
- 协议编号:网关协议的唯一标识符。在系统中具有唯一性,添加时若协议编号已被使用,会添加失败。支持英文字母、数字和下划线,长度限制4-100
- 模板类型:解析网关数据时所用的解析类型
- 平台已有模板:需要网关通讯数据格式符合所选模板,默认选择此项,当选此项时需要网关连接平台之后,第一个数据发送一个唯一标识符,作为网关编号,之后可以发送设备数据和心跳包
- 自有模板:自行开发网关解析协议脚本去适应网关通讯数据格式
- 心跳包的值:选择平台已有模板时,网关和平台保持连接时需要定时上报的数据,数据为16进制字符串
- 协议解析模板:平台的网关通讯数据格式支持以下4种:
- DLT45-2007规约
- DLT45-1997规约
- ModbusTCP
- ModbusRTU
- 通信端口:平台为本协议开放的端口。在系统中具有唯一性,范围在5000-50000内的没有被占用的端口, 只有通信类型为tcp、udp时需要填写
# 创建网关

关键参数说明:
- 名称:必填,填写网关名称
- 网关编号:必填,填写网关编号,系统唯一,一般使用IMEI,此编号作为网关注册的标识
- 网关协议:必填,选择网关协议
- 离线检测时间间隔:必填,用于定时检测网关在线状态(要求离线检测时间间隔在 10 - 129,600 分钟之内)
- 品牌:可选,此网关的品牌
- 型号:可选,此网关的型号
- 北向联网方式:可选,网关往平台发送数据连接方式
- 南向联网方式:可选,网关连接传感器使用方式
- 操作系统:可选,网关的操作系统
- 加密类型:可选,网关的加密类型
- SIM卡ICCID:可选,输入网关内SIM卡ICCID,以获取SIM卡使用状态
- 备注:可选
# 创建设备协议

关键参数说明:
设备协议名称:必填,为设备协议命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位。
协议编号:必填,设备协议的唯一标识。必须平台唯一。支持英文字母、数字和下划线,长度限制4~100
解析方式:必填,网关解析后,得到的设备数据的解析方式
- 模板解析
设备数据格式符合固定字节表示固定属性,
如:第3到第6个字节共4个字节的长度用来表示温度属性值
- 脚本解析
自行开发设备解析协议脚本去适应设备数据格式
协议说明文档附件:可选
备注:可选
创建完设备协议之后配置上行功能定义(设备发送给平台端)

参数说明:
- 上行功能定义code:设备数据类型标识,在设备协议中唯一。modubus格式数据取功能码作为标识符,为03。其它格式数据需要自行找出能够标识某次数据上报的数据类型。支持英文字母、数字和下划线,长度限制4~100
- 功能名称:为设备数据类型命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
点击确定,跳转到添加上行功能属性填写界面,点击添加行,为上行功能添加属性

参数说明:
- 名称:必填,为属性命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
- 标识:必填,属性的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100
- 数据类型:必填,属性的数据类型
- 单位:属性的单位
- 公式:解析属性时所用到的js公式,如采集的数据除以100,那么可以这样写:{标识} / 100
- 长度:属性占位的字节数
- 是否存储:属性是否需要存储到数据库
点击保存,配置下行功能(平台发送数据给设备端)

参数说明:
code:必填,功能的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100
包名称:必填,为功能命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
下发类型:必填,功能的控制方式
- 下发获取数据
平台定时执行此项功能,如定时获取水表读数,时间在设备管理中配置
- 下发控制命令
用户手动调用执行此项功能
点击完成,跳转到添加下行功能属性填写界面,为设备定义功能选项所需的输入参数。点击添加行,为下行功能添加属性,即调用设备功能时所用的输入参数,点击
完成保存配置
参数说明:
名称:必填,为属性命名。支持中文、英文字母、数字和下划线,长度限制4~100
标识:必填,属性的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100
长度:必填,属性的字节数
下行字段类型:必填,属性的类型
- 16进制字符串
填写固定的16进制ASCII码
- 地址号
从设备中截取子设备号
- 16进制和
将前面的参数进行16进制和计算
- crc校验和
将前面的参数进行crc校验和计算
- 需要动态传入的参数
调用功能时传入的动态参数,如设置空调的温度为25度
- 字符串
调用功能时传入的字符串型参数
字段说明:可选
# 创建设备

参数说明:
名称:必填,设备名称,支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
设备编号:必填,设备的唯一标识符。平台唯一性。支持英文字母、数字和下划线,长度限制4~100
建议命名为“网关编号”+“_”+“子设备号(如没有,为01)”
某些协议如modbus协议,强制命名为:“网关编号”+“_”+“子设备号(即子设备号)”
关联网关:必填,设备所关联的网关
设备协议:必填,解析设备数据所使用的协议
采集频率:可选,平台定时发送指令给设备的cron表达式,cron表达式详见:
[]: http://crontab.org/ "crontab"
,不填则不主动采集
设备分类:可选,设备的分类
品牌: 可选,设备的品牌
位置:可选,设备的位置
额外参数:可选
备注:可选
# 查看网关状态

# 查看设备状态

# 查看解析后的数据

# 查看统计图

可根据时间查询,可自动刷新(5s一次)
# MQTT协议
重要:
网关的code不能以“system_mqtt_”作为开头
网关不能订阅以根目录开头的主题,且第一部分必须为租户的id(租户id查看请参考),如:/7cdf9337eb454f2281051176ce9fdf1f/subSmog
说明:这个例子只是供用户参考开发,用户需要结合自己设备的特点进行更多扩展开发,并不仅限本例子。
本次模拟设备是modbus烟雾传感器设备接入网关通过mqtt协议包上报数据。
- 网关通过mqtt协议连入平台
连接过程需要,用户名,密码,clientid(对应平台上网关的code,如:864388040039566)
- 定时上报心跳包
自行根据mqtt协议实现
网关订阅接收采集指令的主题
平台定时推送采集指令到网关订阅的主题
烟雾传感器收到采集指令后,上报modbus数据给网关,网关通过mqtt协议推送烟雾传感器modbus数据到平台
“烟雾传感器modubs数据”,如:“76030400000064FCDF”
# 操作流程
总体流程为:创建网关协议 -> 创建网关 -> 创建设备协议 -> 创建设备 -> 观察设备状态

# 创建网关协议

关键参数说明:
- 网关协议名称:为网关协议命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
- 协议编号:网关协议的唯一标识符。在系统中具有唯一性,添加时若协议编号已被使用,会添加失败。支持英文字母、数字和下划线,长度限制4-100
- 模板类型:解析网关数据时所用的解析类型
- 平台已有模板:需要网关通讯数据格式符合所选模板,默认选择此项,当选此项时需要网关连接平台之后,第一个数据发送一个唯一标识符,作为网关编号,之后可以发送设备数据和心跳包
- 自有模板:自行开发网关解析协议脚本去适应网关通讯数据格式
- 协议解析模板:平台的网关通讯数据格式支持以下4种:
- DLT45-2007规约
- DLT45-1997规约
- ModbusTCP
- ModbusRTU
- 协议说明文档附件:可选
- 协议使用说明:可选
# 创建网关

关键参数说明:
- 用户名:必填,主题订阅账号
- 密码:必填,主题订阅账号的密码
- 名称:必填,填写网关名称
- 网关编号:必填,填写网关编号,系统唯一,不能以“system_mqtt_”作为开头,一般使用IMEI,此编号作为网关注册的标识
- 网关协议:必填,选择网关协议
- 品牌:可选,此网关的品牌
- 型号:可选,此网关的型号
- 北向联网方式:可选,网关往平台发送数据连接方式
- 南向联网方式:可选,网关连接传感器使用方式
- 操作系统:可选,网关的操作系统
- 加密类型:可选,网关的加密类型
- SIM卡ICCID:可选,输入网关内SIM卡ICCID,以获取SIM卡使用状态
- 备注:可选
# 创建设备协议

关键参数说明:
设备协议名称:必填,为设备协议命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位。
协议编号:必填,设备协议的唯一标识。必须平台唯一。支持英文字母、数字和下划线,长度限制4~100
解析方式:必填,网关解析后,得到的设备数据的解析方式。
- 模板解析
设备数据格式符合固定字节表示固定属性,
如:第3到第6个字节共4个字节的长度用来表示温度属性值
- 脚本解析
自行开发设备解析协议脚本去适应设备数据格式
协议说明文档附件:可选
备注:可选
创建完设备协议之后创建上行功能(设备发送给平台端)

参数说明:
- 上行功能code:设备数据类型标识,在设备协议中唯一。modubus格式数据取功能码作为标识符,为03。其它格式数据需要自行找出能够标识某次数据上报的数据类型。支持英文字母、数字和下划线,长度限制4~100
- 功能名称:为设备数据类型命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
点击确定,跳转到添加上行功能属性填写界面,点击添加行,为上行功能添加属性

参数说明:
- 名称:必填,为属性命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
- 标识:必填,属性的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100
- 数据类型:必填,属性的数据类型
- 单位:属性的单位
- 公式:解析属性时所用到的计算公式,如采集的数据除以100,那么可以这样写:{标识} / 100
- 长度:属性占位的字节数
- 是否存储:属性是否需要存储到数据库
点击保存,配置下行功能(平台发送数据给设备端)

参数说明:
code:必填,功能的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100
功能名称:必填,为功能命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
下发类型:必填,功能的控制方式。
- 下发获取数据
平台定时执行此项功能,如定时获取水表读数,时间在设备管理中配置
- 下发控制命令
用户手动调用执行此项功能
mqtt主题:必填,接收该下发命令的主题。
mqtt qos:必填,mqtt服务质量等级。
- 0表示只发送一次消息。
- 1表示最少发送一次消息,确保消息到达。
- 2表示确保消息到达且只会接收一次。
点击完成,跳转到添加下行功能属性填写界面,为设备定义功能选项所需的输入参数。点击添加行,为下行功能添加属性,即调用设备功能时所用的输入参数,点击
完成保存配置
参数说明:
名称:必填,为属性命名。支持中文、英文字母、数字和下划线,长度限制4~100
标识:必填,属性的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100
长度:必填,属性的字节数。
下行字段类型:必填,属性的类型。
- 16进制字符串
填写固定的16进制ASCII码
- 地址号
从设备中截取子设备号
- 16进制和
将前面的参数进行16进制和计算
- crc校验和
将前面的参数进行crc校验和计算
- 需要动态传入的参数
调用功能时传入的动态参数,如设置空调的温度为25度
- 字符串
调用功能时传入的字符串参数
字段说明:可选
# 创建设备

参数说明:
名称:必填,设备名称,支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
设备编号:必填,设备的唯一标识符。平台唯一性。支持英文字母、数字和下划线,长度限制4~100
建议命名为“网关编号”+“_”+“子设备号(如没有,为01)”
某些协议如modbus协议,强制命名为:“网关编号”+“_”+“子设备号(即子设备号)”
关联网关:必填,设备所关联的网关
设备协议:必填,解析设备数据所使用的协议
采集频率:可选,平台定时发送指令给设备的cron表达式,cron表达式详见:
[]: http://crontab.org/ "crontab"
,不填则不主动采集
设备分类:可选,设备的分类
品牌: 可选,设备的品牌
位置:可选,设备的位置
额外参数:可选
备注:可选
# 查看接入状态
包含网关状态,设备状态,解析后的数据,统计图等。详细步骤与TCP协议时的查看状态操作一致
# UDP协议
这个例子只是供用户参考开发,用户需要结合自己设备的特点进行更多扩展开发,并不仅限本例子。
本次模拟设备是modbus水表设备接入网关上报数据
- 连接之后上报注册包 (网关编号),如:
867725030374398 - 网关定时上报设备数据。
# 操作流程
总体流程为:创建网关协议 -> 创建网关 -> 创建设备协议 -> 创建设备 -> 观察设备状态
# 登录物联网平台
# 选择UDP协议标签

# 创建网关协议

关键参数说明:
- 网关协议名称:为网关协议命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位
- 协议编号:网关协议的唯一标识符。在系统中具有唯一性,添加时若协议编号已被使用,会添加失败。支持英文字母、数字和下划线,长度限制4-100
- 模板类型:解析网关数据时所用的解析类型。
- 平台已有模板:需要网关通讯数据格式符合所选模板,默认选择此项,当选此项时需要网关连接平台之后,第一个数据发送一个唯一标识符,作为网关编号,之后可以发送设备数据和心跳包。
- 自有模板:自行开发网关解析协议脚本去适应网关通讯数据格式
- 协议解析模板:平台的网关通讯数据格式支持以下4种:
- DLT45-2007规约
- DLT45-1997规约
- ModbusTCP
- ModbusRTU
- 通信端口:平台为本协议开放的端口。在系统中具有唯一性,范围在5000-50000内的没有被占用的端口, 只有通信类型为tcp、udp时需要填写
- 协议说明文档附件:可选
- 协议使用说明:可选
# 创建网关
详细操作与TCP网关接入相同,可参考TCP网关创建步骤。
# 创建设备协议
详细操作与TCP设备协议创建相同,可参考TCP设备协议创建步骤。
# 创建设备
详细操作与TCP设备创建相同,可参考TCP设备创建步骤。
# 查看接入状态
详细方法及操作与TCP接入后查看状态步骤相同,可参考TCP接入状态查看方法。
# 高级功能
说明:
- 高级解析功能指脚本解析接入功能。
- 脚本解析相对于模板解析较为复杂。
- 脚本解析方式的解析能力更为强大。
- 使用脚本解析时,【模板类型】选项选择--自有模板。
- 高级解析功能除了编写脚本外,其他配置与基础接入时配置一致。
注意
- 高级解析的脚本使用groovy语言进行脚本开发(文件后缀为.groovy)。
- 高级解析的脚本约定只能引入alibaba处理json的工具包。
# 网关脚本解析
# 解析流程
原始数据传输到平台进行网关协议解析前,需要根据不同通讯方式将原始数据进行封装为指定格式,详情可参考接入了解章节。
- 流程图(以tcp通讯方式为例,通讯方式不同入参稍有差别,详情可查看接入了解章节):

- 网关协议脚本作用:
网关协议脚本作用就是将入参(平台预处理后的数据)转换为出参(解析后返回结果)指定的数据格式。
# 网关解析出入参说明
入参
| 参数 | 描述 | 备注 |
|---|---|---|
| data | 原始数据16进制ASCII码字符串 | 无 |
| mduProtocolCode | 协议编号 | 无 |
| channel | 连接通道 | 无 |
| options | 其他参数列表 | 以json格式存储多余参数 |
| topic | 主题 | mqtt通讯方式中特有参数 |
格式:
{
"source_data": "payload数据",
"moduleCode": "网关编号",
"options": {
"topic": "主题",
"option1": "选项1"
}
}
2
3
4
5
6
7
8
出参
| 参数 | 描述 |
|---|---|
| success | 解析状态,bool类型,true或false |
| err_msg | 解析返回说明,若数据有误,填写错误原因。 |
| module_code | 网关编号。 |
| device_code | 设备编号。 |
| packet_code | 上行数据分类标识。 |
| source_data | 原始数据。 |
| remain_data | 剩余数据,如解析了原始数据之后,对于已经无需使用的数据,舍弃掉,只留下尚未解析的设备数据。 |
| reply_data | 回复给客户端的信息的16进制ascii编码。 |
| event_time | 网关解析完成时间,设置系统当前即可 |
格式:
{
"success": "解析状态",
"err_msg": "信息",
"module_code": "网关Code",
"device_code": "设备Code",
"packet_code": "包标识",
"source_data": "原始数据",
"remain_data": "剩余数据",
"reply_data": "回复信息",
"event_time": "完成时间"
}
2
3
4
5
6
7
8
9
10
11
# 网关解析脚本模板
解析脚本约定只能引入alibaba处理json工具包,引入其他包将导致审核不通过
import com.alibaba.fastjson.JSONObject
/**
* sourceJsonInfo 入参
* mJson 出参
*/
class TemplateProtocolAnalysisScript2 {
JSONObject analysis(JSONObject sourceJsonInfo) {
//封装解析返回的结果
JSONObject mJson = new JSONObject()
mJson.put("status", true)
mJson.put("err_msg", "")
mJson.put("module_code", "")
mJson.put("device_code", "")
mJson.put("packet_code", "")
mJson.put("source_data", "")
mJson.put("remain_data", "")
mJson.put("reply_data", "")
mJson.put("event_time", new Date().getTime())
return mJson
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 示例
url参数解析协议为例
入参
module_code=867725030374398&method=report&on_off=on&temperature=25&humidity=67
import com.alibaba.fastjson.JSONObject
/**
* url参数解析协议
*入参:module_code=867725030374398&method=report&on_off=on&temperature=25&humidity=67
*/
class TcpUrlParamProtocolAnalysisScript {
JSONObject analysis(JSONObject sourceJsonInfo) {
//原始数据的16进制ascii码
String sourceHexStr = sourceJsonInfo.getString("source_data")
//转换为字符串类型
String urlParam = hexStringToString(sourceHexStr)
//转换为json格式数据
JSONObject paramJson = urlParam2JSONObject(urlParam, "&", "=")
//获取网关编号
String moduleCode = paramJson.getString("module_code")
//定义设备编号为:网关编号+“_01”组成
String deviceCode = moduleCode + "_01"
//获取数据包的编号
String packetCode = paramJson.getString("method")
//封装解析返回的结果
JSONObject mJson = new JSONObject()
mJson.put("status", true)
mJson.put("err_msg", "")
mJson.put("module_code", moduleCode)
mJson.put("device_code", deviceCode)
mJson.put("packet_code", packetCode)
mJson.put("source_data", sourceHexStr)
paramJson.remove("module_code")
paramJson.remove("method")
mJson.put("remain_data", paramJson.toJSONString())
mJson.put("reply_data", "")
mJson.put("event_time", new Date().getTime())
return mJson
}
/**
* 将字符串转成JSONObject
* @param mapString 待分割字符串
* @param split 第一分隔符
* @param subSplit 子分隔符
*/
private JSONObject urlParam2JSONObject(String urlParam, String split, String subSplit) {
String[] splitData = urlParam.split(split)
JSONObject jsonObject = new JSONObject()
for (int i = 0; i < splitData.length; i++) {
String[] subSplitData = splitData[i].split(subSplit)
jsonObject.put(subSplitData[0], subSplitData[1])
}
return jsonObject
}
/**
* 16进制转换成为string类型字符串
* @param s
* @return
*/
private String hexStringToString(String s) {
if (s == null || s.equals("")) {
return null
}
s = s.replace(" ", "")
byte[] baKeyword = new byte[s.length() / 2]
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16))
} catch (Exception e) {
e.printStackTrace();
}
}
try {
s = new String(baKeyword, "UTF-8")
new String()
} catch (Exception e1) {
e1.printStackTrace()
}
return s
}
}
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
# 设备脚本解析
设备解析需要实现两个方法,analysis方法和assembleDownCmd方法(方法名需要一致)。
analysis方法用来解析设备数据(有上报数据的使用该函数)。
assembleDownCmd方法用来组装下发命令(有下发命令使用该函数)。
设备协议脚本可以包含上两个方法中任意一个,也可以包含多个。
# 解析流程
原始数据经过平台处理和网关解析后,会被封装成固定格式(网关解析的出参格式)进行设备协议解析,经过设备解析后,数据将再次被封装成特定的json格式(设备解析出参格式)。
- 流程图:

# 设备解析出入参说明
- analysis方法:
入参
| 参数 | 描述 |
|---|---|
| module_code | 网关编号。 |
| device_code | 设备编号。 |
| packet_code | 上行数据分类标识。 |
| source_data | 上报数据的16进制ascii编码。 |
| remain_data | 网关解析后剩余的数据。 |
| reply_data | 回复信息。 |
格式:
{
"module_code": "网关Code",
"device_code": "设备Code",
"packet_code": "包标识",
"source_data": "原始数据",
"remain_data": "剩余数据",
"reply_data": "回复信息"
}
2
3
4
5
6
7
8
出参
| 参数 | 描述 |
|---|---|
| status | 解析状态,bool类型,true或false |
| err_msg | 解析返回说明,若数据有误,填写错误原因。 |
| reply_data | 回复消息的16进制ascii编码。 |
| device_code | 设备编号。 |
| packet_code | 包标识Code。 |
| data | 设备解析后的数据列表,json格式存储设备各指标数值。 |
格式:
{
"status": "解析状态",
"err_msg": "信息",
"reply_data": "回复信息",
"device_code": "设备Code",
"packet_code": "包标识Code",
"data": {
"xxx1": 30,
"xxx2": 47
}
}
2
3
4
5
6
7
8
9
10
11
- assembleDownCmd方法:
入参
| 参数 | 描述 |
|---|---|
| module_code | 网关编号。 |
| device_code | 设备编号。 |
| packet_code | 下行数据分类标识。 |
| fields | 下行数据的属性数组。 |
| field_code | 属性标识。 |
| field_value | 属性的值 |
格式:
{
"module_code": "网关Code",
"device_code": "设备Code",
"packet_code": "服务code",
"fields": [
{
"field_code": "字段code",
"field_value": "字段值"
}
]
}
2
3
4
5
6
7
8
9
10
11
出参
| 参数 | 描述 |
|---|---|
| success | 解析状态,bool类型,true或false |
| err_msg | 解析返回说明,若数据有误,填写错误原因。 |
| cmd | 下发命令16进制ascii编码。 |
格式:
{
"status": "解析状态",
"err_msg": "信息",
"cmd ": "下发命令16进制ascii编码"
}
2
3
4
5
# 设备解析脚本模板
解析脚本约定只能引入alibaba处理json工具包,引入其他包将导致审核不通过
import com.alibaba.fastjson.JSONObject
/**
* 设备协议模板
*/
class TemplateAnalysisScript {
/**
* 数据解析方法
* @param mAnalysisJson
* @return
*/
JSONObject analysis(JSONObject mAnalysisJson) {
JSONObject dAnalysisJson = new JSONObject()
dAnalysisJson.put("status", true)
dAnalysisJson.put("err_msg", "")
dAnalysisJson.put("device_code", "")
dAnalysisJson.put("packet_code", "")
dAnalysisJson.put("reply_data", "")
dAnalysisJson.put("event_time", new Date().getTime())
JSONObject dataJson = new JSONObject()
dAnalysisJson.put("data", dataJson)
return dAnalysisJson
}
/**
* 组装命令方法
* @param servicesJsonInfo
* @return
*/
JSONObject assembleDownCmd(JSONObject servicesJsonInfo) {
JSONObject resultJson = new JSONObject()
resultJson.put("status", true)
resultJson.put("err_msg", "")
resultJson.put("cmd", "")
return resultJson
}
}
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
# 示例
url参数解析协议为例
入参
module_code=867725030374398&method=report&on_off=on&temperature=25&humidity=67
import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
/**
* 沅朋温湿度开关设备协议
*/
class YpkjTHAnalysisScript {
//数据解析方法
JSONObject analysis(JSONObject mAnalysisJson) {
String remainDataStr = mAnalysisJson.getString("remain_data")
JSONObject dAnalysisJson = new JSONObject()
dAnalysisJson.put("status", true)
dAnalysisJson.put("err_msg", "")
dAnalysisJson.put("device_code", mAnalysisJson.getString("device_code"))
dAnalysisJson.put("packet_code", mAnalysisJson.getString("packet_code"))
dAnalysisJson.put("reply_data", "")
dAnalysisJson.put("event_time", new Date().getTime())
JSONObject dataJson = JSONObject.parseObject(remainDataStr)
dAnalysisJson.put("data", dataJson)
return dAnalysisJson
}
/**
* 组装命令方法
* 构建为
*{* "success": "解析状态",
* "err_msg": "信息",
* "cmd": "module_code=867725030374398&method=set_switch &on_off=off"
*}* @param servicesJsonInfo
* @return
*/
JSONObject assembleDownCmd(JSONObject servicesJsonInfo) {
String moduleCode = servicesJsonInfo.getString("module_code")
String deviceCode = servicesJsonInfo.getString("device_code")
String subCode = deviceCode.substring(deviceCode.lastIndexOf("_") + 1)
String packetCode = servicesJsonInfo.getString("packet_code")
if (packetCode.equals("set_switch")) {
JSONObject resultJson = new JSONObject()
resultJson.put("status", true)
resultJson.put("err_msg", "")
JSONArray fields = servicesJsonInfo.getJSONArray("fields")
String cmd = "module_code=" + moduleCode + "&method=" + servicesJsonInfo.getString("packet_code")
for (int j = 0; j < fields.size(); j++) {
JSONObject filedJson = fields.getJSONObject(j)
cmd = cmd + "&" + filedJson.getString("field_code") + "=" + filedJson.getString("field_value")
}
resultJson.put("cmd", string2HexString(cmd))
return resultJson
}
}
/**
* 转化十六进制编码为字符串
* @param sourceStr
* @return
*/
String string2HexString(String sourceStr) {
String hexString = "0123456789ABCDEF"
//根据默认编码获取字节数组
byte[] bytes = sourceStr.getBytes()
StringBuilder sb = new StringBuilder(bytes.length * 2)
//将字节数组中每个字节拆解成2位16进制整数
for (int i = 0; i < bytes.length; i++) {
sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4))
sb.append(hexString.charAt((bytes[i] & 0x0f)))
}
return sb.toString()
}
}
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