Expand description
Commercial library by Step Function I/O
A high-performance implementation of the Modbus protocol using Tokio and Rust’s async/await syntax.
Features
- Panic-free parsing
- Correctness and compliance to the specification
- Built-in logging and protocol decoding
- Automatic connection management with configurable reconnect strategy
- Scalable performance using Tokio’s multi-threaded executor
- TLS is implemented using rustls not openssl
- Model-generated bindings for C, C++, Java, and .NET Core
- Runs on all platforms and operating systems supported by the Tokio runtime:
- Official support for: Windows x64 and Linux x64, AArch64, ARMv7 and ARMv6
- Unofficial support: MacOS, PowerPC, MIPS, FreeBSD, and others
Supported Modes
- TCP, RTU (serial), and Modbus security (TLS) with and without X.509 extension containing the user role.
- Client and server
Function Codes
The client and server examples demonstrate simple
usage of the API.
The following function codes are supported:
- Read Coils (
0x01) - Read Discrete Inputs (
0x02) - Read Holding Registers (
0x03) - Read Input Registers (
0x04) - Write Single Coil (
0x05) - Write Single Register (
0x06) - Write Multiple Coils (
0x0F) - Write Multiple Registers (
0x10)
License
This library is publicly available under a non-commercial / non-production license.
Refer to LICENSE.txt for the terms
of this non-commercial license.
This software is publicly available, but is not “open source”. You must purchase a commercial license to use this software for profit.
Please inquire about commercial licensing on our website:
Cargo Features
Default features can be disabled at compile time:
tls- Build the library with support for TLS (secure Modbus)serial- Build the library with support for Modbus RTU and serial ports
Bindings
Bindings in C, C++, java, and .NET Core are available for this library. See the documentation for more details.
Example Client
A simple client application that periodically polls for some Coils
use rodbus::*;
use rodbus::client::*;
use std::net::SocketAddr;
use std::time::Duration;
use std::str::FromStr;
#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut channel = spawn_tcp_client_task(
HostAddr::ip("127.0.0.1".parse()?, 502),
10,
default_retry_strategy(),
DecodeLevel::default(),
None
);
channel.enable().await?;
let param = RequestParam::new(
UnitId::new(0x02),
Duration::from_secs(1),
);
// try to poll for some coils every 3 seconds
loop {
match channel.read_coils(param, AddressRange::try_from(0, 5).unwrap()).await {
Ok(values) => {
for x in values {
println!("index: {} value: {}", x.index, x.value)
}
}
Err(err) => println!("Error: {:?}", err)
}
tokio::time::sleep(std::time::Duration::from_secs(3)).await
}
}Example Server
use rodbus::*;
use rodbus::server::*;
use std::net::SocketAddr;
use std::str::FromStr;
use tokio::net::TcpListener;
struct CoilsOnlyHandler {
pub coils: [bool; 10]
}
impl CoilsOnlyHandler {
fn new() -> Self {
Self {
coils: [false; 10]
}
}
}
impl RequestHandler for CoilsOnlyHandler {
fn read_coil(&self, address: u16) -> Result<bool, ExceptionCode> {
self.coils.get(0).to_result()
}
}
#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let handler = CoilsOnlyHandler::new().wrap();
// map unit ids to a handler for processing requests
let map = ServerHandlerMap::single(UnitId::new(1), handler.clone());
// spawn a server to handle connections onto its own task
// if the handle _server is dropped, the server shuts down
let _server = rodbus::server::spawn_tcp_server_task(
1,
SocketAddr::from_str("127.0.0.1:502")?,
map,
AddressFilter::Any,
DecodeLevel::default(),
).await?;
let mut next = tokio::time::Instant::now();
// toggle all coils every couple of seconds
loop {
next += tokio::time::Duration::from_secs(2);
{
let mut guard = handler.lock().unwrap();
for c in &mut guard.coils {
*c = !*c;
}
}
tokio::time::sleep_until(next).await;
}
}Modules
Structs
u8Enums
Constants
Traits
Functions
RetryStrategyRetryStrategy that doubles on failure up to a maximum value