Crate rodbus

Crate rodbus 

Source
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:

https://stepfunc.io/contact/

§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§

client
Client API
constants
Public constant values related to the Modbus specification
server
Server API

Structs§

AddressRange
Start and count tuple used when making various requests Cannot be constructed with invalid start/count
BitIterator
Zero-copy type used to iterate over a collection of bits
DecodeLevel
Controls the decoding of transmitted and received data at the application, frame, and physical layer
Indexed
Value and its address
MaybeAsync
Represents a result that may be computed synchronously or asynchronously by user code.
RegisterIterator
Zero-copy type used to iterate over a collection of registers
SerialSettings
Serial port settings
Shutdown
The task processing requests has terminated
UnitId
Modbus unit identifier, just a type-safe wrapper around u8

Enums§

AduParseError
Errors that occur while parsing requests and responses
AppDecodeLevel
Controls how transmitted and received message at the application layer are decoded at the INFO log level
DataBits
Number of bits per character
ExceptionCode
Exception codes defined in the Modbus specification
FlowControl
Flow control modes
FrameDecodeLevel
Controls how the transmitted and received frames are decoded at the INFO log level
FrameParseError
Errors that occur while parsing a frame off a stream (TCP or serial)
InternalError
Errors that indicate faulty logic in the library itself if they occur
InvalidRange
Errors that can be produced when validating start/count
InvalidRequest
Errors that result because of bad request parameter
Parity
Parity checking modes
PhysDecodeLevel
Controls how data transmitted at the physical layer (TCP, serial, etc) is logged
RequestError
Top level error type for the client API
StopBits
Number of stop bits

Constants§

VERSION
Current version of the library

Traits§

RetryStrategy
Trait that controls how the channel retries failed connect (TCP/TLS) or open (serial) attempts

Functions§

default_retry_strategy
Return the default RetryStrategy
doubling_retry_strategy
Return a RetryStrategy that doubles on failure up to a maximum value