Administrator
发布于 2024-07-29 / 5 阅读
0
1

SL 651-2014《水文监测数据通信规约》精讲:帧结构、链路模式与报文编码

SL 651-2014 是水文监测领域最核心的通信规约,所有水文测站的遥测终端(RTU)、数采仪、中心站接收软件,只要涉及数据上报与远程控制,报文格式最终都要落到这份标准上。本文按"架构 → 帧结构 → 链路模式 → 报文编码 → 功能码 → 工程落地"的顺序,把这份标准里真正会影响实现的部分梳理一遍。

一、这份标准管什么

SL 651-2014《水文监测数据通信规约》是水利行业标准,规定了水文监测系统中各级各类系统的设计与建设、以及相关设备生产制造应遵守的通信规约。标准第 4 章"总则"明确了三条边界:

  • 各级各类水文监测系统的设计与建设,以及相关设备的生产制造,应符合本标准的规定;
  • 智能传感器与遥测终端设备之间的接口及数据通信协议,应符合数据采集通信规约;遥测站与中心站之间的数据传输通信协议,应符合报文传输规约;
  • 本标准未能详尽的其他水利数据采集、传输规约,可在本标准规定的框架下扩充;
  • 涉及水文监测系统的仪器仪表设备制造,除符合本标准外,还应符合相应国家标准、行业标准的要求。

这里第一条非常重要:它管的不只是软件开发,还包括设备制造。所以对接中出现"设备厂商报的报文格式跟标准对不上"时,标准本身就是谈判依据。

一个常见的对照:HJ 212 管的是环保行业污染物在线监控,SL 651 管的是水文监测。两者报文风格相似(都是"帧起始符 + 地址 + 功能码 + 正文 + 校验"的字节帧,正文都用"标识符 + 数据"的信息组),但地址结构、功能码、要素标识符完全不同。做过 212 再切 651,最容易犯的错就是拿 212 的思维去套 651——尤其是功能码和标识符,一个都对不上。

二、两层协议不要混

这份标准的第 5 章和第 6 章,管的是两个完全不同的通信环节。

第 5 章 数据采集通信规约:智能传感器 ↔ 遥测终端设备(RTU)。

  • 接口宜采用 RS-485/422、RS-232C、SDI-12 等通用接口标准;通信协议宜采用 Modbus-RTU 和 SDI-12 通信协议;
  • 其他接口类水文仪器宜参照 GB/T 19705—2005。

其中 Modbus-RTU 的规定很具体:

  • 通信波特率宜采用 1200、2400、4800、9600、19200 bit/s;
  • 字节帧结构为 1 个起始位"0"、8 个数据位、1 个停止位"1"、无奇偶校验位(即标准 8N1);
  • 数据帧基本格式为:地址(1 字节)+ 功能码(1 字节)+ 数据(不定长)+ 校验(2 字节);地址域在帧的开始部分,范围 0~255。

第 6 章 报文传输规约:遥测站 ↔ 中心站。这是 SL 651 的主体,也是本文后续要讲的部分。

两层协议里有一个容易忽略的细节——CRC 字节序不一致:

  • 第 5 章的 Modbus 帧规定"除校验值外,其他数据传输顺序为高位字节在前、低位字节在后",即校验值不适用高位在前,这与经典 Modbus 的 CRC 低字节在前一致;
  • 第 6 章的报文帧则明确要求"校验码高位字节在前、低位字节在后"。

同一套系统里,Modbus 层和 SL 651 层的 CRC 字节序是反的,收发两个方向都要按各自规则组帧。

三、帧基本单元与报文控制字符

3.1 帧基本单元

帧的基本单元是字节,每个字节包含 8 个数据位、1 个起始位"0"和 1 个停止位"1",无校验。也就是说,SL 651 报文帧跑在标准 UART 8N1 之上,链路的差错检测完全交给帧尾的 CRC。

3.2 控制字符语义

报文帧的控制字符定义如下,注意帧起始符在两种编码下不同:

控制字符代码 对应编码 功能 使用说明
SOH 01H 帧起始 ASCII 字符编码报文帧起始
SOH 7E7EH 帧起始 HEX/BCD 编码报文帧起始
STX 02H 传输正文起始 —
SYN 16H 多包传输正文起始 多包发送、一次确认的传输模式中使用
ETX 03H 报文结束,后续无报文 作为报文结束符,表示传输完成,等待退出通信
ETB 17H 报文结束,后续有报文 在报文分包传输时作为报文结束符,表示传输未完成,不可退出通信
ENQ 05H 询问 作为下行查询及控制命令帧的报文结束符
EOT 04H 传输结束、退出 作为传输结束确认帧报文结束符,表示可以退出通信
ACK 06H 肯定确认、继续发送 作为有后续报文帧的"确认帧"报文结束符
NAK 15H 否定应答、反馈重发 用于要求对方重发数据包的报文结束符
ESC 1BH 传输结束、终端保持在线 下行确认帧代替 EOT 作为报文结束符,要求终端在线;保持在线 10min 内若没有接收到中心站命令,终端退回原先设定的工作状态

ETX 与 ETB 的区别是工程上最容易忽略的一点:ETB 表示"后面还有",收到 ETB 意味着这次通信不能断;ETX 表示"后面没有了",链路可以释放。同理,ACK 表示"收到、请继续发",ESC 表示"收到、你保持在线待命",EOT 才是"可以退出了"。

3.3 帧结构框架

标准分别规定了上行和下行两套帧结构框架,不管采用何种字符编码,都必须满足这个框架。传输顺序为高位字节在前、低位字节在后。

上行报文(遥测站 → 中心站)结构:

序号 名称 编码说明
1 帧起始符 01H / 7E7EH
2 中心站地址 范围 1~255
3 遥测站地址 —
4 密码 —
5 功能码 —
6 报文上下行标识及长度 —
7 报文起始符 STX / SYN
8 包总数及序号 报文起始符为 SYN 时编入该组,其他情况下省略
9 报文正文 —
10 报文结束符 ETB / ETX
11 校验码 校验码前所有字节的 CRC 校验,生成多项式 X¹⁶+X¹¹+X²+1,高位字节在前,低位字节在后

下行报文(中心站 → 遥测站)结构:

序号 名称 编码说明
1 帧起始符 01H / 7E7EH
2 遥测站地址 —
3 中心站地址 范围 1~255
4 密码 —
5 功能码 —
6 报文上下行标识及长度 —
7 报文起始符 STX / SYN
8 包总数及序号 报文起始符为 SYN 时编入该组,其他情况下省略
9 报文正文 —
10 报文结束符 ENQ / ACK / NAK / EOT / ESC
11 校验码 同上行说明

上下行的两个地址顺序是相反的:上行是"中心站地址在前、遥测站地址在后",下行是"遥测站地址在前、中心站地址在后"。这是实现解析器时第一个要对齐的地方,写反了会直接把地址解析错位。

四、地址与密码

4.1 遥测站地址

遥测站地址编码由 5 个字节构成(A5~A1),其中 A5 是高位字节、A1 是低位字节,分两种情况:

水文遥测站:采用 5 字节 BCD 码,首字节为 00,后 4 字节编码方法按照 SL 502 的规定执行。

其他遥测站:采用 5 字节混合编码,中心站解码时还原为 6 个字节 BCD 码。其中前三个字节 A5、A4、A3 采用 GB 2260—2007 规定的行政区划代码的前 6 位,A5 为省(自治区、直辖市)码,A4 为地(市、州、盟)码,A3 为县(市、区、旗)码;后 2 个字节 A2、A1 为遥测站地址自定义段,采用 HEX 码,中心站解码时还原为 3 个字节 BCD 码。每个县遥测站地址自定义段范围为 60000~65534,65535 为广播地址,0 为无效地址。

广播地址 65535 是查询类场景的关键:中心站要批量向某片区所有站下发命令时用得上。

地址编码部门应保证遥测站地址的唯一性。

4.2 密码

密码为 2 个字节 HEX 码,由中心站生成,中心站应能远程统一修改遥测终端密码。遥测终端应设定初始密码,入网后应及时更改。

五、四种链路传输模式

链路传输模式分四种,这是设计通信状态机的基础:

模式代号 模式种类 适用工作制式 适用信道
M1 发送/无回答 自报式 单向或双向信道
M2 发送/确认 自报式 双向信道
M3 多包发送/确认 自报式 双向信道
M4 查询/响应 查询应答式 双向信道

各模式的应用规定要点:

  • M1:遥测站为通信发起端,发出报文后中心站不需响应。可用于发送单帧自报报文,包括测试报、均匀时段水文信息报、遥测站定时报、加报报、小时报、人工置数报;其上行报文结束符为 ETX,没有下行帧。
  • M2:遥测站为发起端,中心站接收正确应发"确认"报文,接收无效则不响应。遥测站收不到响应报文应启动重发机制,最多重发 2 次。上行帧结束符为 ETB/ETX,下行帧为"确认"帧、结束符为 EOT/ESC。
  • M3:通常情况下遥测站为发起端,连续发出多个报文包,中心站正确接收全部数据包仅回答 1 次确认报文;若有错误数据包,中心站应发包括错误数据包序列号(1 个错误包序列号,每包单独重发)的响应包,遥测站重发相应序列号包数据,最多重发 2 次。适用于发送多帧自报报文,包括图片信息报、均匀时段水文信息报、人工置数报等。
  • M4:中心站为发起端,发出查询请求报文后,遥测站接收请求报文正确应发送响应帧;如遥测站接收请求报文无效则不响应。用于查询遥测站数据、设置(修改)遥测站运行状态参数、控制遥测站运行。下行帧为"查询/确认"帧、结束符为 ENQ/ACK/EOT;上行帧为响应帧,结束符为 ETB/ETX。

链路传输基本规则

  • 包的字符之间无线路空闲间隔;两包之间的线路空闲间隔则应考虑信道网络延时、中间环节延时、终端响应时间、波特率等因素。两个数据包之间应至少等待一个线路空闲间隔。标准没有给出这个间隔的具体毫秒数,需要按现场信道特性实测确定——这是一个非常典型的"标准留白,靠联调"的地方。
  • 自报式工作制式下,通信发起端是遥测站、接收端是中心站;查询应答工作制式下,发起端是中心站、接收端是遥测站。
  • 发起端在规定时间内没有正确收到响应报文,应作为超时出错处理,超时出错后应启动重发机制。
  • 数据重发由通信发起端控制,应重复 2 次;若连续 3 次超时,应退出通信,等待下次重新建立链路。
  • 对于单向信道,遥测站发完报文即退出通信;对于双向信道,中心站负责控制是否退出通信链路。
  • 中心站"确认"帧报文结束符是 ESC 时,遥测站应保持通信设备带电值守,随时响应中心站查询/设置命令;是 EOT 时,遥测站退出通信状态。

六、两种字符编码方式

SL 651 与很多同类规约不一样的地方在于:同一套帧结构,有两套字符编码。

6.1 ASCII 字符编码

ASCII 编码下,报文帧起始采用 SOH(01H)。以 M1/M2/M4 上行帧为例,各字段的传输字节数如下:

序号 名称 传输字节数 说明
1 帧起始符 1 SOH
2 中心站地址 2 1 字节 HEX 转换为 2 个 ASCII 字符传输,范围 1~255
3 遥测站地址 10 编码规则见 6.2.3.2,转换为 10 个 ASCII 字符传输
4 密码 4 2 字节 HEX 编码,转换为 4 个 ASCII 字符传输
5 功能码 2 1 个字节功能码转换为 2 个 ASCII 字符传输
6 报文上下行标识及长度 4 2 字节 HEX 编码转换为 4 个 ASCII 字符传输
7 报文起始符 1 STX
8 报文正文 不定长 自报数据、响应帧内容等
9 报文结束符 1 ETX、ETB
10 校验码 4 2 字节 HEX 编码转换为 4 个 ASCII 字符传输

M3 模式则采用 SYN 作为报文起始符,并在其后增加"包总数及序号"字段(6 个 ASCII 字符:前 3 个表示包总数、后 3 个表示本次发送数据包的序号,范围 1~4095,原码采用 HEX 码)。

6.2 HEX/BCD 编码

HEX/BCD 编码下,报文帧起始采用 7E7EH(两个字节)。对应字段的字节数显著缩短:

序号 名称 传输字节数 说明
1 帧起始符 2 7E7EH
2 中心站地址 1 1 字节 HEX 码,范围 1~255
3 遥测站地址 5 见 6.2.3.2
4 密码 2 2 字节 HEX 码
5 功能码 1 1 字节 HEX 码,定义见附录 B
6 报文上下行标识及长度 2 见下
7 报文起始符 1 STX
8 报文正文 不定长 —
9 报文结束符 1 ETX、ETB
10 校验码 2 2 字节 HEX

换算规律很整齐:1 个字节 HEX 对应 2 个 ASCII 字符。中心站地址 1→2、遥测站地址 5→10、密码 2→4、功能码 1→2、报文上下行标识及长度 2→4、校验码 2→4。

6.3 "报文上下行标识及长度"怎么拆

这个 2 字节字段是最容易解析错的,标准给的拆法是:

  • 高 4 位作上下行标识:0000 表示上行,1000 表示下行;
  • 其余 12 位表示报文正文长度,即报文起始符之后、报文结束符之前的报文正文字节数,允许长度 0001~4095。

ASCII 编码下这个字段被拆成 4 个 ASCII 字符,其中第 1 个字符是上下行标识(0 表示上行、8 表示下行),其余 3 个字符是正文长度。

也就是说,方向位是长度字段的一部分,它不是独立字段——解析时如果直接把这 2 个字节当长度用,长度会平白多出 0x8000。

6.4 两套编码的语义差异

除了字节数,两套编码在数据处理上的要求也不同:

  • ASCII 编码:报文帧结构中人工置数数据和图片数据采用原码传输,其他信息组编码均应采用 ASCII 字符传输;
  • HEX/BCD 编码:报文信息组不管是 HEX、BCD 编码还是 ASCII 字符,均采用原编码传输。

这一点在人工置数与图片报(功能码 35H、36H)上体现最明显。

七、报文正文结构

7.1 基本结构

在 ASCII 或 HEX/BCD 编码下,报文正文结构一致,只是采用相应的编码编制报文。

上行报文正文结构:

序号 编码名称 编码结构 说明
1 流水号 2 字节 HEX 码,范围 1~65535 —
2 发报时间 6 字节 BCD 码,YYMMDDHHmmSS —
3 遥测站地址 地址标识符 + 遥测站地址 根据功能码定义选编
4 遥测站分类码 分类码标识符 + 遥测站分类码 根据功能码定义选编
5 观测时间 观测时间标识符 + 观测时间 根据功能码定义选编
6 要素(或参数)信息组 标识符 1 + 数据 1,标识符 2 + 数据 2,…… 见附录 C 和附录 E

下行报文正文结构:流水号、发报时间、遥测站地址、要素(参数)——其中要素由一组或多组命令参数组成。

7.2 ASCII 编码的正文格式规则

ASCII 编码下,正文信息组由要素(参数)标识符与相应数据构成,标识符在前、数据在后,各要素(参数)标识符、数据之间均用"空格"作为分隔符,即:

要素标识符 空格 数据 空格 要素标识符 空格 数据

两条容易被忽略的补充规定:

  • 流水号及发报时间组后不带空格分隔符;
  • 报文正文最后的 1 个空格不应省略。

第二条是极阴的坑:报文末尾那个看似多余的空格,是格式的一部分。很多终端在拼接正文时做了 trim,结果中心站按空格分割元素时少了一项。

7.3 各类数据的编码规则

  • 要素标识符采用附录 C 规定的"标识符 ASCII 码";
  • 遥测站基本参数、运行参数标识符采用附录 D 中标识符引导符并转换为 ASCII 码;
  • 数据采用 HEX 码、整型数或十进制浮点数;
  • 非字符型数据(图片数据除外)应转换为 ASCII 字符传输。

7.4 流水号规则

流水号表示发送报文的顺序,规则较为精细:

  • 上行报文流水号在 01~65535 之间循环;
  • 确认帧下行报文的流水号与上行报文相同;
  • 由中心站发起的下行报文流水号为 0;
  • 重发报文使用原报文流水号;
  • 报文正文分包传输时只有第 1 个包有流水号。

最后两条组合起来,直接影响服务端的幂等设计:确认帧和重发帧会复用同一个流水号,因此 流水号单独不能作为唯一键。实践中更稳妥的幂等键是 (遥测站地址, 发报时间, 功能码, 流水号) 的组合。

7.5 发报时间

发报时间表示发送报文的时间,在发送报文时取实时钟,由年、月、日、时、分、秒组成,编码格式为 YYMMDDHHmmSS:

  • YY 表示年份,2 位数字,取值 00~99;
  • MM 表示月份,2 位数字,取值 01~12;
  • DD 表示日期,2 位数字,取值 01~31;
  • HH 表示小时,2 位数字,取值 00~23;
  • mm 表示分钟,2 位数字,取值 00~59;
  • SS 表示秒,2 位数字,取值 00~59。

年份是 2 位——这决定了系统的时间窗口是 2000~2099。做历史数据入库时要注意两位年份的世纪补全逻辑。

八、功能码体系

功能码定义见附录 B,按方向天然分成三段:

功能码 应用功能描述 说明
00H~2EH 保留 扩展功能码
2FH 链路维持报 遥测站定时向中心站发送链路维持信息
30H 测试报 报送实时数据
31H 均匀时段水文信息报 报送等时间间隔数据
32H 遥测站定时报 报送由时间触发的实时数据
33H 遥测站加报报 报送由时间或事件触发的加报实时数据
34H 遥测站小时报 报送以小时为单位的历史数据和实时数据
35H 遥测站人工置数报 报送人工置数
36H 遥测站图片报或中心站查询遥测站图片采集信息 查询/报送 JPG 图片信息
37H 中心站查询遥测站实时数据 —
38H 中心站查询遥测站时段数据 以小时为单位查询历史数据
39H 中心站查询遥测站人工置数 —
3AH 中心站查询遥测站指定要素数据 —
3BH~3FH 保留 扩展功能码
40H 中心站修改遥测站基本配置表 遥测站基本配置
41H 中心站读取遥测站基本配置表/遥测站自报基本配置表 —
42H 中心站修改遥测站运行参数配置表 遥测站运行参数配置
43H 中心站读取遥测站运行参数配置表/遥测站自报运行参数配置表 —
44H 查询水泵电机实时工作数据 —
45H 查询遥测终端软件版本 —
46H 查询遥测站状态和报警信息 —
47H 初始化固态存储数据 应与标识符配合使用以提高安全性
48H 恢复终端出厂设置 应与标识符配合使用以提高安全性
49H 修改密码 —
4AH 设置遥测站时钟 —
4BH 设置遥测终端 IC 卡状态 —
4CH 控制水泵开关命令/水泵状态信息自报 —
4DH 控制阀门开关命令/阀门状态信息自报 —
4EH 控制闸门开关命令/闸门状态信息自报 —
4FH 水量定值控制命令 —
50H 中心站查询遥测站事件记录 —
51H 中心站查询遥测站时钟 —
52H~DFH 保留 扩展功能码
E0H~FFH 用户自定义扩展区 —

分段的规律值得记一下:3X 段是遥测站"说话"(自报、上报),4X 段是中心站"下命令"(查询、配置、控制、校时),5X 段仍以下行查询为主。47H、48H 这两条危险命令,标准专门要求"应与标识符配合使用以提高安全性"——意思是执行前要有二次确认参数,不能一条命令就把设备清空或恢复出厂。

九、要素标识符与分类报文格式

9.1 标识符引导符体系

要素标识符不是裸的 ASCII 字符串,而是"引导符(1 字节 HEX)+ 标识符 ASCII 码"的组合。附录 C 的汇总表节选:

引导符 标识符 ASCII 码 编码要素 最大和单位
F0H TT 观测时间引导符 —
F1H ST 测站编码引导符 —
F2H RGZS 人工置数 —
F3H PIC 图片信息 KB
F4H DRP 1h 内每 5min 时段雨量 0.1mm
F5H DRZ1 1h 内 5min 间隔相对水位 1 0.01m
F6H~FCH DRZ2~DRZ8 1h 内 5min 间隔相对水位 2~8 0.01m
FDH DATA 流速批量数据传输 m³
01H AC 断面面积 —
02H AI 瞬时气温 ℃
03H C 瞬时水温 ℃
04H DRxnn 时间步长码 min
05H DT 时段长、降水、引排水、抽水历时 h, min
06H ED 日蒸发量 mm
07H EJ 当前蒸发 mm
08H FL 气压 百帕
09H GH 闸坝、水库闸门开启高度 m
0AH GN 输水设备、闸门(组)编号 —
0BH GS 输水设备类别 —
0CH GT 水库、闸坝闸门开启孔数 孔
0DH GTP 地温 ℃
0EH H 地下水瞬时埋深 m
0FH HW 波浪高度 m
10H M10 10cm 处土壤含水量 %
11H M20 20cm 处土壤含水量 %

两个细节值得注意:

  • DRZ1~DRZ8 是"同一个要素的多组数据":1h 内 5min 间隔相对水位共有 12 个时段,每个水位要素占 24 字节 HEX(每组 2 字节 HEX,分辨率 0.01m)。对河道站表示河道水位,对闸坝(泵)站分别表示闸(站)上水位或闸(站)下水位。
  • F4H DRP 用 12 字节 HEX 编码 1h 内 12 组 5min 雨量,每组 1 字节,最大值 25.4mm,数据中不含小数点,FFH 表示非法数据。用 FFH 做哨兵值是这类定长批量编码的通用做法,解析时必须先判 FFH 再换算。

9.2 分类报文格式:以降水量为例

附录 E 按站类/报文类型给出了每类报文的完整编码格式,表 E.2 是降水量编码格式,共 13 项:

序号 编码名称 编码结构 说明
1 流水号 2 字节 HEX 码,范围 1~65535 —
2 发报时间 6 字节 BCD 码,YYMMDDHHmmSS —
3 遥测站地址 地址标识符 + 遥测站地址 编码规则见 6.2.3.2
4 遥测站分类码 降水类 —
5 观测时间 观测时间标识符 + 观测时间 5 字节 BCD 码,YYMMDDHHmm
6 降水量 降水量标识符 + 降水量 十进制浮点数,小数点后保留 1 位;可同时编排多组
7 降雨历时 降雨历时标识符 + 降雨历时 HH.mm;暴雨加报时选编
8 降水量累计值 降水量累计值标识符 + 降水量累计值 编码中有降水量时
9 蒸发量 蒸发量标识符 + 蒸发量 选编
10 风向 风向标识符 + 风向 1~16;选编
11 风速 风速标识符 + 风速 选编
12 其他信息 要素标识符 + 要素值 选编
13 电源电压 电源电压标识符 + 遥测站工作电压 十进制浮点数,小数点后保留 2 位;通常报蓄电池电压

注意观测时间在这里是 5 字节 BCD(YYMMDDHHmm),没有秒,而发报时间是 6 字节带秒——两个时间字段精度不同,别搞混。

河道水文信息(附录 E.2)则可包括降水量、蒸发量、水位、流量、波浪高度、水温、风速、风向、气温、气压等,并规定:

  • 水位应以 m 计,宜记至 2 位小数,特殊要求可记至 3 位;
  • 流量以 m³/s 计,最多记至 3 位小数;
  • 流速以 m/s 计,最多记至 2 位小数;
  • 波浪高度以 m 计,最多记至 2 位小数;
  • 水温以 ℃ 计,记至 1 位小数。

精度约定必须在对接文档里写死,否则同一水位值在不同厂商设备上会出现 0.01m 与 0.001m 混报。

十、CRC 校验的实现

标准对校验码的规定是:校验码为校验码前所有字节的 CRC 校验,生成多项式为 X¹⁶+X¹¹+X²+1,高位字节在前、低位字节在后。

生成多项式 X¹⁶+X¹¹+X²+1 展开为二进制是 1 0000 1000 0000 0101,即 0x8005。

Java 参考实现:

/** SL 651 报文校验码计算:校验码之前的所有字节,高位字节在前 */
public static int crc16(byte[] frame, int offset, int length) {
    int crc = 0x0000;
    for (int i = offset; i < offset + length; i++) {
        crc ^= (frame[i] & 0xFF) << 8;
        for (int b = 0; b < 8; b++) {
            if ((crc & 0x8000) != 0) {
                crc = (crc << 1) ^ 0x8005;
            } else {
                crc <<= 1;
            }
            crc &= 0xFFFF;
        }
    }
    return crc;
}

/** 组帧:校验码高位字节在前、低位字节在后 */
static void appendCrc(java.io.ByteArrayOutputStream out, byte[] frame) {
    int c = crc16(frame, 0, frame.length);
    out.write((c >> 8) & 0xFF);
    out.write(c & 0xFF);
}

需要提醒的是:标准只给出了生成多项式,没有规定初值、是否位反转以及是否做结果异或。上例采用工程中常见的初值 0x0000、不做反转、不做结果异或。这个约定必须与对接方书面确认——不同初值算出来的 CRC 完全不同,现场"报文看着对但中心站一直 NAK"十有八九就是这里没对齐。

十一、标准里的一处内部矛盾

翻到 6.5 节时会发现一处对不上的地方,值得记一下。

"报文上下行标识及长度"这个字段,在表 20 中定义为 2 字节 HEX 码,高 4 位为上下行标识、其余 12 位为报文正文长度,允许长度 0001~4095;表 16 对 ASCII 编码的表述一致;表 23(HEX/BCD M3 下行)也明确写"见表 20 说明"。

但表 22(HEX/BCD M3 上行)同一行的说明写的是"允许长度为 0001H~FFFFH"。

FFFFH = 65535 已经超出 12 位所能表达的范围,且与表 20、表 16、表 23 三处定义都不一致。该字段只有 2 个字节,扣掉高 4 位方向标识后只剩 12 位,上限只能是 4095(0FFFH)。所以表 22 的 FFFFH 应为笔误,实现时应以 4095 为界。

这个坑的代价不低:如果按 FFFFH 去设计缓冲区或做长度校验,遇到异常报文时可能被诱导分配超大缓冲区,或者放过本该判定为非法的长度值。

十二、工程落地要点

把上面这些规定收拢成一份 checklist:

  1. 上下行报头的两个地址顺序相反,解析器不能复用同一段偏移逻辑;
  2. ETB/ETX 与 ACK/ESC/EOT 的语义决定链路是否释放,状态机要按此设计,不能用"收到报文即断开"的简化实现;
  3. ASCII 编码正文末尾的空格不能省略,拼接正文时不要 trim;
  4. "报文上下行标识及长度"的高 4 位是方向位,不能直接当长度使用;正文长度上限 4095,不是 65535;
  5. 超时重发 2 次、连续 3 次超时退出链路,超时阈值需按信道特性实测标定,标准未给具体值;
  6. 确认帧与重发帧复用原流水号,幂等键建议用 (遥测站地址, 发报时间, 功能码, 流水号);
  7. 分包传输只有第 1 个包带流水号,服务端重组时要按"包总数及序号"补齐顺序,不能依赖流水号排序;
  8. 发报时间为 2 位年份,注意世纪的补全与时间窗口(2000~2099);
  9. 观测时间与发报时间精度不同(前者 5 字节到分、后者 6 字节到秒),落库字段要分开;
  10. DRP、DRZ 这类定长批量编码用 FFH 表示非法数据,解析时先判哨兵值再换算,且注意"数据中不含小数点";
  11. CRC 的初值、字节序必须与对接方书面确认,并注意 SL 651 层与 Modbus 层的校验字节序相反;
  12. 密码入网后必须修改,47H/48H 这类高风险命令要按标准要求配合标识符做二次确认。

十三、小结

SL 651-2014 的结构其实很清晰:一层是传感器到 RTU 的 Modbus/SDI-12,一层是 RTU 到中心站的报文传输;报文层用统一的字节帧框架,通过"两种字符编码 + 一套功能码 + 一套要素标识符"覆盖了从雨量、水位、流量到闸门控制、图片传输的全部业务。

真正花时间的不是读懂帧结构,而是把这些"魔鬼细节"对齐:地址顺序、方向位、末尾空格、流水号复用、CRC 初值、两类时间精度、FFH 哨兵值。这些点在标准里都有明文规定,但散落在不同章节和附录里,只有在现场被 NAK 过几轮之后才会真正记住。


关于作者

长期从事水利、水务及生态环境领域的信息化系统研发,主要技术栈为 Java / Spring Boot,熟悉水文监测数据的采集、传输、存储与展示全链路。

在通信规约方面,熟练使用 SL 651-2014《水文监测数据通信规约》 与 HJ 212《污染物在线监控(监测)系统数据传输标准》,具备遥测终端接入、报文解析、分包重组、CRC 校验、指令下发与远程配置的完整落地经验,对 SL 502 站码体系、GB 2260 行政区划编码、Modbus-RTU / SDI-12 传感器接入亦有实践。

如果你正在做水文测站的数据接入、中心站平台建设,或者被某个厂商的报文格式卡住,欢迎交流。


评论