4. SECS-II 数据类型:List、Binary、Boolean、ASCII、UINT、FLOAT 等格式与编码规则
SECS-II 是 SEMI 标准 E5 定义的消息层协议,它规定了在 HSMS 或 RS-232 连接上传输的所有消息的数据结构。SECS-II 的核心是 数据项(Data Item),每个数据项由 数据长度(Length)、格式字节(Format Byte) 和 数据体(Body) 三部分组成。理解这些数据类型的编码规则,是解析和构造 SECS 消息的基础。
4.1 格式字节(Format Byte)结构
格式字节是 SECS-II 数据项的第一个字节,它决定了后续数据的解析方式。其结构如下:
- 高 4 位(Bit 7-4): 数据类型编码(Format Code)。
- 低 4 位(Bit 3-0): 长度字节数(Length Bytes)。通常为 0x01(1 字节长度)或 0x02(2 字节长度)。
例如,格式字节 0x41:高 4 位 0x4 表示 ASCII 类型,低 4 位 0x1 表示长度字段占用 1 个字节。
| 格式码(高4位) | 数据类型 | 缩写 | 长度字节数(低4位) | 数据体编码 |
|---|---|---|---|---|
| 0x0 | List | L | 1 或 2 | 子数据项序列 |
| 0x1 | Binary | B | 1 或 2 | 原始字节 |
| 0x2 | Boolean | BOOLEAN | 1 或 2 | 0x00 (False) / 0x01 (True) |
| 0x4 | ASCII | A | 1 或 2 | ASCII 字符字节 |
| 0x5 | 8 字节有符号整数 | I8 | 1 或 2 | 大端 8 字节 |
| 0x6 | 1 字节有符号整数 | I1 | 1 或 2 | 大端 1 字节 |
| 0x7 | 2 字节有符号整数 | I2 | 1 或 2 | 大端 2 字节 |
| 0x8 | 4 字节有符号整数 | I4 | 1 或 2 | 大端 4 字节 |
| 0x9 | 8 字节无符号整数 | U8 | 1 或 2 | 大端 8 字节 |
| 0xA | 1 字节无符号整数 | U1 | 1 或 2 | 大端 1 字节 |
| 0xB | 2 字节无符号整数 | U2 | 1 或 2 | 大端 2 字节 |
| 0xC | 4 字节无符号整数 | U4 | 1 或 2 | 大端 4 字节 |
| 0xE | 4 字节浮点数 | F4 | 1 或 2 | IEEE 754 大端 |
| 0xF | 8 字节浮点数 | F8 | 1 或 2 | IEEE 754 大端 |
4.2 核心数据类型详解
4.2.1 List(列表)
List 是 SECS-II 中唯一的复合类型,用于包含多个子数据项。格式码为 0x0。List 的数据体不是原始数据,而是由多个子数据项(Item)串联而成。List 的长度字段表示其包含的子数据项个数。
// 示例:一个包含 3 个元素的 List
// 格式字节: 0x01 (List, 1字节长度)
// 长度: 0x03 (3个子项)
// 子项1: [格式字节][长度][数据]
// 子项2: [格式字节][长度][数据]
// 子项3: [格式字节][长度][数据]
4.2.2 Binary(二进制)
Binary 类型用于传输原始字节流,格式码为 0x1。数据体直接是字节序列,不做任何编码转换。常用于传输状态字、标志位或自定义协议数据。
// 示例:传输 4 个字节的二进制数据 0x01 0x02 0x03 0x04
// 格式字节: 0x11 (Binary, 1字节长度)
// 长度: 0x04
// 数据体: 0x01 0x02 0x03 0x04
4.2.3 Boolean(布尔)
Boolean 类型格式码为 0x2。数据体固定为 1 个字节:0x00 表示 False,0x01 表示 True。虽然数据体只有 1 字节,但长度字段仍然存在。
// 示例:传输 True
// 格式字节: 0x21 (Boolean, 1字节长度)
// 长度: 0x01
// 数据体: 0x01
4.2.4 ASCII(字符串)
ASCII 类型格式码为 0x4。数据体为 ASCII 字符的字节序列。注意:SECS-II 标准要求使用 7 位 ASCII 码,高位(Bit 7)必须为 0。
// 示例:传输字符串 "OK"
// 格式字节: 0x41 (ASCII, 1字节长度)
// 长度: 0x02
// 数据体: 0x4F 0x4B ('O' 'K')
4.2.5 UINT(无符号整数)
UINT 系列包括 U1、U2、U4、U8,格式码分别为 0xA、0xB、0xC、0x9。所有整数类型均采用 大端序(Big-Endian) 编码,即高位字节在前。
// 示例:传输无符号整数 1024 (0x0400),使用 U2 类型
// 格式字节: 0xB1 (U2, 1字节长度)
// 长度: 0x02
// 数据体: 0x04 0x00
4.2.6 FLOAT(浮点数)
FLOAT 系列包括 F4(单精度)和 F8(双精度),格式码分别为 0xE 和 0xF。编码遵循 IEEE 754 标准,采用大端序。
// 示例:传输浮点数 3.14,使用 F4 类型
// 3.14 的 IEEE 754 单精度表示为: 0x4048F5C3
// 格式字节: 0xE1 (F4, 1字节长度)
// 长度: 0x04
// 数据体: 0x40 0x48 0xF5 0xC3
4.3 编码规则与字节序
SECS-II 的编码规则可以总结为以下三点:
- TLV 结构: 每个数据项由 Type(格式字节)、Length(长度字段)、Value(数据体)三部分组成。
- 大端字节序: 所有多字节数值(整数、浮点数、长度字段)均使用大端序(网络字节序)传输。
- 长度字段可变: 格式字节的低 4 位决定了长度字段占用的字节数(1 或 2 字节),从而支持不同大小的数据体。
4.4 数据项编码示例
下面通过一个完整的示例,展示如何编码一个包含多种数据类型的 SECS-II 消息体。
// 假设我们要编码一个 List,包含 3 个元素:
// 元素1: ASCII "ABC"
// 元素2: U2 数值 100
// 元素3: Boolean True
// 编码结果(十六进制):
// 0x01 0x03 // List, 3个子项
// 0x41 0x03 0x41 0x42 0x43 // ASCII "ABC"
// 0xB1 0x02 0x00 0x64 // U2 100 (0x0064)
// 0x21 0x01 0x01 // Boolean True
// 逐字节解释:
// 0x01: 格式字节,List类型,1字节长度
// 0x03: 长度字段,表示有3个子项
// 0x41: 格式字节,ASCII类型,1字节长度
// 0x03: 长度字段,表示有3个字符
// 0x41 0x42 0x43: 'A' 'B' 'C'
// 0xB1: 格式字节,U2类型,1字节长度
// 0x02: 长度字段,表示2字节数据
// 0x00 0x64: 大端序数值100
// 0x21: 格式字节,Boolean类型,1字节长度
// 0x01: 长度字段,表示1字节数据
// 0x01: True
4.5 数据类型选择策略
在实际的 SECS/GEM 通信中,选择合适的数据类型可以优化传输效率和解析性能:
| 应用场景 | 推荐类型 | 原因 |
|---|---|---|
| 设备状态标志 | Boolean 或 Binary | 占用空间小,解析简单 |
| 计数器、ID 编号 | U4 或 U2 | 无符号,范围明确 |
| 测量值(温度、压力) | F4 或 F8 | 支持小数,精度可控 |
| 文本消息、配方名称 | ASCII | 人类可读,调试方便 |
| 复杂数据结构 | List | 支持嵌套,灵活组合 |
4.6 SECS-II 数据项编码流程
下面的 SVG 图展示了从原始数据到 SECS-II 编码字节流的完整流程:
4.7 常见问题与避坑指南
- 长度字段溢出: 当数据体长度超过 255 字节时,必须使用 2 字节长度(格式字节低4位=0x2),否则接收方会截断数据。
- 字节序错误: 所有多字节数据必须使用大端序。如果使用小端序编码,数值会被错误解析(例如 0x0102 会被解析为 0x0201)。
- ASCII 高位问题: 某些系统可能发送 8 位扩展 ASCII,但 SECS-II 标准要求 7 位 ASCII。高位为 1 的字节可能导致解析异常。
- List 嵌套深度: 虽然标准未限制嵌套深度,但实际设备通常限制在 10 层以内。过深的嵌套可能导致栈溢出。