4、SECS-II消息编码基础:SECS-II数据项格式、数据项类型(List, ASCII, Binary等)与格式字节解析
SECS-II(SECS-2)是SECS/GEM协议栈中定义消息内容与结构的核心层。它规定了设备与主机之间交换的数据如何被组织、编码和解析。理解SECS-II的数据项格式、类型系统以及格式字节(Format Byte)的编码规则,是进行设备端软件开发、日志解析和协议调试的必备基础。
核心要点: SECS-II消息由一系列数据项(Data Item)组成。每个数据项通过一个格式字节(Format Byte)来声明其数据类型和长度,从而实现自描述(Self-Describing)的编码机制。
4.1 SECS-II数据项通用格式
一个标准的SECS-II数据项在字节流中由三部分组成:格式字节、长度字节和数据体。这种结构使得解析器无需预知消息结构即可逐项解码。
| 字段 | 字节数 | 描述 |
|---|---|---|
| 格式字节 (Format Byte) | 1 | 高4位表示数据类型,低4位表示长度字节数(通常为1、2或3)。 |
| 长度字节 (Length Bytes) | 1 ~ 3 | 以无符号整数形式表示后续数据体的字节长度。长度字节数由格式字节的低4位决定。 |
| 数据体 (Data Body) | 可变 | 实际承载的数据内容,其字节数由长度字节指定。 |
编码示例: 一个ASCII字符串 "ABC" 的编码为:
41 03 41 42 43。其中 41 是格式字节(ASCII类型,长度字节数为1),03 是长度字节(表示后续3个字节),41 42 43 是ASCII字符 'A'、'B'、'C'。
4.2 数据项类型(Format Codes)
格式字节的高4位定义了SECS-II支持的基本数据类型。以下是SECS/GEM协议中最常用的几种类型:
| 类型名称 | 格式码 (Hex) | 描述 | 典型用途 |
|---|---|---|---|
| List | 0x00 – 0x0F | 容器类型,用于嵌套其他数据项。长度字节表示包含的子项数量。 | 结构化消息(如S1F1、S2F41)的顶层封装。 |
| Binary | 0x20 – 0x2F | 原始字节序列,无特定编码。 | 传输固件、配置块或未解析的原始数据。 |
| Boolean | 0x30 – 0x3F | 布尔值,通常0x00表示False,非0x00表示True。 | 状态标志、使能位。 |
| ASCII | 0x40 – 0x4F | 可打印的ASCII字符串。 | 设备ID、版本号、日志消息、配方名称。 |
| JIS-8 | 0x50 – 0x5F | 8位日文字符集(JIS X 0201)。 | 日文注释或特定地区配置。 |
| U2 (Unsigned 2-byte) | 0x60 – 0x6F | 16位无符号整数,大端序。 | 计数器、状态ID、报警ID。 |
| U4 (Unsigned 4-byte) | 0x70 – 0x7F | 32位无符号整数,大端序。 | 时间戳、大范围计数器。 |
| I1 (Signed 1-byte) | 0x80 – 0x8F | 8位有符号整数。 | 小范围有符号状态值。 |
| I2 (Signed 2-byte) | 0x90 – 0x9F | 16位有符号整数,大端序。 | 偏差值、误差范围。 |
| I4 (Signed 4-byte) | 0xA0 – 0xAF | 32位有符号整数,大端序。 | 测量值、坐标。 |
| F4 (Float 4-byte) | 0xB0 – 0xBF | 32位单精度浮点数,IEEE 754标准,大端序。 | 温度、压力、流量等模拟量。 |
| F8 (Float 8-byte) | 0xC0 – 0xCF | 64位双精度浮点数,IEEE 754标准,大端序。 | 高精度测量数据。 |
常见误区: List类型的长度字节表示的是子项数量,而非字节长度。例如,一个包含3个ASCII字符串的List,其长度字节值为0x03,而不是这些字符串的总字节数。
4.3 格式字节与长度字节解析
格式字节的低4位(Bit 0 – Bit 3)决定了长度字节的个数,进而影响整个数据项的解析方式。这是SECS-II编码灵活性的关键。
- 低4位 = 0x0 (0): 表示数据体长度为0。此时没有长度字节,也没有数据体。常用于表示空List或空字符串。
- 低4位 = 0x1 (1): 后续有1个长度字节,可表示0 – 255字节的数据体。
- 低4位 = 0x2 (2): 后续有2个长度字节(大端序),可表示0 – 65535字节的数据体。
- 低4位 = 0x3 (3): 后续有3个长度字节(大端序),可表示0 – 16,777,215字节的数据体。
解析示例: 假设收到字节序列
71 00 00 04 00 00 00 01。71:高4位0x7表示U4类型;低4位0x1表示有1个长度字节。00:长度字节,值为0,表示数据体长度为0。但U4类型通常不会长度为0,此处可能为编码错误或特殊约定。- 若序列为
71 04 00 00 00 01:则长度字节04表示后续4个字节为数据体,解析为U4值0x00000001。
4.4 List数据项的嵌套结构
List是SECS-II中唯一用于构建层次结构的类型。一个List可以包含任意数量的子项,每个子项可以是任何类型(包括另一个List)。这种递归结构使得SECS-II能够表达复杂的消息体。
// 示例:一个包含两个子项的List
// 子项1: ASCII "OK"
// 子项2: U2 值 100
// 编码字节流(十六进制):
// 01 02 -- List格式字节(0x01) + 长度字节(0x02,表示2个子项)
// 41 02 4F 4B -- 子项1: ASCII格式字节(0x41) + 长度(0x02) + 数据("OK")
// 61 02 00 64 -- 子项2: U2格式字节(0x61) + 长度(0x02) + 数据(0x0064 = 100)
解析技巧: 解析List时,需要递归地读取每个子项的格式字节,并根据其类型和长度跳转到下一个子项的起始位置。大多数SECS/GEM库(如SECS-I、HSMS)都内置了这种递归解析器。
4.5 SECS-II数据项编码流程
下面的SVG图展示了从原始数据到SECS-II字节流的编码过程,以及解码时的逆向流程。
4.6 常见数据项编码示例
为了加深理解,下表列出了几种常见数据项的实际编码示例(十六进制表示):
| 数据类型 | 原始值 | 编码字节流 (Hex) | 说明 |
|---|---|---|---|
| List | 空List | 00 |
格式字节0x00,低4位为0,无长度字节和数据体。 |
| List | 包含2个U4 | 01 02 71 04 00 00 00 0A 71 04 00 00 00 14 |
List格式字节0x01,长度2;两个U4值分别为10和20。 |
| ASCII | "SECS" | 41 04 53 45 43 53 |
格式字节0x41,长度4,数据为'S','E','C','S'。 |
| U2 | 1024 | 61 02 04 00 |
格式字节0x61,长度2,数据0x0400 = 1024。 |
| I4 | -1 | A1 04 FF FF FF FF |
格式字节0xA1,长度4,数据为-1的补码表示。 |
| F4 | 3.14 | B1 04 40 48 F5 C3 |
格式字节0xB1,长度4,IEEE 754单精度浮点数。 |
4.7 格式字节速查表
在实际开发中,快速识别格式字节是调试的基础。下表列出了最常用格式字节的完整值(假设长度字节数为1):
| 类型 | 格式字节 (Hex) | 长度字节数 | 数据体长度范围 |
|---|---|---|---|
| List | 0x01 | 1 | 0 – 255 个子项 |
| Binary | 0x21 | 1 | 0 – 255 字节 |
| Boolean | 0x31 | 1 | 0 – 255 字节 |
| ASCII | 0x41 | 1 | 0 – 255 字符 |
| U2 | 0x61 | 1 | 0 – 255 字节 (通常为2) |
| U4 | 0x71 | 1 | 0 – 255 字节 (通常为4) |
| I1 | 0x81 | 1 | 0 – 255 字节 (通常为1) |
| I2 | 0x91 | 1 | 0 – 255 字节 (通常为2) |
| I4 | 0xA1 | 1 | 0 – 255 字节 (通常为4) |
| F4 | 0xB1 | 1 | 0 – 255 字节 (通常为4) |
| F8 | 0xC1 | 1 | 0 – 255 字节 (通常为8) |
实战建议: 在编写SECS-II解析器时,建议先读取第一个字节,提取高4位判断类型,再根据低4位决定读取多少个长度字节。对于List类型,需要递归处理;对于固定长度类型(如U4、F4),可以校验长度字节是否与预期一致,以捕获编码错误。