3. 数据项(Data Item)基础:SECS-II 标准数据类型编码规则
SECS-II 消息的核心是数据项(Data Item, DI)。每个数据项由数据项标识符(Item ID)、长度(Length)和数据体(Data Body)三部分组成。理解标准数据类型的编码规则,是正确解析和构造 SECS-II 消息的前提。本章将详细拆解 ASCII、BINARY、无符号/有符号整数、浮点数、列表及布尔类型的二进制编码格式。
3.1 数据项通用格式
每个 SECS-II 数据项在字节流中遵循统一的 TLV(Type-Length-Value)结构。其中“Type”字段不仅标识数据类型,还包含格式位和长度位。
| 字段 | 字节数 | 说明 |
|---|---|---|
| Item ID | 1 字节 | 高 2 位为格式位(00=List, 01=Single, 10=二次编码),低 6 位为数据类型编码 |
| Length | 1 或 3 字节 | 若 Item ID 低 6 位为 0x00 或 0x01,则 Length 为 3 字节(大端序);否则为 1 字节 |
| Data Body | Length 指定 | 按具体数据类型编码的原始字节 |
3.2 标准数据类型编码规则
SECS-II 定义了 11 种标准数据类型。下表列出了每种类型的编码值、字节长度规则及典型用途。
| 类型 | 编码值(Hex) | 字节长度 | 编码规则 | 典型用途 |
|---|---|---|---|---|
| L | 0x01 | 可变 | Data Body 包含子数据项,Length 表示子项个数 | 嵌套结构、参数列表 |
| BINARY | 0x00 | 可变 | 原始字节序列,无编码转换 | 原始数据、图像、固件块 |
| BOOLEAN | 0x0C | 1 字节 | 0x00=False,非 0x00=True | 开关状态、标志位 |
| ASCII | 0x02 | 可变 | ASCII 字符序列,无终止符 | 设备 ID、文本描述、状态名 |
| U1 | 0x04 | 1 字节 | 无符号 8 位整数,范围 0~255 | 小范围计数、索引 |
| U2 | 0x08 | 2 字节 | 无符号 16 位整数,大端序 | 模块编号、端口号 |
| U4 | 0x10 | 4 字节 | 无符号 32 位整数,大端序 | 时间戳、计数器 |
| I1 | 0x05 | 1 字节 | 有符号 8 位整数,补码表示 | 小范围偏差、状态码 |
| I2 | 0x09 | 2 字节 | 有符号 16 位整数,大端序补码 | 测量值、偏移量 |
| I4 | 0x11 | 4 字节 | 有符号 32 位整数,大端序补码 | 主计数器、累计值 |
| F4 | 0x14 | 4 字节 | IEEE 754 单精度浮点数,大端序 | 温度、压力、速率 |
| F8 | 0x18 | 8 字节 | IEEE 754 双精度浮点数,大端序 | 高精度测量、校准参数 |
3.3 编码示例与字节流解析
以下通过具体示例展示常见数据类型的编码结果。所有示例均采用大端字节序。
3.3.1 ASCII 编码
数据项 "AB"(2 个字符):
Item ID: 0x02 (格式=Single, 类型=ASCII)
Length: 0x02 (2 字节)
Data: 0x41 0x42 ('A' 'B')
完整字节流: 02 02 41 42
3.3.2 U4 编码
数据项 1000(无符号 32 位):
Item ID: 0x10 (格式=Single, 类型=U4)
Length: 0x04 (4 字节)
Data: 0x00 0x00 0x03 0xE8 (1000 的大端表示)
完整字节流: 10 04 00 00 03 E8
3.3.3 F4 编码
数据项 3.14(单精度浮点数):
Item ID: 0x14 (格式=Single, 类型=F4)
Length: 0x04 (4 字节)
Data: 0x40 0x48 0xF5 0xC3 (3.14 的 IEEE 754 大端表示)
完整字节流: 14 04 40 48 F5 C3
3.3.4 BOOLEAN 编码
数据项 True:
Item ID: 0x0C (格式=Single, 类型=BOOLEAN)
Length: 0x01 (1 字节)
Data: 0x01 (非零表示 True)
完整字节流: 0C 01 01
3.4 列表(L)数据项的嵌套结构
列表类型(L)的 Data Body 不包含原始数据,而是包含一个或多个子数据项。每个子数据项自身又是一个完整的 TLV 结构。列表的 Length 字段表示子数据项的个数,而非字节数。
示例:一个包含两个子项的列表,子项分别为 U1 值 5 和 ASCII 值 "OK"。
L Item ID: 0x01 (格式=List, 类型=L)
L Length: 0x02 (2 个子项)
子项1 ID: 0x04 (U1)
子项1 Length:0x01
子项1 Data: 0x05
子项2 ID: 0x02 (ASCII)
子项2 Length:0x02
子项2 Data: 0x4F 0x4B ('O' 'K')
完整字节流: 01 02 04 01 05 02 02 4F 4B
3.5 数据类型编码流程 SVG
下图展示了从原始数据到 SECS-II 字节流的编码过程,以及解码时的逆向流程。
3.6 字节序与对齐规则
SECS-II 协议明确规定所有多字节数据(U2、U4、I2、I4、F4、F8)均采用大端序(Big-Endian),即最高有效字节(MSB)存储在最低地址。这与网络字节序一致,便于跨平台通信。
- U2/I2:高字节在前,低字节在后。例如值 0x1234 编码为 0x12 0x34。
- U4/I4/F4:字节顺序为 [MSB, ..., LSB]。例如值 0x12345678 编码为 0x12 0x34 0x56 0x78。
- F8:8 字节顺序同样为 MSB 在前。
- 对齐:SECS-II 不要求数据项在字节流中对齐到特定边界。每个数据项紧跟前一个数据项的最后一个字节。
ntohl()、ntohs() 等函数或手动字节交换。对于浮点数,需先将字节序转换为小端后再使用 memcpy 到 float/double 变量。
3.7 数据类型选择策略
在实际协议栈移植中,选择合适的数据类型可以节省带宽并提高解析效率。以下是一些推荐策略:
| 场景 | 推荐类型 | 理由 |
|---|---|---|
| 状态标志、开关量 | BOOLEAN | 仅 1 字节,语义清晰 |
| 小范围计数(0~255) | U1 | 节省带宽,避免 U4 浪费 |
| 设备 ID、模块编号 | U2 | 范围 0~65535,足够大多数场景 |
| 时间戳、累计产量 | U4 | 支持大范围无符号值 |
| 温度、压力测量值 | F4 | 单精度满足一般精度要求 |
| 校准参数、高精度数据 | F8 | 双精度保证精度不丢失 |
| 文本描述、日志 | ASCII | 人类可读,易于调试 |
| 嵌套参数结构 | L | 支持复杂层次关系 |
3.8 常见编码错误与调试方法
在移植过程中,数据项编码错误是导致通信失败的主要原因。以下列出典型错误及排查方法:
- 字节序错误:多字节数据未进行大端转换,导致数值错误。调试时打印原始字节流与期望值对比。
- 列表 Length 误解:将列表的 Length 当作字节数解析,导致后续数据项解析错位。务必根据子项个数循环解析。
- ASCII 无终止符:接收方使用
strlen或strcpy处理 ASCII 数据项可能导致缓冲区溢出。必须使用 Length 字段精确控制拷贝长度。 - BOOLEAN 非标值:某些设备发送 0x02 或 0xFF 表示 True,接收方应判断非零即为 True,而非仅判断 0x01。
- 浮点数字节序:IEEE 754 浮点数在小端平台上需先做字节交换,再解释为 float/double。直接强制类型转换会得到错误值。
hexdump)逐字节比对编码结果。对于浮点数,可先编码为已知值(如 1.0、3.14159)验证字节序是否正确。
掌握以上编码规则后,开发者可以准确构造和解析 SECS-II 消息中的数据项,为后续的事务处理(Transaction)和消息流控制打下坚实基础。