Skip to content

SL651 Driver

dc3-driver-sl651 connects SL651-2014 hydrological telemetry stations to IoT DC3: it listens on a TCP port, passively receives telemetry reports pushed by remote stations, and turns the element at a configured position in the report body into a PointValue. After reading this page you will understand how it differs from a polling driver, how to fill in the driver and point attributes correctly, and how to troubleshoot the classic " reports arrive but no point values" problem.

Protocol background

SL651-2014 is the PRC water-conservancy industry standard Hydrological Monitoring Data Communication Protocol, used for data communication between telemetry terminals (RTUs) — rain gauges, water-level stations, flow stations — and a central station. Its typical use is remote telemetry for basin hydrology, urban waterlogging, reservoirs and dams, and irrigation metering: stations are scattered in the field and use links such as GPRS / 4G / BeiDou to send scheduled or event-triggered hydrological elements back to the center.

Unlike field buses such as Modbus, where the master actively reads slaves, SL651 is a server-side protocol: telemetry stations scattered in the field push their collected data to a central server on their own schedule (on the hour, supplementary reports, alarms, and so on). This driver is that central server — it starts an SL651 TCP server on a listen port, waits for stations to connect and report, parses the telemetry elements out of the report body, matches the station address in the report header to a Device, and forwards the configured element as a point value.

In the four-layer IoT architecture, SL651 sits at the network layer: it defines how station terminals transmit and aggregate sensing-layer data over wide-area links to the platform. It does not specify how sensors measure (perception layer) or how the platform stores and analyzes (application layer); it only governs frame structure, function codes, element encoding, and uplink/downlink exchange. To see where it sits in the protocol spectrum and the trade-offs of " server passively receiving reports" versus a polling model, see the IoT network-layer chapter.

This is a listener driver, not a polling one

Because data arrives asynchronously and unsolicited from the stations, the SDK read / write methods do not participate in collection — by design read returns null and write returns false. Scheduled reads are disabled ( schedule.read.enable: false); the driver keeps only an internal schedule.custom cron and the device health check, and the real collection is triggered by station reports.

Two core terms

  • Station address: the address in the SL651 report header that identifies the sender. The driver takes the bytes from getRemoteStationAddress(), converts them to an uppercase hex string, and matches them against the device's deviceCode or deviceName (case-insensitive).
  • Telemetry element: an ordered list of measured values in one report body (water level, rainfall, voltage, …). The driver collects every report body's getBodyElements() into one ordered list, and a Point picks one of them by its index index.

Attribute configuration

Onboarding an SL651 station involves attributes at two levels: driver attributes (driver-attribute, which decide how the server listens) and point attributes (point-attribute, which decide which element to take from the report body). All come from the driver's application.yml, mapping to the dc3.driver.sl651.port / dc3.driver.sl651.pwd config keys and the point config index. The values are filled in on the Device instance; for the three-layer origin of attributes see Attribute and Config.

Driver attributes (device-level driver-attribute)

port decides which TCP port the whole driver process starts the SL651 server on; pwd is the authentication password passed when constructing SL651Server, used for the station's access credential check. Both have defaults and fall back to them when left blank.

AttributecodeTypeDefaultDescription
Listen PortportINT5001TCP port the SL651 server listens on
Auth PasswordpwdSTRING0000Remote station authentication password

The port is driver-level and shared by every station in the process

port decides which TCP port the whole driver process listens on; every station reporting to that port shares one server instance. Different stations are distinguished by their station address (i.e. the device's deviceCode / deviceName), not by port. A metadata change (device add / update) triggers restartServer(), and deleting a device calls stopServer().

Point attributes (point-attribute)

Each collected Point needs just one attribute — its index into the report body's element list. When a report arrives from a station, the driver collects all report-body elements into an ordered list in order; the Point's index selects which one to take.

AttributecodeTypeDefaultDescription
Element IndexindexINT0Zero-based index into the telemetry body element list

index=0 takes the first element, index=1 the second, and so on. Points whose index is out of range (index < 0 or index >= elements.size()) are skipped for that round without error. validatePoint() requires index to be present; the point config fails validation if it is missing.

End-to-end pipeline

SL651 message (TCP)onMessageelement by indexTelemetry RTUstation addr 12345678SL651Serverport 5001handleSl651Messageparse station + elementsDevicematch deviceCode/Name by stationPointValueelement by indexpointValueSender

At startup startServer() constructs SL651Server via reflection and registers an ISl651MessageListener. Whenever a station reports, the onMessage callback hands the report header's station address (hex string) and the report body's element list to forwardTelemetry(): it iterates the devices under this driver, and for each device whose address matches, iterates its points, takes the value by index, assembles PointValue objects, and forwards them in a batch via driverSenderService.pointValueSender().

Troubleshooting

  • Reports arrive but no point values: the most common cause is a station address that does not match the device code. The driver matches the report header's station address (uppercase hex string) against the device's deviceCode or deviceName (case-insensitive); a mismatch is silently dropped. First confirm the actual stationAddr reported from the driver log (the DEBUG-level Driver SL651 message received prints it), then copy it verbatim into deviceCode.
  • A point reads the wrong value: index is a zero-based element-list index whose order is determined by the station configuration; it is not an SL651 identifier code, nor a register address. Verify each index against the actual element order the station reports — do not guess by unit.
  • Station cannot connect / authentication fails: confirm the port on the device matches the station's target port and the network is reachable; pwd must equal the station's configured access credential (default 0000). Changing port triggers a server restart and a brief disconnect.
  • sl651ApiMissing warning in the driver log: the runtime is missing the iot-communication SL651 classes, so the server does not start (Driver SL651 server unavailable). A normal build bundles the dependency; if you trimmed dependencies, add it back.
  • Device stays offline: the device health check cron is 0/15 * * * * ? with a 45 second lease timeout. If the station's reporting interval exceeds 45 seconds (e.g. hourly or long-interval supplementary reports), being judged offline between two reports is expected; see Device for the online determination.
  • A misconfigured write command has no effect: this driver's write returns false by design, there is no command-attribute, and a write command on a Point is never dispatched. For remote control of a station, use the station's own downlink channel; it is outside this driver's scope.

How it lands in IoT DC3

  • dc3.driver.code: Sl651Driver (driver name SL651 Hydrological Telemetry Driver, type DRIVER_CLIENT). This is a stable routing identifier — do not change it casually.
  • Read / write / subscribe capability: subscribe / report only. read returns null, write returns false, scheduled reads are off, and collection is driven entirely by station reports. This matches the driver capability matrix: read —, write —, subscribe ✓.
  • Collection and health: passive listening with no active read cycle; the driver also has an internal schedule.custom cron 0/5 * * * * ? (schedule() is currently a no-op and does not collect). The device health check cron is 0/15 * * * * ? with a 45 second lease timeout.

The device code must equal the station address, or the data is dropped

The driver matches the station address (uppercase hex string) in the report header against the device's deviceCode or deviceName (case-insensitive). If they do not match, the report is silently dropped — you will see the driver receiving reports yet no point values. Confirm the address the station actually reports, and copy it verbatim into deviceCode before onboarding.

index is the "Nth element" of the body, not a register address

index is the element-list index the driver parses out, zero-based, matching the order of elements in the station's report one-to-one. It is not an SL651 identifier code, nor any register address. The element order is determined by the station configuration, so confirm which value each index maps to against the station's report content before onboarding.

Implementation status: available (graceful degradation when the server dependency is missing)

The SL651 server is invoked via reflection on the iot-communication library's SL651Server, and the report parsing and forwarding pipeline is complete, so this is an available driver. If the runtime lacks the library's SL651 classes, startServer() logs an sl651ApiMissing warning and skips startup without affecting the rest of the process; a normal build already bundles the dependency.

Minimal onboarding example

Onboard a water-level station with station address 12345678 reporting to local port 5001:

  1. Create a Device using SL651 Hydrological Telemetry Driver, and set the device code deviceCode to 12345678 (it must match the address the station reports), with driver attributes port=5001 and pwd=0000.
  2. Add a water-level Point to the Profile bound to the device (set pointTypeFlag to match the reported element's actual type, READ_ONLY), and set the point attribute index=0 (take the first element of the report body).
  3. Start the driver and let the station push data; as soon as the station reports, the matched Point shows up in PointValue.

Further reading

Released under the AGPL-3.0 License