本文讲解4.4版jxTMS中的自定义协议包,整个系列的文章请查看:[docker版jxTMS使用指南:docker版jxTMS使用指南:4.4版升级内容
docker版本的使用,请查看:docker版jxTMS使用指南
4.0版jxTMS的说明,请查看:4.0版升级内容
4.2版jxTMS的说明,请查看:4.2版升级内容
笔者用rt-thread基于GD32开发了一个现场的多串口数据采集器,采集器采用了MQQT+自定义协议包的方式来回传数据。
自定义协议包包括包头和包身两部分。
包头
包头共三个字、12个字节,其结构为:
0-3:4个字节的识别冠字,jxTMS支持冠字自定义,即定义自己的识别冠字加以注册即可
4:包类型,包括数据包、状态报告包、命令包、事件包等
5-7:保留
8:协议版本,目前固定为1
9:CRC,包身逐字节异或
10-11:包身按字节计数的总长
包身
包身全部都是数据,但其也是有结构的。一个包对应一个数据集,一个数据集相当于或说可以映射为python中的一个dict。
数据集由多个数据单元组成,而一个数据单元就是一个【key-value】对。所有数据都按TLV【Type-Length-Value】进行打包,类型一个字节、长度一个字节,整数4个字节、浮点数4个字节,字符串目前都按ascii编码。
所以包身的打包是:
12:数据集类型【64】
13:数据单元数
14:数据集名的TLV
然后是每个数据单元的打包:
offset:数据单元类型【65】
offset+1:数据单元中key的TLV
offset+1+2+len(key):数据单元中value的TLV
约束
自定义协议包存在几个约束:
-
识别冠字必须先注册,否则无法识别
-
版本必须为1
-
包身总长必须和解包后得到的数据总长相等
-
CRC应是包身所有字节的异或
解包时要根据13处所指定的数据单元数,来确定应解的数据单元数量,解完此数量的数据单元后的偏移值再减去包头的12个字节,就是数据总长。
这些约束加上包身中有太多指示数据长的L值,而且这些L值的位置还不是固定的,所以通信过程中的偶发性错误配合CRC基本都会被识别出来。
引用:
from jx.packet import packet
类函数
register(self, type,newPacketFunc)
注册一个自定义协议包的识别冠字
参数:
type:四个字符的识别冠字,一般是组织的大写缩写
newPacketFunc:返回一个新的包,无参
返回值:
无
说明:
识别冠字应先注册,否则无法正确解包
对象函数
init(self, type)
声明一个自定义协议包
参数:
type:就是识别冠字,一般是四个大写字母
返回值:
无
说明:
识别冠字应先注册,否则无法正确解包
crc_check(self, ba, dataLen)
返回crc校验结果
参数:
ba:正在解包的字节数组
dataLen:正在解包的字节数组的数据总长
返回值:
True:校验成功
False:校验失败
说明:
如果发送方没有执行CRC,则重载本函数并返回True
packetType(self, pt=None)
设置或返回包类型
参数:
pt:包类型
None:返回该包的包类型
不是None:则将该包的包类型设置为pt
返回值:
如果pt是None,则返回该包的包类型
说明:
包类型在packet中定义,需要时可直接引用:
from jx.packet import PacketType_data,PacketType_report,PacketType_cmd,PacketType_event
name(self, name=None)
设置或返回包名
参数:
name:包名
None:返回该包的包名
不是None:则将该包的名字设置为name
返回值:
如果pt是None,则返回该包的包名
说明:
包名是数据集的名字,包可以是一个站点的所有数据,这时包名就是站点名;也可以是某个设备的数据,则包名就是设备名。具体如何,看通信双方的约定
ts(self)
包的时间戳
参数:
无
返回值:
包创建时的时间戳
说明:
ts是包创建时的时间戳,也就是jxTMS在收到包根据包的头四个字节中的识别冠字确定了解包函数后,调用了该解包函数来创建一个新包时的时间戳,也就是说这个时间戳是收包的时间
allUnit(self)
包中所有的数据单元
参数:
无
返回值:
包所映射的dict
clear(self)
清除包中所有的数据单元
参数:
无
返回值:
无
说明:
clear主要用来打包后发送这样的应用场景中重复使用包对象
get(self, key)
获取包中的某项数据
参数:
key:包中某数据单元的key
返回值:
包中存在key所对应的数据单元,则返回其值;否则返回None
set(self, key,value)
设置包中的某项数据
参数:
key:包中某数据单元的key
value:待设置的包中某数据单元的值
返回值:
无
说明:
set主要用来打包后发送这样的应用场景中设置发送数据
toBytes(self)
打包
参数:
无
返回值:
打包后得到的字节数组【bytes类型】
说明:
toBytes主要用来打包后发送这样的应用场景中
参考资料:
下面的系列文章讲述了如何用jxTMS开发一个实用的业务功能:
下面的系列文章讲述了jxTMS的一些基本开发能力: