4. SECS-II消息编码与解码实战
SECS-II 是 Host 与设备之间真正承载业务语义的层。它规定了消息由 SxFy(Stream 与 Function)标识,消息体由若干数据项(Data Item)按顺序组成,数据项可以是标量,也可以是列表,列表内部还能继续嵌套列表。EAP 联机调试中大量问题并非出在 HSMS 连接,而是出在“消息体结构理解错了”:字段顺序错、类型错、列表层级错,都会导致设备回 S9F7 或直接不响应。因此,掌握 SECS-II 的编码与解码,是联机开发的核心基本功。
一、三种表示形式:SML、XML 与二进制
同一条 SECS-II 消息有三种常见表达方式。二进制是线上真实传输的格式,由长度字节、格式字节和数据字节组成;SML(SECS Message Language)是面向人的文本表示,常用于日志、测试脚本和文档;XML 表示则便于与上层 MES/系统集成。三者可以互相转换,理解它们的对应关系是解码的第一步。
以一条常见的 S1F13(Establish Communications Request)为例,其 SML 表示如下:
S1F13 W
<L [2]
<A [6] 'EQUIP1'
<A [4] 'HOST'>
.
其中 W 表示需要回复(Wait),<L [2] 表示一个含 2 个元素的列表,<A [6] 表示长度为 6 的 ASCII 字符串。对应的 XML 表示则把结构显式标签化:
<SECSMessage s="1" f="13" replyBit="true">
<List count="2">
<ASCII length="6">EQUIP1</ASCII>
<ASCII length="4">HOST</ASCII>
</List>
</SECSMessage>
可以看到,SML 用尖括号和方括号紧凑表达,XML 用标签和属性表达,但两者描述的是同一棵树。解码的本质,就是把二进制字节流还原成这棵树;编码则是把这棵树序列化成字节流。
二、数据项类型与列表嵌套
SECS-II 的数据项类型由格式码决定,常见的有:L(列表,0x00)、B(二进制,0x20)、Boolean(0x11)、A(ASCII,0x40)、J(有符号整型)、U(无符号整型,U1/U2/U4/U8)、F(浮点,F4/F8)。每个数据项编码时先写格式字节,再写长度字节,最后写数据。列表比较特殊:它的“长度”表示的是元素个数,而不是字节数,且列表本身不携带元素类型信息,必须靠双方约定的消息结构来解析。
列表嵌套是解析中最容易出错的地方。例如 S2F41(Host Command)的典型结构是:
S2F41 W
<L [2]
<A [8] 'STARTCMD'
<L [1]
<L [2]
<A [4] 'PORT'
<A [2] '01'>>>
.
这里外层列表有 2 个元素:命令名和一个参数列表;参数列表里每个参数又是一个二元列表(参数名 + 参数值)。解码时必须按“外层 → 参数列表 → 单个参数”三层递归展开,任何一层计数错误都会导致后续字段全部错位。
三、常见 SxFy 消息的解析与构造
联机中最常打交道的消息包括:S1F13/S1F14(通信建立)、S1F1/S1F2(Are You There)、S2F41/S2F42(Host Command)、S2F49/S2F50(Enhanced Remote Command)、S6F11/S6F12(Event Report)、S5F1/S5F2(Alarm Report)。以 S6F11 事件报告为例,其结构通常为:
S6F11 W
<L [3]
<U4 [1] 1001 // CEID 事件ID
<L [1] // 报告列表
<L [2]
<U4 [1] 2001 // RPTID 报告ID
<L [2] // 变量列表
<A [4] 'TEMP'
<F4 [1] 25.5>>>
<L [0]> // 可选数据,空列表
.
构造这条消息时,需要依次写入:CEID、报告列表、每个报告内的 RPTID 和变量列表。变量值类型必须与设备定义一致,例如温度用 F4,若误写成 A,设备可能直接丢弃该报告。解析时则反向操作:先读 CEID,再遍历报告列表,逐层取出 RPTID 和变量名值对。
四、编解码的实操要点
在代码实现上,建议把编解码拆成两个独立函数:encode(item) 负责把内存中的树结构序列化为字节流,decode(bytes) 负责把字节流还原为树。解码时维护一个游标,每读一个数据项就前进相应字节数;遇到列表则递归调用自身,直到读完该列表声明的元素个数。这样无论嵌套多深,逻辑都保持一致。
验证编解码是否正确,最直接的方法是用 SML 做“往返测试”:把一条 SML 消息编码成二进制,再解码回 SML,比较两者是否一致。若一致,说明编解码对称;若不一致,通常是长度字节或列表计数写错。实际联机时,再结合设备返回的 SxFy 和 S9F7(Illegal Data)判断是结构问题还是权限问题。
掌握 SECS-II 的编码与解码,本质上就是掌握“树结构 + 类型码 + 长度”这三件事。把 SML 当作调试语言,把 XML 当作集成语言,把二进制当作传输语言,三者互转熟练之后,绝大多数联机消息问题都能快速定位。