3. SECS-II数据项类型全解
SECS-II 消息体由一串“数据项”组成,每个数据项都带一个格式字节,用来告诉接收端“我是什么类型、有多长”。理解这些类型的编码规则,是解析报文、构造回复、排查长度错位问题的基本功。本节把常用类型分成四组来看:结构类(L)、位与逻辑类(B、BOOLEAN)、字符类(A、JIS8)、数值类(I、U、F)。
格式字节与长度字段
每个数据项以 1 字节格式码开头。格式码 = (格式编号 << 2) | 长度字节数。例如 A 类型格式编号为 020 八进制(即 0x10),若长度用 1 字节表示,格式字节就是 0x10 | 0x01 = 0x11;若长度需要 2 字节,则为 0x12。长度字段紧随其后,按大端序读取,其值等于该数据项包含的元素个数。对于 A、JIS8、B 这类单字节元素,元素个数等于字节数;对于 I2、U4、F8,元素个数要乘以元素宽度才是实际字节数。
示例:A 类型,内容 "HELLO"(5 字节)
格式字节 = 0x11 (A, 1 字节长度)
长度字段 = 0x05 (5 个字符)
数据 = 48 45 4C 4C 4F
示例:U4 类型,内容 [0x00000001, 0x00000002]
格式字节 = 0x72 (U4, 2 字节长度)
长度字段 = 0x0002 (2 个元素)
数据 = 00 00 00 01 00 00 00 02 (共 8 字节)
结构类:L(List)
L 是唯一可以嵌套的类型,相当于“容器”。它的长度字段表示列表中包含的子数据项个数,而不是字节数。解析 L 时必须递归:先读格式字节和长度,再循环读取 N 个子项,每个子项自己带格式字节。L 的格式编号为 000 八进制,格式字节常见为 0x01(1 字节长度)。空列表写作 0x01 0x00。L 是构建复杂消息(如多参数事件报告)的骨架,几乎所有结构化报文都从 L 开始。
位与逻辑类:B、BOOLEAN
B(Binary)表示任意二进制位串,格式编号 010 八进制,格式字节 0x21/0x22/0x23。长度字段是字节数,每个字节 8 位,高位在前。B 常用于传输位掩码、状态字、原始字节块。BOOLEAN 格式编号 011 八进制,格式字节 0x25/0x26/0x27,每个元素占 1 字节,0x00 表示 False,非 0(通常 0x01)表示 True。注意 BOOLEAN 的长度是元素个数,不是位打包,所以 8 个布尔值占 8 字节,而不是 1 字节。
字符类:A、JIS8
A(ASCII)格式编号 020 八进制,格式字节 0x41/0x42/0x43,每个字符 1 字节,按 ASCII 编码。JIS8 格式编号 021 八进制,格式字节 0x45/0x46/0x47,每个字符 1 字节,按 JIS X 0201 的 8 位编码,常用于日文设备。两者长度字段都等于字符个数。解析时若遇到非 ASCII 字节,应检查是否误用了 JIS8。A 类型是设备名、配方名、错误文本最常用的载体。
数值类:I、U、F
有符号整数 I1/I2/I4/I8 分别占 1/2/4/8 字节,格式编号 030/032/034/036 八进制,格式字节 0x65/0x69/0x71/0x79(以 1 字节长度为例)。无符号整数 U1/U2/U4/U8 格式编号 031/033/035/037 八进制,格式字节 0x67/0x6B/0x73/0x7B。浮点 F4/F8 遵循 IEEE 754,格式编号 040/044 八进制,格式字节 0x91/0x99。所有数值类型都是大端序,长度字段为元素个数。例如 U2 的 3 个元素占 6 字节,长度字段写 0x0003。
解析时的关键判断
拿到一段报文后,先读格式字节,用 (fmt >> 2) 得到格式编号,用 (fmt & 0x03) 得到长度字节数。然后按长度字节数读取长度字段,得到元素个数 N。接着根据格式编号确定元素宽度 W:A/JIS8/B/BOOLEAN/I1/U1 为 1,I2/U2 为 2,I4/U4/F4 为 4,I8/U8/F8 为 8,L 特殊——它的“数据”是 N 个子项,需要递归。实际字节数 = N × W(L 除外)。若剩余字节不足,说明报文被截断或长度字段解析错误。
类型选择建议
设备名、配方名用 A;日文文本用 JIS8;状态字、位掩码用 B;开关量、使能标志用 BOOLEAN;计数、ID、端口号用 U1/U2/U4;温度、压力等可能为负的测量值用 I2/I4;需要小数的工艺参数用 F4/F8。选型时优先考虑接收端能否正确解析,以及数值范围是否够用。例如温度范围 -40~150℃,用 I2 足够;若需要 0.01℃ 精度,可放大 100 倍后用 I2 传输,或直接用 F4。