2. SECS-II消息结构精解

SECS-II 是 SEMI E5 标准定义的设备通信消息层,它规定了主机(Host)与设备(Equipment)之间交换的消息长什么样。一条 SECS-II 消息由两部分组成:消息头(Message Header)和消息体(Message Body)。消息头固定 10 字节,负责“路由与语义标识”;消息体是可变长度的数据项序列,负责“承载业务数据”。理解这两部分的结构,是读懂任何一条 SxFy 消息、排查通信问题的起点。

一、消息头:10 字节的固定结构

消息头是定长的 10 个字节,按顺序排列如下:

字节位置字段长度说明
Byte 0Session ID / Device ID1 字节HSMS 中通常为 0xFFFF(未使用),SECS-I 中为设备号
Byte 1Header Byte 21 字节W-Bit(bit7)+ Stream(bit0~6)
Byte 2Header Byte 31 字节Function(0~255)
Byte 3PType1 字节Presentation Type,SECS-II 固定为 0
Byte 4SType1 字节Session Type,数据消息为 0,控制消息非 0
Byte 5~8System Bytes4 字节事务标识,用于请求/应答配对
Byte 9Header Byte 101 字节保留或用于特定扩展

其中最关键的是 Stream、Function、W-Bit 和 System Bytes 四个字段。

Stream(S)占 7 位,取值 0~127,表示消息的“大类”。例如 S1 是设备状态类,S2 是设备控制与诊断类,S6 是数据采集类。Stream 决定了这条消息属于哪个业务域。

Function(F)占 8 位,取值 0~255,表示该 Stream 下的“具体动作”。例如 S1F1 是“Are You There”,S1F2 是它的应答;S1F13 是“Establish Communications Request”,S1F14 是应答。Stream 与 Function 组合成 SxFy,就是一条消息的唯一语义标识。

W-Bit(Wait Bit)位于 Header Byte 2 的最高位。W-Bit = 1 表示发送方期待对方回复(Primary Message,主消息);W-Bit = 0 表示这是一条回复(Secondary Message,应答消息)。例如 S1F1 的 W-Bit 为 1,S1F2 的 W-Bit 为 0。W-Bit 是判断“谁该回谁”的第一依据。

System Bytes 是 4 字节的无符号整数,由发起方生成,应答方必须原样回填。它的作用是让请求与应答能够配对。例如主机发送 S1F1 时 System Bytes = 0x00000001,设备回复 S1F2 时也必须带 0x00000001,主机才能确认这是对刚才那条请求的应答。如果 System Bytes 不匹配,通信层就会认为应答丢失或错乱。

记忆口诀:S 定大类,F 定动作,W 定方向,System Bytes 定配对。四者合起来,一条消息的“身份”就确定了。

二、消息体:数据项与列表结构

消息体由若干数据项(Data Item)组成,每个数据项采用“格式字节 + 长度字节 + 数据”的结构。格式字节的高 6 位表示数据格式(Format Code),低 2 位表示长度字节的个数(Length Bytes)。常见格式码如下:

  • L(List):格式码 0b000000,表示一个列表,其“数据”是若干子数据项,长度表示子项个数。
  • B(Binary):格式码 0b001000,二进制字节串。
  • BOOLEAN:格式码 0b001001,布尔值。
  • A(ASCII):格式码 0b010000,ASCII 字符串。
  • I1/I2/I4/I8:有符号整数,格式码 0b011001/0b011010/0b011100/0b011000。
  • U1/U2/U4/U8:无符号整数,格式码 0b101001/0b101010/0b101100/0b101000。
  • F4/F8:浮点数,格式码 0b100100/0b100000。

长度字节的个数由格式字节低 2 位决定:00 表示 1 个长度字节,01 表示 2 个,10 表示 3 个。长度值表示后续数据的字节数(对 L 类型则表示子项个数)。例如格式字节 0x01 表示“L 类型,1 个长度字节”,后跟 0x02 表示列表内有 2 个子项。

列表可以嵌套。例如一条 S6F11 事件报告消息,其消息体通常是:L,3 { U4 事件ID, L,2 { U4 报告ID, L,n { 变量数据项... } }, L,0 }。这种嵌套结构让 SECS-II 能表达复杂的树形数据。

SECS-II 消息结构:消息头 + 消息体 消息头(10 字节,固定) Session ID Byte 0 W-Bit + S Byte 1 bit7 | bit0-6 Function Byte 2 PType Byte 3 SType Byte 4 System Bytes Byte 5~8(4 字节) Header Byte 10 Byte 9 消息体(可变长度,数据项序列) 数据项结构 格式字节(Format Code + Length Bytes) 长度字节(1~3 字节) 数据内容 示例:S6F11 事件报告消息体 L,3 { U4 事件ID, L,2 { U4 报告ID, L,n { 变量... } }, L,0 } 常用格式码(Format Code) L=0b000000(列表) B=0b001000(二进制) BOOLEAN=0b001001 A=0b010000(ASCII) I1=0b011001 I2=0b011010 I4=0b011100 I8=0b011000(有符号整数) U1=0b101001 U2=0b101010 U4=0b101100 U8=0b101000(无符号整数) F4=0b100100 F8=0b100000(浮点)

三、常见 SxFy 消息示例

下面用几条工程中最常见的消息,把消息头与消息体串起来看。

S1F1 / S1F2(Are You There):主机发送 S1F1,W-Bit=1,System Bytes=0x00000001,消息体为空(L,0)。设备回复 S1F2,W-Bit=0,System Bytes 仍为 0x00000001,消息体通常为 L,2 { A 设备型号, A 软件版本 }。这是最基础的“握手”消息,用于确认设备在线。

S1F13 / S1F14(Establish Communications Request):主机发送 S1F13,W-Bit=1,消息体为 L,2 { A MDLN, A SOFTREV },其中 MDLN 是设备型号,SOFTREV 是软件版本。设备回复 S1F14,W-Bit=0,消息体为 L,2 { B 通信确认码, L,2 { A MDLN, A SOFTREV } }。通信确认码为 0 表示成功,非 0 表示失败。这条消息用于建立通信链路后的能力协商。

S6F11 / S6F12(Event Report Send):设备主动上报事件时发送 S6F11,W-Bit=1,消息体为 L,3 { U4 事件ID, L,2 { U4 报告ID, L,n { 变量数据项 } }, L,0 }。主机收到后回复 S6F12,W-Bit=0,消息体为空。这是数据采集场景中最核心的消息,设备通过它把状态变化、工艺参数、报警等信息推送给主机。

S2F41 / S2F42(Host Command Send):主机向设备下发命令时发送 S2F41,W-Bit=1,消息体为 L,2 { A 命令名, L,n { L,2 { A 参数名, A 参数值 } } }。设备执行后回复 S2F42,W-Bit=0,消息体为 L,2 { B 执行结果码, L,n { L,2 { A 参数名, A 参数值 } } }。结果码 0 表示成功,非 0 表示失败或拒绝。

注意:W-Bit 与 System Bytes 必须成对理解。W-Bit=1 的消息必须由对方用 W-Bit=0 的消息应答,且 System Bytes 必须一致。如果设备收到一条 W-Bit=1 的消息却不回复,主机会超时(T3 超时);如果回复的 System Bytes 不匹配,主机会丢弃该应答并继续等待。

四、实际解析时的观察顺序

拿到一串 SECS-II 报文时,建议按以下顺序解析:先看 Byte 1 的 bit7 判断 W-Bit,再看 bit0~6 得到 Stream;接着看 Byte 2 得到 Function;然后看 Byte 5~8 得到 System Bytes;最后从 Byte 10 开始解析消息体。消息体的解析要递归处理:遇到 L 类型就按长度字段确定子项个数,逐个解析子项;遇到基本类型就按格式码和长度读出数据。这样就能把一条二进制报文还原成可读的 SxFy 消息树。