2. 消息结构解析:SECS-II 消息头与消息体的字节布局

SECS-II 消息是 SECS/GEM 协议栈中设备与主机之间交换的最小逻辑单元。一条完整的 SECS-II 消息由 消息头(Message Header) 和 消息体(Message Body) 两部分组成。消息头承载传输控制信息,消息体承载实际的设备数据或命令参数。理解其字节布局是协议栈移植和消息事务处理的基础。

关键概念: SECS-II 消息的字节序采用 大端序(Big-Endian),即高位字节存储在低地址。所有多字节字段(如 Device ID、System Bytes)均遵循此规则。

2.1 消息头(Message Header)字节布局

消息头固定长度为 10 字节,位于消息的最前端。其结构定义了消息的路由、类型和事务标识。下表列出了消息头各字段的偏移量、长度及含义:

偏移量(字节) 长度(字节) 字段名称 说明
0 2 Device ID 设备标识符,用于区分多设备场景下的目标设备。
2 1 R bit + S bit + F bit 控制位:R(Reply expected)、S(Secondary)、F(Function type)。
3 1 Stream 消息流编号(0-255),定义消息的类别。
4 1 Function 消息功能编号(0-255),定义消息的具体操作。
5 1 P bit + S bit + Reserved 控制位:P(Primary/Secondary)、S(Wait bit),其余保留。
6 4 System Bytes 系统字节,用于事务匹配和超时管理。
字段详解:
  • Device ID (2字节): 取值范围 0-32767。在单设备场景下通常固定为 0。
  • 控制位 (1字节): 第7位为 R bit(1=期望回复),第6位为 S bit(1=Secondary消息),第5位为 F bit(1=Function类型)。
  • Stream/Function (各1字节): 组合成 SxFy 格式,例如 S1F13 表示 Stream 1, Function 13。
  • System Bytes (4字节): 由发送方生成唯一值,接收方在回复消息中回传相同值以完成事务匹配。

以下 SVG 展示了消息头 10 字节的完整布局,并标注了每个字段的位偏移和功能:

SECS-II 消息头字节布局 SECS-II 消息头字节布局 (10 字节) Device ID 2 字节 R/S/F 1 字节 Stream 1 字节 Function 1 字节 P/S/Res 1 字节 System Bytes 4 字节 偏移 0 偏移 2 偏移 3 偏移 4 偏移 5 偏移 6 偏移 10 消息头总长度固定为 10 字节,所有多字节字段采用大端序(Big-Endian)

2.2 消息体(Message Body)字节布局

消息体紧跟在消息头之后,其长度由消息头中的 Stream/Function 以及实际数据决定。消息体采用 SECS-II 数据项(Data Item) 格式进行编码,每个数据项由 长度字节(Length Bytes) 和 数据字节(Data Bytes) 组成。数据项可以嵌套,形成复杂的树形结构。

数据项的基本编码规则如下:

  • 长度字节: 使用 1、2 或 3 字节表示后续数据字节的长度。长度字节的最高位(MSB)用于指示长度字节本身的个数(1=还有后续长度字节)。
  • 数据字节: 包含实际的数据内容,格式由数据项的格式代码(Format Code)决定。

下表列出了常见的 SECS-II 数据项格式代码及其对应的数据类型:

格式代码(十六进制) 数据类型 说明
0x00 List 列表,包含多个子数据项
0x10 Binary 二进制数据
0x20 Boolean 布尔值(TRUE/FALSE)
0x30 ASCII ASCII 字符串
0x40 JIS-8 日文汉字字符串
0x50 I8 8 字节有符号整数
0x60 I1 1 字节有符号整数
0x70 I2 2 字节有符号整数
0x80 I4 4 字节有符号整数
0x90 F8 8 字节浮点数
0xA0 F4 4 字节浮点数
0xB0 U8 8 字节无符号整数
0xC0 U1 1 字节无符号整数
0xD0 U2 2 字节无符号整数
0xE0 U4 4 字节无符号整数
注意: 在解析消息体时,必须严格按照长度字节指示的字节数读取数据,并递归处理嵌套的 List 数据项。错误的长度解析会导致消息边界错乱,进而引发协议栈解析异常。

以下 SVG 展示了一个包含 List 和 ASCII 数据项的消息体字节布局示例:

SECS-II 消息体数据项布局示例 消息体数据项布局示例 (List + ASCII) 格式码 0x00 (List) 长度字节 (2 子项) 格式码 0x30 (ASCII) 长度字节 (5 字节) 数据字节 "HELLO" 格式码 0x30 (ASCII) 长度字节 (3 字节) 数据字节 "SEC" 消息体解析要点 1. 每个数据项以格式码开头,格式码的高 4 位表示数据类型,低 4 位表示长度字节数。 2. List 数据项的长度字节表示其包含的子数据项个数,而非字节数。 3. 数据字节的解析方式由格式码决定,例如 ASCII 直接按字符读取,整数按大端序读取。

2.3 消息头与消息体的组合结构

在实际的 SECS-II 消息中,消息头和消息体连续排列,形成完整的消息帧。消息头提供路由和控制信息,消息体承载具体数据。以下 SVG 展示了完整消息帧的结构:

完整 SECS-II 消息帧结构 完整 SECS-II 消息帧结构 消息头 10 字节 消息体 可变长度(由数据项决定) 消息头 + 消息体 = 完整 SECS-II 消息,消息体长度由消息头中的 Stream/Function 隐式定义

2.4 消息解析流程

在协议栈移植过程中,解析 SECS-II 消息通常遵循以下步骤:

  1. 读取消息头: 从接收缓冲区中读取前 10 字节,解析 Device ID、控制位、Stream、Function 和 System Bytes。
  2. 验证消息头: 检查控制位合法性(如 R bit 是否与期望一致),确认 Stream/Function 是否在支持列表中。
  3. 解析消息体: 根据消息头中的 Stream/Function 确定消息体的预期结构,然后递归解析数据项。
  4. 事务匹配: 使用 System Bytes 查找对应的事务上下文,将解析后的消息体挂载到事务对象中。
  5. 错误处理: 如果解析过程中发现长度不匹配、格式码无效或数据溢出,则触发错误回调并丢弃消息。
移植提示: 在嵌入式环境中,建议使用 状态机 驱动消息解析流程。状态机可以优雅地处理分片接收和部分数据到达的场景,避免阻塞式读取。典型的状态包括:WAIT_HEADER、PARSE_HEADER、WAIT_BODY、PARSE_BODY、MESSAGE_COMPLETE。