4. SECS 消息结构解析:Message Header(消息头)各字段详解
SECS 消息是 SECS/GEM 通信的基本数据单元。无论是 HSMS 还是 RS-232 传输,每条 SECS 消息都包含一个固定长度的 Message Header(消息头) 和紧随其后的 Data Block(数据块)。消息头承载了消息的路由、控制与标识信息,是解析 SECS 流量的第一道关卡。
4.1 消息头字段总览
HSMS 的 10 字节消息头被划分为 6 个主要字段。下表列出了每个字段的字节偏移、长度与功能概要:
| 字节偏移 | 字段名称 | 长度(字节) | 功能描述 |
|---|---|---|---|
| 0 | Device ID | 2 | 标识目标设备或控制器的逻辑 ID |
| 2 | Stream / Function | 2 | 定义消息的类别(Stream)与具体功能(Function) |
| 4 | Reply Expected | 1 | 指示发送方是否期望收到回复消息 |
| 5 | Block Number | 2 | 消息分块传输时的块序号(0 表示未分块) |
| 7 | System Bytes | 3 | 用于消息匹配与事务关联的唯一标识 |
4.2 Device ID(设备 ID)
Device ID 占用消息头的第 0~1 字节(共 2 字节),是一个 16 位的无符号整数。它用于在 SECS 通信链路中唯一标识一个 设备(Equipment) 或 主机(Host)。
- 取值范围: 0 ~ 65535(0x0000 ~ 0xFFFF)。
- 常见约定: 设备端通常使用 0 或 1,主机端使用 0。实际值由工厂协议约定。
- 位 15 特殊用途: 在 HSMS 中,Device ID 的最高位(bit 15)被用作 控制位,指示消息是控制消息(1)还是数据消息(0)。
4.3 Stream / Function(流 / 功能码)
Stream / Function 占用第 2~3 字节,是 SECS 消息的 类型标识。它由两个部分组成:
- Stream(流): 高字节(Byte 2),取值范围 0~127。Stream 定义了消息的大类,例如 Stream 1 用于设备控制与状态,Stream 2 用于设备数据收集。
- Function(功能码): 低字节(Byte 3),取值范围 0~255。Function 定义了在特定 Stream 下的具体操作,例如 S1F1 表示“获取设备列表请求”。
在 SML 表示法中,Stream 和 Function 组合为 S<Stream>F<Function> 格式,例如 S1F1、S2F41。
| SML 表示 | Stream | Function | 含义 |
|---|---|---|---|
S1F1 |
1 | 1 | Are You There Request(设备存在性查询) |
S1F2 |
1 | 2 | Are You There Reply(设备存在性回复) |
S2F41 |
2 | 41 | Host Command Send(主机命令发送) |
S6F11 |
6 | 11 | Event Report Send(事件报告发送) |
4.4 Reply Expected(期望回复标志)
Reply Expected 占用第 4 字节,是一个 1 字节的标志字段。它指示发送方是否期望接收方在收到此消息后返回一条回复消息。
- 0x00(False): 不期望回复。发送方发送后即完成,不等待回复。
- 0x01(True): 期望回复。发送方会等待接收方返回对应的 Function 码为偶数的回复消息。
4.5 Block Number(块号)
Block Number 占用第 5~6 字节(2 字节),用于处理 消息分块(Message Blocking)。当一条 SECS 消息的数据块长度超过底层传输单元的限制时,发送方会将消息拆分为多个块进行传输。
- 0x0000: 表示消息未分块,这是最常见的情况。
- 0x0001 ~ 0xFFFF: 表示当前块在分块序列中的序号,从 1 开始递增。
- 最后一个块: 通过消息头中的其他标志(如 E-bit)标识,Block Number 本身不指示是否为最后一块。
4.6 System Bytes(系统字节)
System Bytes 占用第 7~9 字节(3 字节),是 SECS 消息的 事务标识符。它用于将请求消息与对应的回复消息进行匹配。
- 唯一性: 发送方在发送每条请求消息时,应生成一个唯一的 System Bytes 值。
- 匹配机制: 接收方在回复消息中会原样返回请求消息的 System Bytes,发送方据此识别回复对应哪条请求。
- 取值范围: 0x000000 ~ 0xFFFFFF(约 1600 万个唯一值)。
| 字段 | 字节偏移 | 长度 | 典型值示例(Hex) | 说明 |
|---|---|---|---|---|
| System Bytes | 7~9 | 3 字节 | 0x01A3F5 |
请求消息中的唯一标识 |
| System Bytes(回复) | 7~9 | 3 字节 | 0x01A3F5 |
回复消息原样返回,用于匹配 |
4.7 消息头完整解析示例
下面是一个从 Wireshark 捕获的原始 HSMS 消息头十六进制数据,我们逐字段进行解析:
原始数据(10 字节 Hex):
00 01 01 01 01 00 00 00 00 01
字段解析:
- Device ID: 0x0001 → 设备 ID = 1
- Stream/Function: 0x0101 → Stream=1, Function=1 → S1F1
- Reply Expected: 0x01 → True(期望回复)
- Block Number: 0x0000 → 未分块
- System Bytes: 0x000001 → 系统字节 = 1
4.8 消息头字段与 SML 的对应关系
在 SML 表示法中,消息头字段并不直接出现在文本中,而是通过上下文隐式表达。理解这种对应关系,有助于在抓包数据与 SML 日志之间建立映射:
| SML 元素 | 对应消息头字段 | 说明 |
|---|---|---|
S<n>F<m> |
Stream / Function | SML 消息的第一行直接标识 Stream 和 Function |
<Device ID> |
Device ID | 通常在 SML 文件头或会话上下文中定义 |
W(Wait) 或 R(Reply) |
Reply Expected | SML 中通过关键字指示是否等待回复 |
SystemBytes |
System Bytes | 部分 SML 实现会在注释或扩展字段中记录 |