mbus-client
mbus-client is a helper crate for modbus-rs.
It provides the client-side Modbus request/response engine, built on top of shared
protocol and transport abstractions from mbus-core.
If you want a single top-level entry point, use modbus-rs.
If you want direct access to client orchestration and callbacks, use mbus-client.
Helper Crate Role
mbus-client is responsible for client workflow, not transport implementation:
- Builds Modbus requests and tracks outstanding transactions.
- Polls transport for responses and dispatches parsed callbacks.
- Handles retries and timeout-based failure paths.
- Exposes feature-gated service modules by function group.
Transport implementations are provided by helper crates such as:
mbus-networkmbus-serial
What Is Included
services::ClientServices: the central client orchestrator.services::SerialClientServices: convenience alias for serial clients (N = 1).- Feature-gated service modules:
services::coilservices::registerservices::discrete_inputservices::fifo_queueservices::file_recordservices::diagnostic
appcallback traits:RequestErrorNotifier- response traits for each function group
Retry Backoff and Jitter
Retries are poll-driven and timestamp-scheduled. The client never sleeps or blocks.
- Timeout detection happens inside
ClientServices::poll(). - Retries are scheduled using
BackoffStrategyfrommodbus-rs. - Optional jitter is applied using
JitterStrategy. - Randomness for jitter is application-provided via
retry_random_fnon config.
Example (TCP with exponential backoff + percentage jitter):
use ;
let mut tcp = new?;
tcp.retry_attempts = 3;
tcp.retry_backoff_strategy = Exponential ;
tcp.retry_jitter_strategy = Percentage ;
tcp.retry_random_fn = Some;
If retry_random_fn is None, jitter strategies gracefully fall back to non-jittered delays.
Reconnect and Connection State
ClientServices now exposes explicit connection management helpers:
client.is_connected()to query transport connection state.client.reconnect()to re-establish transport using the current config.
Reconnect behavior:
- Pending in-flight requests are failed immediately with
MbusError::ConnectionLost. - Internal receive buffers and timeout checkpoints are cleared.
disconnect()is attempted, thenconnect(&config)is called.- Requests are not auto re-sent; the application should requeue explicitly.
This behavior is suitable for long-running daemons and embedded systems that must recover from temporary link loss.
App Handler Access
ClientServices keeps the application callback handler encapsulated.
- Use
client.app()for immutable inspection. - There is no public replacement/mutable handler API.
This preserves callback identity for in-flight requests and avoids accidental handler swaps during active transactions.
Serial Queue Constraint
For serial transports, Modbus is half-duplex and only one request may be in flight.
- Runtime-safe path:
ClientServices::new(...)validates serialN == 1. - Compile-time-safe path:
ClientServices::new_serial(...)enforcesN == 1. - Recommended type alias:
SerialClientServices<TRANSPORT, APP>.
Feature Flags
This crate uses selective compilation so you only build required protocol services.
Available features:
coilsregistersdiscrete-inputsfifofile-recorddiagnosticsserial-ascii(forwards tombus-core/serial-asciito enable ASCII-sized ADU buffers)logging(enables low-priority internal state-machine diagnostics via thelogfacade)
Default behavior:
defaultenables all service features above.
Feature forwarding:
- Each feature forwards to the equivalent model feature in
mbus-core.
Example (minimal feature set):
[]
= { = "0.4.0", = false, = ["coils"] }
Logging
mbus-client can emit low-priority internal diagnostics through the log facade when the
logging feature is enabled.
These logs are intentionally limited to debug and trace so applications can filter them
without treating normal control-flow events as warnings or errors.
Examples of logged events:
- frame parse/resynchronization
- response dispatch matching
- timeout scans and retry scheduling
- retry send failures
- pending-request flush during connection loss or reconnect
Typical filtering example:
RUST_LOG=mbus_client=trace
Usage Pattern
Typical flow:
- Implement required callback traits in your app type.
- Provide a
Transportimplementation (custom,mbus-network, ormbus-serial). - Build a
ModbusConfig. - Construct
ClientServices. - Issue requests.
- Call
poll()periodically to process responses and timeouts.
Minimal Example
use ;
use ;
use Vec;
;
;
Feature-Scoped Access Style
ClientServices now supports feature facades so request APIs can be grouped by domain:
client.coils()client.registers()client.discrete_inputs()client.diagnostic()client.fifo()client.file_records()
For grouped request submission in a single scoped borrow, use batch helpers:
client.with_coils(...)client.with_registers(...)client.with_discrete_inputs(...)client.with_diagnostic(...)client.with_fifo(...)client.with_file_records(...)
Build Examples
From workspace root:
# default services
# only coils service
# registers + discrete inputs only
Notes
- This crate is
no_stdfriendly and usesheaplessinternally. - Service and callback traits are conditionally compiled by feature flags.
- Use exact feature names with hyphens:
discrete-inputsfile-record
License
Copyright (C) 2025 Raghava Challari
This project is currently licensed under GNU GPL v3.0. See LICENSE for details.
Disclaimer
This is an independent Rust implementation of the Modbus specification and is not affiliated with the Modbus Organization.
Contact
For questions or support:
- Name: Raghava Ch
- Email: ch.raghava44@gmail.com