3. SECS‑II 消息结构详解:Stream、Function、Item 与编码规则

SECS‑II 是 SECS/GEM 协议栈中定义消息内容与格式的层。它不关心消息如何传输(那是 HSMS 或 RS‑232 的工作),只规定:消息由什么组成、如何描述数据、如何编码成字节流。理解 SECS‑II 是开发设备端通信模块、编写消息解析器、调试通信日志的必备基础。

学习目标:掌握 Stream/Function 的语义与分类、Item 的 6 种基本数据类型、消息的嵌套结构与编码规则,能够手动解析或构造一条 SECS‑II 消息。

3.1 Stream 与 Function:消息的“地址”

每一条 SECS‑II 消息都由一个 Stream (S) 和一个 Function (F) 唯一标识。Stream 表示消息的类别,Function 表示该类下的具体操作。格式为 S<n>F<m>,例如 S1F13、S6F11。

  • Stream 编号:0–127,常用 0–63。偶数 Stream 通常用于设备端向主机发送的消息(设备主动上报),奇数 Stream 用于主机向设备发送的消息(主机请求/控制)。
  • Function 编号:0–255,其中 0–63 为标准功能,64–127 为设备自定义,128–255 保留。
  • W bit:Function 编号最高位(bit 7)为 1 时表示该消息需要回复(Wait bit),例如 S1F13 的 Function 13 二进制为 00001101,W bit=0;S1F14 的 Function 14 二进制为 10001110,W bit=1,表示主机发送 S1F13 后设备必须回复 S1F14。
常见 Stream 分类速查:
Stream类别典型消息
S1设备状态与通信控制S1F13 (通信建立请求), S1F14 (通信建立确认)
S2设备诊断与参数管理S2F41 (主机发送数据), S2F42 (设备确认)
S5报警管理S5F1 (报警上报), S5F2 (报警确认)
S6数据收集与事件通知S6F11 (事件报告), S6F12 (事件报告确认)
S7配方管理S7F1 (配方请求), S7F2 (配方数据)
S10终端服务S10F3 (终端显示消息), S10F4 (终端显示确认)
Stream / Function 消息标识结构 SECS‑II 消息帧 Stream (S) + Function (F) + W bit + 消息体 (Item 列表) Stream (S) Function (F) W bit (bit 7) 示例: S1F13 → Stream=1, Function=13 (W=0) → 主机请求建立通信 S1F14 → Stream=1, Function=14 (W=1) → 设备回复确认

3.2 Item 数据类型:消息的“积木块”

SECS‑II 消息体由若干个 Item 组成。每个 Item 包含一个 数据项头 和 数据内容。Item 可以嵌套(List 类型),形成树形结构。标准定义了 6 种基本数据类型:

类型码缩写名称字节长度说明
0LList可变子 Item 的容器,长度字段表示子 Item 个数
1BBinary1–n 字节原始字节数组,无符号
2BBoolean1 字节0x00=False, 0x01=True
3AASCII1–n 字节可打印 ASCII 字符 (0x20–0x7E)
4I1Signed Integer 1‑byte1 字节–128 到 127
5I2Signed Integer 2‑byte2 字节–32,768 到 32,767 (大端)
6I4Signed Integer 4‑byte4 字节–2³¹ 到 2³¹–1 (大端)
7F4Float 4‑byte4 字节IEEE 754 单精度 (大端)
8F8Float 8‑byte8 字节IEEE 754 双精度 (大端)
9U1Unsigned Integer 1‑byte1 字节0 到 255
10U2Unsigned Integer 2‑byte2 字节0 到 65,535 (大端)
11U4Unsigned Integer 4‑byte4 字节0 到 4,294,967,295 (大端)
注意:实际工程中 L (List) 是最常用的容器类型,用于构建嵌套结构。例如一条 S6F11 事件报告消息,最外层是 List,内部包含多个子 List 和 A/I4 等类型。解析时必须递归处理。

3.3 消息格式与编码规则

SECS‑II 消息采用 TLV (Type-Length-Value) 编码,但这里的 Type 是 格式字节 (Format Byte),同时携带类型和长度信息。编码规则如下:

  1. 格式字节 (1 字节):高 4 位表示数据类型(0–11),低 4 位表示长度字节数(0–3)。长度字节数表示后续长度字段占几个字节。
  2. 长度字段 (0–3 字节):大端无符号整数,表示 Value 部分的字节数。对于 List 类型,长度表示子 Item 的个数。
  3. Value 字段:实际数据。对于 List,Value 是连续的多个子 Item 的编码。
编码示例:一个 ASCII 字符串 "OK"
格式字节: 0x41  (类型 A=3, 长度字节数=1)
长度字段: 0x02  (2 字节)
Value:    0x4F 0x4B  ("OK")
完整编码: 41 02 4F 4B
SECS‑II Item 编码结构 (TLV) 格式字节 高4位:类型 低4位:长度字节数 长度字段 0–3 字节 (大端) Value 字段 实际数据 (对于 List 为子 Item 序列) 编码规则详解 1. 格式字节 = (类型码 << 4) | (长度字节数 & 0x0F) 2. 长度字节数 = 0 表示 Value 长度固定 (如 Boolean 固定 1 字节) 3. 对于 List: 长度字段表示子 Item 个数, Value 为子 Item 的连续编码 4. 所有多字节整数/浮点使用大端 (Big‑Endian) 字节序

3.4 嵌套结构与消息树

由于 List 可以包含任意类型的 Item(包括其他 List),SECS‑II 消息天然形成一棵 消息树。解析时需递归遍历。以下是一个典型的 S6F11 事件报告消息结构:

消息: S6F11 (事件报告)
最外层 List (L, 子项数=3)
├── List (L, 子项数=2)
│   ├── ASCII (A) "CEID"   → 事件 ID
│   └── I4 (4 字节) 1001   → 事件编号
├── List (L, 子项数=2)
│   ├── ASCII (A) "DATAID" → 数据 ID
│   └── I4 (4 字节) 5      → 数据编号
└── List (L, 子项数=1)
    └── List (L, 子项数=2)
        ├── ASCII (A) "SVID" → 状态变量 ID
        └── I4 (4 字节) 200  → 变量值
工程建议:在编写解析器时,不要假设消息的层级深度。始终使用递归或栈来解析 List 嵌套。调试时,将消息打印为树形结构(如上)能快速定位问题。

3.5 常见编码陷阱与避坑

陷阱现象解决方案
长度字节数错误解析出的 Value 长度异常,导致后续 Item 错位严格按格式字节低 4 位读取长度字段,不要假设固定长度
大端/小端混淆整数/浮点数值错误SECS‑II 固定大端,使用 ntohl 或手动移位
List 长度表示子项数而非字节数将 List 长度当作字节数解析,导致递归崩溃List 的长度字段永远表示子 Item 个数,不是字节数
ASCII 字符串未以 NUL 结尾字符串末尾出现乱码SECS‑II 的 A 类型不要求 NUL 结尾,长度字段决定有效字符数
Boolean 类型误用将 0x00/0x01 以外的值当作布尔严格检查:0x00=False, 0x01=True,其他值应视为非法

3.6 手动解析示例

假设收到以下字节流(十六进制):

41 02 4F 4B

解析步骤:

  1. 读取第 1 字节 0x41:高 4 位 = 3 (ASCII),低 4 位 = 1 (长度字段占 1 字节)。
  2. 读取第 2 字节 0x02:Value 长度为 2 字节。
  3. 读取第 3–4 字节 0x4F 0x4B:ASCII 解码为 "OK"。

再考虑一个嵌套 List 示例:

00 02  (格式字节 0x00: List, 长度字节数=0? 实际低4位=0 表示长度固定? 不, 低4位=0 表示长度字段占0字节, 但 List 必须有长度! 这里修正: 正确 List 编码应为 0x01 或 0x02 等)
正确示例: 
0x01 0x02  (格式字节 0x01: List, 长度字节数=1; 长度字段 0x02: 2 个子 Item)
  子 Item 1: 0x41 0x02 0x4F 0x4B  (ASCII "OK")
  子 Item 2: 0x71 0x01 0x2A  (U1 类型, 长度=1, Value=0x2A=42)
完整编码对照:
原始字节: 01 02 41 02 4F 4B 71 01 2A
解析结果:
  List (2 个子项)
    ├── ASCII "OK"
    └── U1 42

3.7 本章小结

  • SECS‑II 消息由 Stream/Function 标识,W bit 控制是否需要回复。
  • 消息体由 Item 组成,Item 类型包括 L、B、A、I1–I4、F4/F8、U1–U4 等。
  • 编码采用 TLV 格式:格式字节(类型+长度字节数)+ 长度字段 + Value。
  • List 嵌套 形成消息树,解析时必须递归。
  • 工程中注意大端字节序、List 长度语义、ASCII 无 NUL 结尾等细节。