# 用户指南

说明:本用户指南分为两部分 基础功能高级功能

基础功能:用户开发的网关、设备协议符合当前平台模板的协议格式,此时,用户可以参照平台基础功能说明部分进行网关、设备接入平台。基础功能相对高级功能的网关、设备接入过程,能够简化较多开发步骤。平台模板的协议格式说明如下:

  1. TCP
    1. 网关连接平台时,上报第一个数据为网关编号,必须平台唯一,如网关imei号
    2. 网关连接成功后,进行DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU等设备数据的透传
    3. 网关和平台连接期间,网关可定时上报心跳包到平台以维持正常连接
  2. UDP
    1. 与平台通信时,网关数据格式为:“网关编号”+“@”+“设备数据”的16进制ASCII码数据,如:“383637373235303330333734333935”+“40”+“76030400000064FCDF”
    2. 其中“40”符合前面部分为网关编号的,后面部分为设备数据,设备数据支持以下格式:DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU
  3. MQTT
    1. mqtt网关的clientid作为网关的编号,必须平台唯一
    2. mqtt发送设备数据时,payload内容为DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU格式的数据
  4. COAP
    1. 与平台通信时,uri第一部分作为网关的编号,必须平台唯一,如:“/864388040039566/reportTemperature”
    2. body数据格式:DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU
  5. HTTP
    1. 与平台通信时,uri第一部分作为网关的编号,必须平台唯一,如:“/864388040039566/reportTemperature”
    2. body数据格式:DLT45-2007规约、DLT45-1997规约、ModbusTCP、ModbusRTU

高级功能:用户开发的网关、设备协议不符合当前平台模板的协议格式,使用平台模板无法正常解析时,可使用脚本解析方式进行解析。此时,用户进行网关或设备协议配置时,【模板类型】选项选择【自有模板】,除网关协议或设备协议配置需要编写脚本外,其他配置参照平台基础功能说明部分进行配置即可实现网关、设备接入平台。

# 接入了解

数据包处理流程

原始数据 -> 平台预处理 -> 网关解析 -> 设备解析 -> 解析后处理

# 原始数据

网关或设备通过2G/3G/4G,nb-iot,wifi,有线网络连接到平台传输的数据。

# 平台预处理

从硬件端传输到平台的数据差异性很大,需要平台先对数据做预处理操作,根据不同的通讯协议封装成不同格式。

  1. TCP或UDP通讯协议

说明:

通过TCP或UDP通讯协议传输到平台的数据,平台统一解码成十六进制字符串再封装。

出参格式:

{
  "source_data":"原始数据16进制ASCII码字符串",
  "mduProtocolCode":"协议编号",
  "channel":"连接通道"
}
1
2
3
4
5
  1. MQTT通讯协议

说明:

clientid作为网关编号,payload数据作为原始数据,topic,options存放到options对象中。

出参格式:

{
    "source_data": "payload数据",
    "module_code": "网关编号",
    "options": {
    	"topic": "主题",
    	"option1": "选项1"
    }
}
1
2
3
4
5
6
7
8
  1. Http、Coap通讯协议

说明:

url第一部分作为网关编号,payload数据作为原始数据,options存放到options对象中。

格式:

{
	"source_data": "payload数据",
	"module_code": "网关编号",
	"options": {
		"option1": "选项1"
	}
}
1
2
3
4
5
6
7

# 网关解析

平台预处理后会包装成固定的json格式数据,然后将其交由对应的网关协议进行解析。

  1. 解析类型
    • 平台已有模板解析--通过配置可完成解析,接入方便,只能解析标准协议
    • 自有模板解析--编写脚本进行解析,接入有难度,能适配各种协议
  2. 解析完成后出参
{
	"success": "解析状态",
	"err_msg": "信息",
	"module_code": "网关Code",
	"device_code": "设备Code",
	"packet_code": "包标识",
	"source_data": "原始数据",
	"remain_data": "剩余数据",
	"reply_data": "回复信息的16进制ascii编码",
	"event_time": "完成时间"
}
1
2
3
4
5
6
7
8
9
10
11

# 设备解析

网关协议解析后会包装成固定的json格式数据,然后将其交由对应的设备协议进行解析。

  1. 解析类型
    • 平台已有模板解析--通过配置可完成解析,接入方便,适用于固定的数据格式协议。
    • 自有模板解析--编写脚本进行解析,接入有难度,能适配各种协议
  2. 解析完成后出参(示例)
  • analysis方法
{
	"status": "解析状态",
	"err_msg": "信息",
	"reply_data": "回复信息的16进制ascii编码",
	"device_code": "设备Code",
	"packet_code": "包标识Code",
	"data": {
		"temperature": 30,
		"humidity": 47
	}
}
1
2
3
4
5
6
7
8
9
10
11
  • assembleDownCmd方法
{
	"status": "解析状态",
	"err_msg": "信息",
	"cmd ": "下发命令16进制ascii编码"
}
1
2
3
4
5

# 解析完成后平台处理

通过网关协议和设备协议解析后平台会进一步对数据进行处理,主要是为数据加上一些业务字段,方便进行数据分析,推送和存储。

最终结果:

{
	"status": "解析状态",
	"err_msg": "信息",
	"reply_data": "回复信息",
	"device_id": "设备Id",
	"device_code": "设备Code",
	"packet_code": "包标识Code",
	"data": {
		"temperature": 30,
		"humidity": 47
	}
}
1
2
3
4
5
6
7
8
9
10
11
12

# 基础接入功能

# TCP协议

这个例子只是供用户参考开发,用户需要结合自己设备的特点进行更多扩展开发,并不仅限本例子。

本次模拟设备是modbus水表设备接入网关上报数据

  1. 连接之后上报注册包 (网关编号),如:867725030374398
  2. 定时上报心跳包“心跳包的值”,如:00
  3. 平台定时发送采集数据指令到设备,“采集指令内容”,如modbus协议则发送采集指令为:01 03 02 00 01 79 84
  4. 水表收到采集指令后,上报modbus数据给网关,网关透传水表modbus数据到平台, “水表modubs数据”,如:76030400000064FCDF

# 操作流程

总体流程为:创建网关协议 -> 创建网关 -> 创建设备协议 -> 创建设备 -> 观察设备状态

  1. # 登录物联网平台
  2. # 选择TCP协议标签

  3. # 创建网关协议

    关键参数说明:

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

    关键参数说明:

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

    关键参数说明:

    • 设备协议名称:必填,为设备协议命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位。

    • 协议编号:必填,设备协议的唯一标识。必须平台唯一。支持英文字母、数字和下划线,长度限制4~100

    • 解析方式:必填,网关解析后,得到的设备数据的解析方式

      1. 模板解析

      设备数据格式符合固定字节表示固定属性,

      如:第3到第6个字节共4个字节的长度用来表示温度属性值

      1. 脚本解析

      自行开发设备解析协议脚本去适应设备数据格式

    • 协议说明文档附件:可选

    • 备注:可选

  6. 创建完设备协议之后配置上行功能定义(设备发送给平台端)

    参数说明:

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

    参数说明:

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

    参数说明:

    • code:必填,功能的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100

    • 包名称:必填,为功能命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位

    • 下发类型:必填,功能的控制方式

      1. 下发获取数据

      平台定时执行此项功能,如定时获取水表读数,时间在设备管理中配置

      1. 下发控制命令

      用户手动调用执行此项功能

  9. 点击完成,跳转到添加下行功能属性填写界面,为设备定义功能选项所需的输入参数。点击添加行,为下行功能添加属性,即调用设备功能时所用的输入参数,点击完成保存配置

    参数说明:

    • 名称:必填,为属性命名。支持中文、英文字母、数字和下划线,长度限制4~100

    • 标识:必填,属性的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100

    • 长度:必填,属性的字节数

    • 下行字段类型:必填,属性的类型

      1. 16进制字符串

      填写固定的16进制ASCII码

      1. 地址号

      从设备中截取子设备号

      1. 16进制和

      将前面的参数进行16进制和计算

      1. crc校验和

      将前面的参数进行crc校验和计算

      1. 需要动态传入的参数

      调用功能时传入的动态参数,如设置空调的温度为25度

      1. 字符串

      调用功能时传入的字符串型参数

    • 字段说明:可选

  10. # 创建设备

    参数说明:

    • 名称:必填,设备名称,支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位

    • 设备编号:必填,设备的唯一标识符。平台唯一性。支持英文字母、数字和下划线,长度限制4~100

      建议命名为“网关编号”+“_”+“子设备号(如没有,为01)”

      某些协议如modbus协议,强制命名为:“网关编号”+“_”+“子设备号(即子设备号)”

    • 关联网关:必填,设备所关联的网关

    • 设备协议:必填,解析设备数据所使用的协议

    • 采集频率:可选,平台定时发送指令给设备的cron表达式,cron表达式详见:

      []: http://crontab.org/ "crontab"

      ,不填则不主动采集

    • 设备分类:可选,设备的分类

    • 品牌: 可选,设备的品牌

    • 位置:可选,设备的位置

    • 额外参数:可选

    • 备注:可选

  11. # 查看网关状态

  12. # 查看设备状态

  13. # 查看解析后的数据

  14. # 查看统计图

    可根据时间查询,可自动刷新(5s一次)

# MQTT协议

重要:

  1. 网关的code不能以“system_mqtt_”作为开头

  2. 网关不能订阅以根目录开头的主题,且第一部分必须为租户的id(租户id查看请参考),如:/7cdf9337eb454f2281051176ce9fdf1f/subSmog

说明:这个例子只是供用户参考开发,用户需要结合自己设备的特点进行更多扩展开发,并不仅限本例子。

本次模拟设备是modbus烟雾传感器设备接入网关通过mqtt协议包上报数据。

  1. 网关通过mqtt协议连入平台

连接过程需要,用户名,密码,clientid(对应平台上网关的code,如:864388040039566)

  1. 定时上报心跳包

自行根据mqtt协议实现

  1. 网关订阅接收采集指令的主题

  2. 平台定时推送采集指令到网关订阅的主题

  3. 烟雾传感器收到采集指令后,上报modbus数据给网关,网关通过mqtt协议推送烟雾传感器modbus数据到平台

“烟雾传感器modubs数据”,如:“76030400000064FCDF”

# 操作流程

总体流程为:创建网关协议 -> 创建网关 -> 创建设备协议 -> 创建设备 -> 观察设备状态

  1. # 登录物联网平台
  2. # 选择MQTT协议标签

  1. # 创建网关协议

    关键参数说明:

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

    关键参数说明:

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

    关键参数说明:

    • 设备协议名称:必填,为设备协议命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位。

    • 协议编号:必填,设备协议的唯一标识。必须平台唯一。支持英文字母、数字和下划线,长度限制4~100

    • 解析方式:必填,网关解析后,得到的设备数据的解析方式。

      1. 模板解析

      设备数据格式符合固定字节表示固定属性,

      如:第3到第6个字节共4个字节的长度用来表示温度属性值

      1. 脚本解析

      自行开发设备解析协议脚本去适应设备数据格式

    • 协议说明文档附件:可选

    • 备注:可选

  4. 创建完设备协议之后创建上行功能(设备发送给平台端)

    参数说明:

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

    参数说明:

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

    参数说明:

    • code:必填,功能的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100

    • 功能名称:必填,为功能命名。支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位

    • 下发类型:必填,功能的控制方式。

      1. 下发获取数据

      平台定时执行此项功能,如定时获取水表读数,时间在设备管理中配置

      1. 下发控制命令

      用户手动调用执行此项功能

    • mqtt主题:必填,接收该下发命令的主题。

    • mqtt qos:必填,mqtt服务质量等级。

      • 0表示只发送一次消息。
      • 1表示最少发送一次消息,确保消息到达。
      • 2表示确保消息到达且只会接收一次。
  7. 点击完成,跳转到添加下行功能属性填写界面,为设备定义功能选项所需的输入参数。点击添加行,为下行功能添加属性,即调用设备功能时所用的输入参数,点击完成保存配置

    参数说明:

    • 名称:必填,为属性命名。支持中文、英文字母、数字和下划线,长度限制4~100

    • 标识:必填,属性的唯一标识。在设备协议中唯一。支持英文字母、数字和下划线,长度限制4~100

    • 长度:必填,属性的字节数。

    • 下行字段类型:必填,属性的类型。

      1. 16进制字符串

      填写固定的16进制ASCII码

      1. 地址号

      从设备中截取子设备号

      1. 16进制和

      将前面的参数进行16进制和计算

      1. crc校验和

      将前面的参数进行crc校验和计算

      1. 需要动态传入的参数

      调用功能时传入的动态参数,如设置空调的温度为25度

      1. 字符串

      调用功能时传入的字符串参数

    • 字段说明:可选

  8. # 创建设备

    参数说明:

    • 名称:必填,设备名称,支持中文、英文字母、数字和下划线,长度限制4~100,一个中文汉字算2位

    • 设备编号:必填,设备的唯一标识符。平台唯一性。支持英文字母、数字和下划线,长度限制4~100

      建议命名为“网关编号”+“_”+“子设备号(如没有,为01)”

      某些协议如modbus协议,强制命名为:“网关编号”+“_”+“子设备号(即子设备号)”

    • 关联网关:必填,设备所关联的网关

    • 设备协议:必填,解析设备数据所使用的协议

    • 采集频率:可选,平台定时发送指令给设备的cron表达式,cron表达式详见:

      []: http://crontab.org/ "crontab"

      ,不填则不主动采集

    • 设备分类:可选,设备的分类

    • 品牌: 可选,设备的品牌

    • 位置:可选,设备的位置

    • 额外参数:可选

    • 备注:可选

  9. # 查看接入状态

    包含网关状态,设备状态,解析后的数据,统计图等。详细步骤与TCP协议时的查看状态操作一致

# UDP协议

这个例子只是供用户参考开发,用户需要结合自己设备的特点进行更多扩展开发,并不仅限本例子。

本次模拟设备是modbus水表设备接入网关上报数据

  1. 连接之后上报注册包 (网关编号),如:867725030374398
  2. 网关定时上报设备数据。

# 操作流程

总体流程为:创建网关协议 -> 创建网关 -> 创建设备协议 -> 创建设备 -> 观察设备状态

  1. # 登录物联网平台
  2. # 选择UDP协议标签

  3. # 创建网关协议

    关键参数说明:

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

    详细操作与TCP网关接入相同,可参考TCP网关创建步骤。

  5. # 创建设备协议

    详细操作与TCP设备协议创建相同,可参考TCP设备协议创建步骤。

  6. # 创建设备

    详细操作与TCP设备创建相同,可参考TCP设备创建步骤。

  7. # 查看接入状态

    详细方法及操作与TCP接入后查看状态步骤相同,可参考TCP接入状态查看方法。

# 高级功能

说明:

  1. 高级解析功能指脚本解析接入功能。
  2. 脚本解析相对于模板解析较为复杂。
  3. 脚本解析方式的解析能力更为强大。
  4. 使用脚本解析时,【模板类型】选项选择--自有模板。
  5. 高级解析功能除了编写脚本外,其他配置与基础接入时配置一致。

注意

  1. 高级解析的脚本使用groovy语言进行脚本开发(文件后缀为.groovy)。
  2. 高级解析的脚本约定只能引入alibaba处理json的工具包。

# 网关脚本解析

# 解析流程

原始数据传输到平台进行网关协议解析前,需要根据不同通讯方式将原始数据进行封装为指定格式,详情可参考接入了解章节。

  • 流程图(以tcp通讯方式为例,通讯方式不同入参稍有差别,详情可查看接入了解章节):

  • 网关协议脚本作用:

网关协议脚本作用就是将入参(平台预处理后的数据)转换为出参(解析后返回结果)指定的数据格式。

# 网关解析出入参说明

入参

参数 描述 备注
data 原始数据16进制ASCII码字符串
mduProtocolCode 协议编号
channel 连接通道
options 其他参数列表 以json格式存储多余参数
topic 主题 mqtt通讯方式中特有参数

格式:

{
	"source_data": "payload数据",
	"moduleCode": "网关编号",
	"options": {
		"topic": "主题",
		"option1": "选项1"
	}
}
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": "完成时间"
}
1
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
    }

}
1
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
    }
}

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

# 设备脚本解析

设备解析需要实现两个方法,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": "回复信息"
}
1
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
	}
}
1
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": "字段值"
		}
	]
}
1
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编码"
}
1
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
    }

}
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

# 示例

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()
    }
}
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
Last Updated: 1/18/2022, 9:59:10 AM