4. SECS-II 消息结构:Header 与 Body 详解
SECS-II 是 SEMI 标准 E5 定义的消息层协议,它规定了设备与主机之间交换数据的格式。一条完整的 SECS-II 消息由 Message Header(消息头) 和 Message Body(消息体) 两部分组成。Header 负责路由和控制,Body 负责承载实际数据。理解这两部分的结构是解析日志、定位通信故障的基础。
4.1 Message Header(消息头)结构
SECS-II 消息头固定长度为 10 个字节(Bytes),在 HSMS 传输中位于 T3 定时器超时重传机制之前被解析。其结构决定了消息的流向、类型和应答方式。
| 字节偏移 | 字段名称 | 长度(Bytes) | 说明 |
|---|---|---|---|
| 0 | Device ID | 2 | 设备标识符,用于区分多设备或虚拟设备 |
| 2 | Stream | 1 | 消息流编号,范围 0~127 |
| 3 | Function | 1 | 消息功能编号,范围 0~255 |
| 4 | W bit | 1(bit 7) | 等待位,0=不等待回复,1=需要回复 |
| 4 | Reserved | 1(bit 6~0) | 保留位,必须为 0 |
| 5 | System Bytes | 4 | 系统字节,用于消息匹配与超时管理 |
S6F11 时,表示 Stream=6, Function=11。如果后面跟着 W 标记(如 S6F11 W),说明发送方要求接收方必须回复 S6F12。
4.1.1 Device ID 详解
Device ID 占用 2 个字节(16 bit),但在实际 HSMS 传输中,只有低 15 位有效,最高位(bit 15)被用作控制位。在日志中,Device ID 通常以十进制或十六进制显示。如果日志中 Device ID 为 0x000A,表示设备 ID 为 10。
4.1.2 Stream 与 Function 组合
Stream 和 Function 共同构成消息的 ID,格式为 S<Stream>F<Function>。Stream 0 和 Stream 127 为保留值,Stream 1~9 为通用标准定义,Stream 10~126 为设备厂商自定义。
- Primary Message(主消息): Function 为奇数,如 S1F1、S6F11。
- Secondary Message(回复消息): Function 为偶数,且与对应的主消息 Function 相差 1,如 S1F2 回复 S1F1。
4.1.3 W bit(Wait Bit)
W bit 是 SECS-II 协议中最重要的控制位之一,它决定了通信的交互模式。
| W bit 值 | 含义 | 通信模式 | 日志表现 |
|---|---|---|---|
| 0 | 不等待回复 | 单向消息(Fire-and-Forget) | 发送后无对应回复消息 |
| 1 | 需要回复 | 双向握手(Request-Reply) | 必须匹配到对应的 Secondary Message |
S2F17 W 请求设备时间,但设备回复了 S2F18 却未携带数据,或者主机未收到任何回复,日志中会出现 T3 Timeout 错误。此时应优先检查 W bit 是否被正确设置。
4.2 Message Body(消息体)与 Item 格式
Message Body 紧跟在 Header 之后,采用 Item 格式进行编码。Item 是 SECS-II 数据的基本单元,支持嵌套(List 套 List),形成树形结构。每个 Item 由 Header(长度/格式信息) 和 Data(实际数据) 组成。
4.2.1 Item 格式总览
| 格式码 | 缩写 | 数据类型 | 长度(Bytes) | 示例 |
|---|---|---|---|---|
| 0x00 | L | List(列表) | 1~4(子项数量) | L[3] 表示包含 3 个子 Item |
| 0x10 | A | ASCII 字符串 | 1~4(字符数) | "OK" |
| 0x20 | B | 二进制字节数组 | 1~4(字节数) | 0x01 0x02 |
| 0x30 | I | 有符号整数(1/2/4/8 Bytes) | 1~4(长度前缀) | I1: -128~127 |
| 0x40 | F | 浮点数(4/8 Bytes) | 1~4(长度前缀) | F4: IEEE 754 单精度 |
| 0x50 | U | 无符号整数(1/2/4/8 Bytes) | 1~4(长度前缀) | U2: 0~65535 |
<L [2]> 表示一个 List 包含 2 个子元素。看到 <A 5 "Hello"> 表示一个长度为 5 的 ASCII 字符串。嵌套结构如 <L [2]> <A 3 "ABC"> <I4 100> 是常见的数据封装方式。
4.2.2 格式码与长度编码规则
每个 Item 的第一个字节是 格式码,高 4 位表示数据类型,低 4 位表示长度字节数(Length Bytes)。例如:
0x41:高 4 位0x4表示 F(浮点数),低 4 位0x1表示长度占用 1 个字节,后续 1 个字节表示实际数据长度。0x42:高 4 位0x4表示 F,低 4 位0x2表示长度占用 2 个字节。
4.2.3 常见 Item 编码示例
// 示例 1:一个简单的 ASCII 字符串 "OK"
// 格式码 0x41 (A + 1字节长度) + 长度 0x02 + 数据 0x4F 0x4B
0x41 0x02 0x4F 0x4B
// 示例 2:一个包含 2 个子项的 List
// 格式码 0x01 (L + 1字节长度) + 长度 0x02 + 子项1 + 子项2
0x01 0x02 0x41 0x03 0x41 0x42 0x43 0x31 0x04 0x00 0x00 0x00 0x64
// 子项1: 0x41 0x03 0x41 0x42 0x43 -> A 3 "ABC"
// 子项2: 0x31 0x04 0x00 0x00 0x00 0x64 -> I4 100
// 示例 3:无符号整数 U2,值为 1000
// 格式码 0x52 (U + 2字节长度) + 长度 0x02 + 数据 0x03 0xE8
0x52 0x00 0x02 0x03 0xE8
4.3 日志中的 SECS-II 消息实例
以下是从实际设备日志中截取的一条 SECS-II 消息,展示了 Header 与 Body 的完整结构:
2024-08-15 10:23:45.678 [RX] HSMS Message
Header:
Device ID : 0x000A (10)
Stream : 1
Function : 1
W bit : 1 (需要回复)
System : 0x12345678
Body:
<L [2]>
<A 4 "MDLN">
<A 8 "SECS-GEM">
Interpretation: S1F1 W (Are You There Request)
Reply Expected: S1F2
- W bit = 1:主机发送 S1F1 后,必须等待设备回复 S1F2。如果日志中只有 S1F1 而没有后续的 S1F2,说明通信链路可能中断或设备未响应。
- Body 结构:L[2] 表示 List 包含 2 个字符串,这是 S1F1 的标准数据格式,用于询问设备型号。
- System Bytes:0x12345678 用于匹配请求与回复,回复消息的 System Bytes 必须与此相同。
4.4 常见解析错误与避坑指南
| 错误类型 | 现象 | 根本原因 | 解决方案 |
|---|---|---|---|
| W bit 忽略 | 主机发送 W=1 消息后未收到回复,日志报 T3 Timeout | 设备未实现回复逻辑或 W bit 被错误置 0 | 检查设备配置,确保 W bit 与设备能力匹配 |
| Item 长度解析错误 | Body 解析到一半报错,或数据显示不全 | 格式码低 4 位表示的长度字节数被误读 | 确认格式码的低 4 位,正确读取后续长度值 |
| 嵌套层级溢出 | 解析器栈溢出或死循环 | L 类型 Item 嵌套过深,超出解析器限制 | 限制最大嵌套深度(通常 10 层),日志中检查异常嵌套 |
| Device ID 不匹配 | 消息被设备忽略或路由错误 | Header 中的 Device ID 与设备配置不一致 | 核对日志中的 Device ID 与设备参数设置 |