SL651 驱动
dc3-driver-sl651 把 SL651-2014 水文遥测站接入 IoT DC3:它监听一个 TCP 端口,被动接收远端测站主动上报的遥测报文,按位号配置取出报文体里指定位置的要素值并转成位号值 。读完本页,你能理解它和轮询型驱动的差别,正确填写驱动 / 位号属性,并排查"收到报文却没有位号值"这类典型问题。
协议背景
SL651-2014 是中华人民共和国水利行业标准《水文监测数据通信规约》,用于雨量站、水位站、流量站等遥测终端(RTU)与中心站之间的数据通信。它的典型用途是流域水情、城市内涝、水库大坝、灌区量水等场景的远程遥测——测站分散在野外,靠 GPRS / 4G / 北斗等链路把定时采集或事件触发的水文要素回传到中心。
和 Modbus 那种"主站主动去读从站"的现场总线不同,SL651 是服务端协议:分散在各处的测站按自己的时段(整点、加报、报警等),把采集到的遥测数据 主动推送给一个中心服务器。本驱动就是那个中心服务器——它启动一个 SL651 TCP 服务监听端口,等测站连上来上报,解析报文体里的遥测要素,用报文头里的测站地址匹配到对应设备 ,再把指定要素转成位号值。
在物联网四层架构里,SL651 属于网络层 :它定义了测站终端如何把感知层采集的数据,经广域链路传输汇聚到平台。它不规定传感器怎么测(感知层),也不规定平台怎么存储与分析(应用层),只约定报文帧结构、功能码、要素编码与上下行交互。要理解它在整体协议谱系里的位置、以及" 服务端被动收报文"这种通信模型与轮询模型的取舍,见 物联网网络层章节。
这是监听型驱动,不是轮询型
因为数据是测站异步、主动送上来的,SDK 的 read / write 不参与采集——按设计 read 返回 null、write 返回 false 。定时读取被关闭(schedule.read.enable: false),驱动只保留一个内部 schedule.custom cron 和设备健康检查;真正的采集由测站上报触发。
两个核心名词
- 测站地址(station address):SL651 报文头里标识上报方的地址。驱动取报文头
getRemoteStationAddress()的字节并转成十六进制大写串,用来和设备的deviceCode或deviceName做匹配(不区分大小写)。 - 遥测要素(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 Port | port | INT | 5001 | SL651 服务端监听的 TCP 端口 |
| Auth Password | pwd | STRING | 0000 | 远端测站接入鉴权密码 |
端口是驱动级的,被同进程内所有测站共用
port 决定整个驱动进程监听哪个 TCP 端口,所有上报到这个端口的测站共用同一个服务端实例。不同测站靠测站地址(即设备的 deviceCode / deviceName)区分,不是靠端口。元数据变更(设备新增 / 更新)会触发 restartServer() 重启服务端,删除设备会 stopServer() 停掉服务端。
位号属性(point-attribute)
每个采集位号上只需填一个属性——它在报文体要素列表里的下标。驱动收到某测站的上报后,会把所有报文体的要素按顺序汇成一个列表;位号的 index 就是从这个列表里取第几个值。
| 属性 | code | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
| Element Index | index | INT | 0 | 报文体要素列表的下标(从 0 开始) |
index=0 取第一个要素,index=1 取第二个,以此类推。下标越界(index < 0 或 index >= elements.size())的位号本轮被跳过,不会报错。 validatePoint() 会校验 index 必填,缺失时该位号配置不通过。
端到端落地链路
驱动启动时 startServer() 通过反射构造 SL651Server,注册一个 ISl651MessageListener。每当测站上报,onMessage 回调把报文头的测站地址(十六进制串)与报文体的要素列表交给 forwardTelemetry():遍历本驱动名下的设备,站址匹配上的设备再遍历其位号,按 index 取值组装成 PointValue,批量交给 driverSenderService.pointValueSender() 发往平台。
故障排查
- 收到报文却没有位号值:最常见原因是站址对不上设备编码。驱动用报文头的测站地址(十六进制大写串)匹配设备的
deviceCode或deviceName(不区分大小写),对不上就静默丢弃。先从驱动日志确认实际上报的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.code:Sl651Driver(驱动名SL651 Hydrological Telemetry Driver,类型DRIVER_CLIENT)。这是稳定的路由标识,不要随意改。- 读 / 写 / 订阅能力:仅订阅 / 上报。
read返回null、write返回false,定时读取关闭;采集完全由测站上报触发。与驱动能力矩阵一致:读 —、写 —、订阅 ✓。 - 采集与健康:被动监听无主动读取周期;驱动另有内部
schedule.customcron0/5 * * * * ?(schedule()当前为空实现,不参与采集)。设备健康检查 cron0/15 * * * * ?、租约超时45 秒。
设备编码必须等于测站地址,否则数据被丢弃
驱动用上报报文头里的**测站地址(十六进制大写串)**匹配设备的 deviceCode 或 deviceName (不区分大小写)。两者对不上,这份上报被静默丢弃——你会看到驱动在收报文,却没有任何位号值。接入前先确认测站实际上报的地址,并照抄到 deviceCode。
index 是报文体要素的"第几个",不是寄存器地址
index 是驱动解析出的要素列表下标,从 0 开始,与测站报文里要素的排列顺序一一对应。它不是 SL651 的标识符编码,也不是任何寄存器地址。要素顺序由测站配置决定,接入前需对照测站的上报内容确认每个 index 对应哪个量。
实现状态:可用(服务端依赖缺失时优雅降级)
SL651 服务端基于 iot-communication 库的 SL651Server 反射调用,报文解析与转发链路完整,是可用驱动。若运行时缺少该库的 SL651 类,startServer() 记 sl651ApiMissing 警告并跳过启动,不影响进程其余部分;正常打包已包含该依赖。
最小接入示例
把一个测站地址为 12345678、上报到本机 5001 端口的水位站接进来:
- 选
SL651 Hydrological Telemetry Driver创建设备,设备编码deviceCode填12345678(要和测站上报的地址一致),驱动属性填port=5001、pwd=0000。 - 给设备绑定的模板加一个水位位号(按上报要素的实际类型设
pointTypeFlag、READ_ONLY),位号属性填index=0(取报文体第一个要素)。 - 启动驱动,让测站把数据推上来;测站一上报,匹配上的位号就会出现在位号值里。