3. SECS-II 消息结构:Message Header、Stream 与 Function、Message Body 的编码规则

SECS-II 是 SEMI 标准 E5 定义的消息层协议,它规定了在 HSMS 或 RS-232 连接上传输的每一条消息的格式。理解 SECS-II 消息结构是进行 DataItem 定义与数据采集的基础。一条完整的 SECS-II 消息由 Message Header(消息头)和 Message Body(消息体)两部分组成。

核心要点:SECS-II 消息是“Header + Body”的二元结构。Header 固定 10 字节,用于路由和控制;Body 采用 SML(SECS Message Language)编码,用于承载具体的数据项。

3.1 Message Header(消息头)编码规则

Message Header 是每条 SECS-II 消息的前 10 个字节,它不依赖于具体的消息内容,而是为底层传输(如 HSMS)提供必要的控制信息。其结构如下表所示:

字节偏移 字段名称 长度(字节) 描述
0 Length 4 消息总长度(包含 Header 和 Body),大端序(Big-Endian)
4 Device ID 2 设备 ID,用于多设备环境下的消息路由
6 Stream 1 消息流编号(0-255),定义消息的类别
7 Function 1 消息功能编号(0-255),定义消息的具体操作
8 PType 1 消息类型(0x00 表示 SECS-II 消息)
9 SType 1 会话类型(0x00 表示数据消息,其他值表示控制消息)
实践提示:在解析 Header 时,务必注意 Length 字段是大端序(网络字节序)。Device ID 通常用于区分同一物理连接上的不同设备,在单设备场景下常设为 0。
SECS-II Message Header 结构(10 字节) Length (4 Bytes) Device ID (2) S (1) F (1) PType (1) SType (1) 偏移 0-3 偏移 4-5 6 7 8 9 说明:S=Stream, F=Function。PType 固定为 0x00,SType 为 0x00 表示数据消息。 Length 字段包含整个消息(Header + Body)的字节数。

3.2 Stream 与 Function 的语义

Stream 和 Function 共同构成了 SECS-II 消息的“动词+名词”语义。Stream 定义消息的类别(如设备状态、材料处理、数据收集等),Function 定义对该类别执行的具体操作。Function 编号的奇偶性决定了消息的方向:

  • 奇数 Function(如 S1F1、S6F11): 主设备(Host)发送给从设备(Equipment)的请求(Primary Message)。
  • 偶数 Function(如 S1F2、S6F12): 从设备(Equipment)回复给主设备(Host)的响应(Secondary Message)。
常见误区:不要将 Stream 编号与物理连接混淆。Stream 是逻辑分类,例如 Stream 1 是“设备状态”,Stream 6 是“数据收集”。一个物理连接上可以传输任意 Stream 的消息。

以下是几个常用的 Stream & Function 组合示例:

S&F 名称 方向 描述
S1F1 Are You There Host → Eq 查询设备是否在线
S1F2 On-Line Data Eq → Host 回复设备在线状态
S6F11 Data Report Eq → Host 设备主动上报数据(事件报告)
S2F41 Host Command Host → Eq 主机发送远程命令
Stream & Function 消息流示例 Host Equipment S1F1 (奇数) S1F2 (偶数) S6F11 (偶数,上报) 规则:奇数 Function 为请求(Host→Eq),偶数 Function 为响应(Eq→Host)。 S6F11 是设备主动上报,虽为偶数,但属于“未请求的响应”。

3.3 Message Body(消息体)编码规则

Message Body 紧跟在 Header 之后,采用 SML(SECS Message Language)定义的格式进行编码。SECS-II 定义了一组 数据项(Data Item)类型,用于表示不同种类的数据。Body 的编码遵循以下规则:

  1. 嵌套结构: Body 可以包含一个或多个数据项,数据项可以嵌套(List 包含其他数据项)。
  2. 长度前缀: 每个数据项都有一个长度前缀,用于指示该数据项的总字节数。
  3. 格式字节: 每个数据项的第一个字节是格式字节,编码了数据类型和长度信息。

格式字节的编码规则如下:

位(Bit) 7-4 3-0
含义 数据类型(Format Code) 长度类型(Length Type)
说明 0x00=List, 0x10=Binary, 0x20=Boolean, 0x30=ASCII, 0x40=JIS-8, 0x50=2-byte signed, 0x60=4-byte signed, 0x70=8-byte signed, 0x80=2-byte unsigned, 0x90=4-byte unsigned, 0xA0=8-byte unsigned, 0xB0=Float, 0xC0=Double 0x00=1字节长度, 0x01=2字节长度, 0x02=3字节长度, 0x03=4字节长度
编码示例:一个 ASCII 字符串 "ABC" 的编码为:
0x43 0x03 0x41 0x42 0x43
其中 0x43 = (0x30 | 0x03) 表示 ASCII 类型 + 3 字节长度,0x03 是长度值,0x41/0x42/0x43 是字符 'A'/'B'/'C' 的 ASCII 码。
Message Body 编码结构(SML 格式) Message Body Data Item 1 格式字节 (1B) 长度字节 (1-4B) 数据值 (N Bytes) Data Item 2 格式字节 (1B) 长度字节 (1-4B) 数据值 (N Bytes) Data Item 3 (List) 格式字节 (0x00) 长度字节 (子项数) 子项 1 ... 子项 N 格式字节高 4 位表示数据类型(如 0x30=ASCII),低 4 位表示长度字段占用的字节数(如 0x03=4 字节长度)。

3.4 完整消息示例:S1F1 与 S1F2

下面通过一个完整的消息示例,展示 Header 和 Body 如何组合成一条 SECS-II 消息。以 S1F1(Are You There)和 S1F2(On-Line Data)为例:

S1F1 消息(Host → Equipment):
Header: 00 00 00 0A  00 00  01  01  00  00
        |--Length=10--| DevID | S | F |PT|ST|
Body: (空,无数据项)

Length=10 表示 Header 10 字节 + Body 0 字节。Stream=1, Function=1(奇数,请求)。

S1F2 消息(Equipment → Host):
Header: 00 00 00 0E  00 00  01  02  00  00
        |--Length=14--| DevID | S | F |PT|ST|
Body:  03 01 00
       |--List--|--BIN--|
       格式: 0x03 (List, 1字节长度)
       长度: 0x01 (1个子项)
       子项: 0x00 (Binary, 0字节长度, 表示空数据)

Length=14 表示 Header 10 字节 + Body 4 字节。Stream=1, Function=2(偶数,响应)。Body 包含一个 List,内含一个空的 Binary 数据项。

解析技巧:在实际开发中,建议使用现成的 SECS/GEM 库(如 SECSComm、GEMSecs)来解析消息,避免手动处理字节流。但理解底层编码规则对于调试和排查问题至关重要。

3.5 本章小结

  • Message Header 固定 10 字节,包含 Length、Device ID、Stream、Function、PType、SType 字段。
  • Stream & Function 定义消息的语义:奇数 Function 为请求,偶数 Function 为响应。
  • Message Body 采用 SML 编码,每个数据项由格式字节、长度字节和数据值组成。
  • 格式字节的高 4 位表示数据类型,低 4 位表示长度字段的字节数。
  • 掌握消息结构是后续学习 DataItem 定义和数据采集方案设计的基础。