Skip to main content

Serial RTU server

The library supports serial communication using the RTU transmission mode. Several servers can share one serial line, each answering for its own unit IDs, and a client can broadcast writes to all of them at once.

The library handles RTU framing for clients and servers alike: it derives the frame timing from the baud rate, and after line noise or a partial frame it discards bytes until a valid frame starts, logging a warning, without closing the port.

Creating a server​

First build a DeviceMap for each unit ID to which the server will respond, as for a TCP server. Then use the create_rtu static method of the Server class (spawn_rtu_server_task in Rust). It takes the same serial port path and settings as an RTU client, and a RetryStrategy.

The server opens the port in the background. If the port can't be opened, or fails later, for example when a USB-to-serial adapter is unplugged, the server reopens it, waiting as the RetryStrategy sets.

let handler = SimpleHandler::new(POINT_COUNT).wrap();

// map unit ids to a handler for processing requests
let map = ServerHandlerMap::single(UnitId::new(UNIT_ID), handler.clone());

let server = rodbus::server::spawn_rtu_server_task(
path,
rodbus::SerialSettings::default(),
default_retry_strategy(),
map,
DecodeLevel::new(
AppDecodeLevel::DataHeaders,
FrameDecodeLevel::Nothing,
PhysDecodeLevel::Nothing,
),
)?;

Broadcast​

The server applies a write request sent to the broadcast unit ID (0x00) to every unit in its map, and doesn't reply, so an exception returned by your handler goes nowhere. It ignores any other broadcast, such as a read.

Reserved addresses​

Don't use unit IDs 248 (0xF8) to 255 (0xFF), which the specification reserves. The library processes them like any other unit ID, but logs a warning as a reminder of potential interoperability issues.