DiverseCloud 平台TLV标准封装
雅鲁紧凑型TLV数据格式规范
[TOC]
0. 修改日志
Version | Date | Author | Modified Points |
---|---|---|---|
1.0 | 2019.03.14 | nix.long | Initial Version |
1. 协议背景
在面向物联网的通信传输过程中, 通信双方需要约定数据通信传输的格式来顺利的编码/解码。 根据数据格式可读性, 可将传输协议分为可读性强的文本格式(文本格式也是特殊的二进制数据流)和可读性差的二进制数据流格式.
文本格式如xml, json等, 用户接收后容易识别处理传输内容; 其他数据流格式就需要收发双方进行约定.
在物联网领域,纯私有帧协议不具备广泛应用的特征; 而当面对一些资源受限设备,文本格式又会因为额外浪费不少传输资源,而被限制性使用.为了在广泛复用和节省资源空间之间找到一个平衡, 我们定义了TLV紧凑型数据格式
其他:
本协议不涉及数据的二次加密, 只定义传输原生为加密数据
本协议不讨论复杂的流传输协议,如视频流,音频流等, 只定义用于基础数据类型传输的简单传输格式
##2. TLV通信数据格式基础规范
2.1 数据格式分类
文本
json
xml
....
二进制流
私有帧格式
TLV
....
2.2 雅鲁简化的TLV格式 定义(v1.0版)
在传统的TLV格式定义中, T表示Type或Tag, L表示Length, V表示Value.每个字段的长度都可以自由定义, 在实际的很多物联网设备应用场景下, 数据种类和数据格式都相对简洁, 因此我们这里先定义一个相对简洁的TLV格式, 用以说明TLV的应用.再根据实际需要, 在实际项目中使用变化的TLV格式
规范的TLV支持基本型(不嵌套)和结构型(嵌套), 在v1.0版去掉对结构型TLV的支持, 只设计对基本型的支持.
2.2.1 协议基础
使用TAG - LENGTH - VALUE的方式进行一个值或数据的传输
每种(或每类)数据属性定义唯一的TAG标识, 并同时定义确切的传输数据类型和数据单位, 数据类型通过LENGTH和VALUE字段进行表征, 而为了节省传输空间, 单位不再协议中传输, 由用户自行在使用时表征
同一个应用或客户场景, TAG值不能重复表达
通信双方按照定义好的TLV, 进行数据的编解码
2.2.2 TAG的定义
TAG主要用于表征数据是什么(诸如数据对象是什么, 数据来自哪,...), 根据不同场景可以使用一到多个字节来表征TAG字段. 如果场景很简单, 不会存在同类型数据的重复,且数据量少,可以考虑定义1字节的TAG, 否则,可以使用多个字节表征TAG
TAG 自身也可以分解成多个部分,用于表达不同含义. TAG的目的达到即可
后续章节会根据不同场景进行TAG定义举例.
2.2.3 LENGTH的定义
在本规范下, LENGTH不仅仅是表达长度的含义, 他同时表达了数据值的基础数据类型、数据长度、和数据精度等信息
2.2.3.1 LENGTH位域定义
定义如下:
第一字节分为3个功能位域:
数据类型位域: bit7 ~ bit4, 用来表示Value的类型
保留位: bit3, 暂时未使用
数据精度位域: bit2 ~ bit0 , 表示十进制整数进行小数表示时的有效小数位,在Value为其他类型时候(非整型数)忽略
2.2.3.2 LENGTH的位域功能码定义
说明:
目前共支持14类数据类型, v1.0版本不支持变长整数
Value长度大于1字节的整型数、浮点数使用网络字节序传输(大端格式)
(signed/unsigned)char/short/int/long, 当精度位域均是0时, 表示整型数; 当精度位域不是0时, 表示小数,小数精度为精度位域值. 最大的小数位为7位
使用IEEE754 float/double和十进制附带小数位的方法均可表示浮点数, 但使用后者既能确保精度值,也能较少运算消耗, 建议更多的使用十进制数附带小数位的方式来传输浮点数
ascii string和byte array的主要区别是,前者是可打印字符串, 后者可以是任意ascii数组
比较特殊的ascii string和byte array, 由于变长, 额外使用Value部分的第一字节来表达Value长度, 真实长度不包含Value部分的第一字节. 因此这两种数据类型Value部分实际的长度为 1 + 第一字节的值
date-time是为支持时间,特别定义的一个传输时间的类型, 6字节分别标识YYMMDDhhmmss - 年的后两位(比如2018的18)、月(1 ~ 12)、日(1 ~ 31)、时(0 ~ 23, 24小时制)、分(0 ~ 59)、秒(0 ~ 59), 时间为UTC+8. 真实的年份为YY + 2000
2.2.3.3 Length的精度位域进一步说明
精度位域只在Value类型是{(signed/unsigned) char/short/int/long}之一时有效,其他情况下忽略.
使用携带精度位域值的整型数表达小数值,比使用浮点数(float/double)精确, 但限制是只能表达到10^(-7),已能满足很多情况下需求
当精度位域值为0时,这时Value是整型数
当精度位域不为0时(设为X),这时Value是使用整型数表达的小数,小数位数即为X
真实值的计算方法: 设Value值为N,精度位域值为M(范围0~7), 那么所表达的值为: N * 1/(10^M)
2.2.3.4 举例
-
传输Ascii字符串举例:
传输TAG为0x11,Ascii字符串为 "1234"(长度4) 则TLV编码为: 0x11, 0xc0, 0x04, 0x31,0x32,0x33,0x34
-
传输整型数举例
传输TAG为0x12,使用Unsigned Int类型传输精度为2位小数的数据1234.56 (数据类型位域: unsigned int; 小数位域: 2; 值: 123456 (对应16进制0x0001E240)) 则TLV编码为: 0x12, 0x62, 0x00, 0x01, 0xE2, 0x40
2.2.4 VALUE的定义
已定义了支持的VALUE类型(使用C语言数据类型表达):
1byte: bool (true:1 ; false:0)
1byte: (unsigned/signed)char
2byte: (unsigned/signed)short (网络字节序,大端)
4byte: (unsigned/signed)int ; float (网络字节序,大端)
8byte: (unsigned/signed)long ; double (网络字节序,大端)
6byte: date-time - YYMMDDhhmmss
1 ~ 255byte: Ascii字符串
1 ~ 255byte: Ascii数组
2.2.5 雅鲁紧凑型TLV数据格式总结
使用本章节定义的TLV v1.0版本格式, 可以方便支持嵌入式端的各种基础数据类型的数据传输,以及支持有限长度的字符串/数组. 主要特点:
TAG :1字节长度, 最大可以支持255(0特殊用处)个TAG定义
LENGTH: 字段1字节长度(单点传输)或2字节(批量传输), 并分成多个位域用于扩展TLV表达能力
VALUE:支持常见基本数据类型,有限长度字符串、数组,特殊格式的日期时间
3. 应用场景的TLV定义
不同的应用场景, LENGTH字段含义是固定的, Value 也根据Length的定义而确定下来, 唯有变化的TAG字段.
不同场景中, 用户可以根据不同需求来定义TAG 的长度和含义
3.1 雅鲁物联网云平台TLV 接入协议定义
为了在TLV基础上进一步压缩帧数据长度, 我们把每帧都会公有的信息作为固定帧头/帧尾, 而变化数据部分采用TLV格式
3.1.1 基础帧结构
数据帧格式, 保持帧头帧尾部分一致, 消息体部分变化
帧头:
帧头帧尾固定长度总共24字节
其中CMD 根据不同的数据帧有不同的值定义
供应商代码统一分配
消息体: TLV格式, 其中 TAG的长度在帧头(TAG字节数)字段定义
帧尾:
固定长度3字节
-
CRC8(校验) 为从帧头开始,包含整个消息体,采用多项式为:
X^8 + X^5 + X^4 + 1
0xDD, 0xEE为帧尾标志
帧总长: 21 + len(body_msg)
3.1.2 雅鲁物联网云平台TLV接入协议TAG定义
TAG由三字节构成:
外设地址TAG: DeviceTAG, 用于表征被采集设备的外设地址, 范围 1 ~ 255, 如Modbus地址. 如果无外设, 使用0x00
通道地址TAG: ChannelTAG, 当同一个设备节点, 采集多个同类型数据时候, 有可能来自同一个外设的多个点,也有可能来自不同外设, 用通道(Channel)来区分不同数据点
数据类型TAG: DataTAG, 即用来表征数据对象类型的TAG值, 平台暂时使用的1字节
3.1.3 使用TAG进行全局唯一数据的表征
在一个物联网场景中, 一个场景需要多个设备, 一个设备可能搭载多个外设, 一个外设又可能做多个数据采集. 那么平台如果进行全局唯一的数据表征呢?
1. 全局数据的设备ID 不重复, 可以定位到具体设备 2. 通过 DeviceTAG定位到这个设备的具体外设 3. 通过ChannelTAG定位到外设的具体通道 4. 通过预定义的Data TAG表定位到全局唯一的数据类型
即: DeviceID + DeviceTAG + ChannelTAG + DataTAG 构成的全局键能正确的找到全局的对应值