Skip to content

SL651 驱动

dc3-driver-sl651 把 SL651-2014 水文遥测站接入 IoT DC3:它监听一个 TCP 端口,被动接收远端测站主动上报的遥测报文,按位号配置取出报文体里指定位置的要素值并转成位号值 。读完本页,你能理解它和轮询型驱动的差别,正确填写驱动 / 位号属性,并排查"收到报文却没有位号值"这类典型问题。

协议背景

SL651-2014 是中华人民共和国水利行业标准《水文监测数据通信规约》,用于雨量站、水位站、流量站等遥测终端(RTU)与中心站之间的数据通信。它的典型用途是流域水情、城市内涝、水库大坝、灌区量水等场景的远程遥测——测站分散在野外,靠 GPRS / 4G / 北斗等链路把定时采集或事件触发的水文要素回传到中心。

和 Modbus 那种"主站主动去读从站"的现场总线不同,SL651 是服务端协议:分散在各处的测站按自己的时段(整点、加报、报警等),把采集到的遥测数据 主动推送给一个中心服务器。本驱动就是那个中心服务器——它启动一个 SL651 TCP 服务监听端口,等测站连上来上报,解析报文体里的遥测要素,用报文头里的测站地址匹配到对应设备 ,再把指定要素转成位号值。

在物联网四层架构里,SL651 属于网络层 :它定义了测站终端如何把感知层采集的数据,经广域链路传输汇聚到平台。它不规定传感器怎么测(感知层),也不规定平台怎么存储与分析(应用层),只约定报文帧结构、功能码、要素编码与上下行交互。要理解它在整体协议谱系里的位置、以及" 服务端被动收报文"这种通信模型与轮询模型的取舍,见 物联网网络层章节

这是监听型驱动,不是轮询型

因为数据是测站异步、主动送上来的,SDK 的 read / write 不参与采集——按设计 read 返回 nullwrite 返回 false 。定时读取被关闭(schedule.read.enable: false),驱动只保留一个内部 schedule.custom cron 和设备健康检查;真正的采集由测站上报触发。

两个核心名词

  • 测站地址(station address):SL651 报文头里标识上报方的地址。驱动取报文头 getRemoteStationAddress() 的字节并转成十六进制大写串,用来和设备的 deviceCodedeviceName 做匹配(不区分大小写)。
  • 遥测要素(element):一份上报报文体里按顺序排列的一组测量值(如水位、雨量、电压……)。驱动把所有报文体的 getBodyElements() 汇成一个有序列表,位号靠下标 index 从中取一个。

属性配置

接入一台 SL651 测站,需要在两个层面填属性:驱动属性driver-attribute,决定服务端怎么监听)与位号属性point-attribute,决定从报文体取哪个要素)。这些属性都来自驱动的 application.yml,对应代码里的 dc3.driver.sl651.port / dc3.driver.sl651.pwd 配置项与位号配置 index。属性的取值在设备 实例上填写,三层来历见属性与配置

驱动属性(设备级 driver-attribute

port 决定整个驱动进程在哪个 TCP 端口上启动 SL651 服务端;pwd 是创建 SL651Server 时传入的鉴权密码,用于测站接入时的口令校验。两者都有默认值,未填时按默认走。

属性code类型默认值说明
Listen PortportINT5001SL651 服务端监听的 TCP 端口
Auth PasswordpwdSTRING0000远端测站接入鉴权密码

端口是驱动级的,被同进程内所有测站共用

port 决定整个驱动进程监听哪个 TCP 端口,所有上报到这个端口的测站共用同一个服务端实例。不同测站靠测站地址(即设备的 deviceCode / deviceName)区分,不是靠端口。元数据变更(设备新增 / 更新)会触发 restartServer() 重启服务端,删除设备会 stopServer() 停掉服务端。

位号属性(point-attribute

每个采集位号上只需填一个属性——它在报文体要素列表里的下标。驱动收到某测站的上报后,会把所有报文体的要素按顺序汇成一个列表;位号的 index 就是从这个列表里取第几个值。

属性code类型默认值说明
Element IndexindexINT0报文体要素列表的下标(从 0 开始)

index=0 取第一个要素,index=1 取第二个,以此类推。下标越界(index < 0index >= elements.size())的位号本轮被跳过,不会报错。 validatePoint() 会校验 index 必填,缺失时该位号配置不通过。

端到端落地链路

SL651 报文 (TCP)onMessage按 index 取要素遥测测站 RTU站址 12345678SL651Serverport 5001handleSl651Message解析站址 + 要素列表设备 Device按站址匹配 deviceCode/Name位号值 PointValue按 index 取要素pointValueSender

驱动启动时 startServer() 通过反射构造 SL651Server,注册一个 ISl651MessageListener。每当测站上报,onMessage 回调把报文头的测站地址(十六进制串)与报文体的要素列表交给 forwardTelemetry():遍历本驱动名下的设备,站址匹配上的设备再遍历其位号,按 index 取值组装成 PointValue,批量交给 driverSenderService.pointValueSender() 发往平台。

故障排查

  • 收到报文却没有位号值:最常见原因是站址对不上设备编码。驱动用报文头的测站地址(十六进制大写串)匹配设备的 deviceCodedeviceName(不区分大小写),对不上就静默丢弃。先从驱动日志确认实际上报的 stationAddr(DEBUG 级 Driver SL651 message received 会打印),再照抄到 deviceCode
  • 位号值取错了量index 是要素列表下标,从 0 开始,顺序由测站配置决定,不是 SL651 标识符编码、也不是寄存器地址。对照测站实际上报的要素顺序逐个核对 index,别凭量纲猜。
  • 测站连不上 / 鉴权失败:确认设备上填的 port 与测站实际目标端口一致、网络可达;pwd 要与测站配置的接入口令一致(默认 0000)。改 port 会触发服务端重启,短时间内会断连。
  • 驱动日志出现 sl651ApiMissing 警告:说明运行时缺少 iot-communication 的 SL651 类,服务端不会启动( Driver SL651 server unavailable)。正常打包会带上该依赖;若自定义裁剪了依赖需补回。
  • 设备一直离线:设备健康检查 cron 0/15 * * * * ?、租约超时 45 秒。测站若上报间隔大于 45 秒(如整点报、长间隔加报),在两次上报之间会被判为离线属正常现象;在线判定见设备
  • 配错写命令不生效:本驱动 write 按设计返回 false,没有 command-attribute ,给位号配写命令不会下发。远程控制测站请走测站自身的下行通道,不在本驱动职责内。

在 IoT DC3 中如何落地

  • dc3.driver.codeSl651Driver(驱动名 SL651 Hydrological Telemetry Driver,类型 DRIVER_CLIENT )。这是稳定的路由标识,不要随意改。
  • 读 / 写 / 订阅能力:仅订阅 / 上报read 返回 nullwrite 返回 false ,定时读取关闭;采集完全由测站上报触发。与驱动能力矩阵一致:读 —、写 —、订阅 ✓。
  • 采集与健康:被动监听无主动读取周期;驱动另有内部 schedule.custom cron 0/5 * * * * ?schedule() 当前为空实现,不参与采集)。设备健康检查 cron 0/15 * * * * ?、租约超时 45 秒

设备编码必须等于测站地址,否则数据被丢弃

驱动用上报报文头里的**测站地址(十六进制大写串)**匹配设备的 deviceCodedeviceName (不区分大小写)。两者对不上,这份上报被静默丢弃——你会看到驱动在收报文,却没有任何位号值。接入前先确认测站实际上报的地址,并照抄到 deviceCode

index 是报文体要素的"第几个",不是寄存器地址

index 是驱动解析出的要素列表下标,从 0 开始,与测站报文里要素的排列顺序一一对应。它不是 SL651 的标识符编码,也不是任何寄存器地址。要素顺序由测站配置决定,接入前需对照测站的上报内容确认每个 index 对应哪个量。

实现状态:可用(服务端依赖缺失时优雅降级)

SL651 服务端基于 iot-communication 库的 SL651Server 反射调用,报文解析与转发链路完整,是可用驱动。若运行时缺少该库的 SL651 类,startServer()sl651ApiMissing 警告并跳过启动,不影响进程其余部分;正常打包已包含该依赖。

最小接入示例

把一个测站地址为 12345678、上报到本机 5001 端口的水位站接进来:

  1. SL651 Hydrological Telemetry Driver 创建设备设备编码 deviceCode12345678(要和测站上报的地址一致),驱动属性填 port=5001pwd=0000
  2. 给设备绑定的模板加一个水位位号(按上报要素的实际类型设 pointTypeFlagREAD_ONLY),位号属性填 index=0(取报文体第一个要素)。
  3. 启动驱动,让测站把数据推上来;测站一上报,匹配上的位号就会出现在位号值里。

延伸阅读

基于 AGPL-3.0 协议发布