3、SECS/GEM消息结构:Message Header与Data Item的组成,以及Block与Multi-Block传输机制

SECS/GEM协议的核心在于其结构化的消息格式。理解消息头(Message Header)与数据项(Data Item)的组成,以及底层传输时的分块(Block)与多块(Multi-Block)机制,是进行高效调试与抓包分析的基础。本章将深入剖析这些关键概念,帮助你在调试工具中准确解读原始报文。

3.1 消息结构总览:Header + Body

一条完整的SECS消息由两部分组成:Message Header(消息头)和Message Body(消息体)。消息头固定长度为10字节(在HSMS模式下),而消息体则由一个或多个Data Item(数据项)构成。

调试要点: 在抓包工具(如Wireshark或SECS专用调试器)中,识别消息头的前10个字节是解析的第一步。任何长度不足或格式错误的头部都会导致会话异常。
SECS消息结构总览 SECS 消息结构 (HSMS) Message Header (10 字节) 设备ID / 流与功能 / 块号 / 系统字节 固定长度,控制消息路由与重组 Message Body (可变长度) 由 1 个或多个 Data Item 组成 包含实际数据,如设备状态、参数值

3.2 Message Header 深度解析

消息头是SECS通信的“信封”,它告诉接收方这条消息从哪里来、要到哪里去、属于哪个会话以及如何重组。在HSMS协议中,10字节的Header结构如下:

字节偏移 字段名称 长度 描述
0-1 Device ID / Session ID 2 字节 设备标识符,用于区分总线上的不同设备。Bit 15 为控制位(0=数据消息,1=控制消息)。
2 Stream (流) 1 字节 消息类别,如 Stream 1 (设备控制)、Stream 6 (数据收集)。
3 Function (功能) 1 字节 具体功能码,如 S1F1 (Are You There)、S6F11 (Event Report)。
4 PType (消息类型) 1 字节 协议类型,HSMS 中通常为 0x00 (SECS-II)。
5 SType (会话类型) 1 字节 会话类型,0x00=数据消息,0x01=选择/分离等控制消息。
6-7 Block Number (块号) 2 字节 当前块编号,从 1 开始。单块消息为 0x8001。
8-9 System Bytes (系统字节) 2 字节 系统事务ID,用于匹配请求与响应。
抓包技巧: 在调试工具中,重点关注 Stream/Function 和 System Bytes。S/F 决定了消息的业务含义,而 System Bytes 用于追踪一次完整的“请求-响应”事务。如果响应超时,首先检查 System Bytes 是否匹配。
HSMS Message Header 10字节布局 HSMS Message Header 10字节布局 Device ID 字节 0-1 Stream 字节 2 Function 字节 3 PType 字节 4 SType 字节 5 Block Num 字节 6-7 System Bytes 字节 8-9 总长度固定为10字节,任何解析都必须以此为基础进行偏移计算

3.3 Data Item 的组成与格式

消息体由Data Item构成。每个Data Item包含三个部分:Length(长度)、Format(格式)和Value(值)。这种自描述的结构使得SECS协议能够灵活传输各种类型的数据。

3.3.1 Data Item 三要素

  • Length (长度):1~3字节,表示Value部分的字节数。长度本身也使用可变长度编码(如长度小于128字节时用1字节表示)。
  • Format (格式):1字节,高4位表示数据类型(如List、ASCII、Binary、U2、F4等),低4位表示字节数或子类型。
  • Value (值):实际数据内容,长度由Length字段决定。
格式码 (高4位) 数据类型 示例 调试工具显示
0x0 List (列表) 包含多个子Item L, n
0x1 Binary (二进制) 0x01 0x02 B: 01 02
0x2 Boolean (布尔) TRUE / FALSE BOOL: True
0x4 ASCII (字符串) "Hello" A: "Hello"
0x8 U1 / U2 / U4 (无符号整数) 100, 1000 U2: 1000
0x9 I1 / I2 / I4 (有符号整数) -50, 32000 I4: -50
0xA F4 / F8 (浮点数) 3.14 F4: 3.14
常见解析错误: 在抓包时,如果看到调试工具显示“Invalid Data Item”或长度异常,通常是因为 Format 字节 被误读,或者 Length 字段使用了多字节编码(如长度 > 127 时需占用2字节)。务必确认工具是否支持可变长度编码。
Data Item 三要素结构 Data Item 三要素结构 Length 1~3 字节 表示 Value 的长度 Format 1 字节 高4位类型,低4位子类型 Value N 字节 (由 Length 决定) 实际数据载荷 解析时:先读 Format,再读 Length,最后根据 Length 读取 Value

3.4 Block 与 Multi-Block 传输机制

当一条SECS消息的数据量超过底层传输单元(如TCP报文段)的承载能力时,协议会将消息分割成多个Block(块)进行传输。理解Block机制对于分析大消息(如配方上传、大量日志数据)至关重要。

3.4.1 单块 (Single Block) 消息

大多数控制类消息(如S1F1、S2F17)都是单块消息。其特点是:

  • 消息头中的 Block Number 字段值为 0x8001(高位为1表示这是最后一块,同时也是第一块)。
  • 整个消息体在一个TCP包中传输完毕。

3.4.2 多块 (Multi-Block) 消息

当消息体较大时,发送方将其拆分为多个Block依次发送。接收方根据Block Number进行重组。

Block 序号 Block Number 值 含义
第 1 块 0x0001 起始块,高位为0,表示后面还有更多块。
第 2 块 0x0002 中间块,序号递增。
... ... ...
最后 1 块 0x800N 结束块,高位为1,表示这是最后一块(N为总块数)。
调试关键: 在抓包分析中,如果发现消息不完整或重组失败,请检查:
1. 所有块的 System Bytes 是否一致?
2. Block Number 是否连续且没有丢包?
3. 最后一块的 Block Number 高位是否为 1?
Multi-Block 传输与重组流程 Multi-Block 传输与重组流程 发送方 (Host/Equipment) 接收方 (Equipment/Host) Block 1 (Block Num=0x0001, SysID=0x1234) Block 2 (Block Num=0x0002, SysID=0x1234) Block 3 (Block Num=0x8003, SysID=0x1234) 接收方重组完整消息 按 Block Num 排序,去除头部,拼接 Body 所有块的 System Bytes 必须相同,否则接收方无法正确重组

3.5 抓包分析实战:识别Block边界

在Wireshark或SECS调试工具中,面对一串连续的TCP流,你需要快速识别出Block的边界。以下是标准步骤:

  1. 定位消息头: 找到10字节的Header起始位置。通常可以通过查找固定的PType (0x00) 和 SType (0x00) 来辅助定位。
  2. 读取Block Number: 解析字节6-7。如果值为 0x8001,则为单块消息,直接解析后续Body即可。
  3. 判断多块: 如果Block Number的高位为0(如 0x0001),则说明这是多块消息的第一块。记录下System Bytes,准备接收后续块。
  4. 等待最后一块: 持续接收具有相同System Bytes的后续块,直到收到Block Number高位为1的块(如 0x8003)。
  5. 重组与校验: 将所有块的Body部分按Block Number顺序拼接,然后解析完整的Data Item树。
工具推荐: 使用支持“自动重组”功能的调试工具(如SECSMon或某些商业调试器)可以大幅提高效率。它们会自动处理Block排序和重组,直接展示完整的消息结构树,让你专注于Data Item的值是否正确。

3.6 常见问题与避坑指南

问题现象 可能原因 排查方法
消息解析为乱码 Format字节解析错误,导致长度读取异常 检查Format字节的高4位,确认数据类型是否正确
多块消息重组超时 中间块丢失或顺序错乱 检查TCP层是否有重传或乱序;确认Block Number是否连续
System Bytes不匹配 多块消息中混入了其他事务的块 过滤同一System Bytes的包,排除干扰
Header长度不足10字节 TCP粘包导致数据未完全到达 检查TCP载荷长度,确认是否需要进行应用层缓存