libmodbus-rs 0.8.3

libmodbus bindings for Rust
Documentation
extern crate rand;
extern crate libmodbus_rs;

use libmodbus_rs::{Modbus, ModbusClient};
use rand::Rng;


/// This is an example client, copied from the libmodbus test random-test-client.c
///
/// The goal of this program is to check all major functions of
///
/// libmodbus:
///
/// - write_coil
/// - read_bits
/// - write_coils
/// - write_register
/// - read_registers
/// - write_registers
/// - read_registers
///
/// All these functions are called with random values on a address range defined by the following consts
const LOOPS: i32 = 1;    // Number of loops
#[allow(dead_code)] // only used in RTU context
const SERVER_ID: i32 = 17;   // Modbus ID Server
const ADDRESS_START: usize = 0;
const ADDRESS_END: usize = 99;

// At each loop the programm works in the range ADDRESS_START to ADDRESS_END
// then ADDRESS_START + 1 to ADDRESS_END and so on.
fn run() -> Result<(), String> {
    // Initialize random number generator
    let mut rng = rand::thread_rng();

    // // RTU
    // use libmodbus_rs::ModbusRTU;
    // let mut modbus = Modbus::new_rtu("/dev/ttyUSB0", 19200, 'N', 8, 1).expect("could not create RTU context");
    // modbus.set_slave(SERVER_ID).expect("could not set slave ID");

    // TCP
    use libmodbus_rs::ModbusTCP;
    let mut modbus = Modbus::new_tcp("127.0.0.1", 1502).expect("could not create TCP context");

    modbus.set_debug(true).expect("could not set DEBUG mode");
    modbus.connect().expect("could not coonect");

    let mut num_bit = ADDRESS_END - ADDRESS_START;

    let mut request_bits = vec![0u8; num_bit];
    let mut response_bits = vec![0u8; num_bit];
    let mut request_registers = vec![0u16; num_bit];
    let mut response_registers = vec![0u16; num_bit];
    let mut rw_request_registers = vec![0u16; num_bit];

    let mut num_failures = 0;

    for _ in 0..LOOPS {
        for address in ADDRESS_START..ADDRESS_END {

            for i in 0..num_bit {
                // Random numbers (short)
                // fill `request_registers` with random u16 values
                request_registers[i] = rng.gen::<u16>();
                // `rw_request_registers` conaint the invert `request_registers` values
                rw_request_registers[i] = !request_registers[i];
                // Modulo2 only 0, 1/ true, false values
                request_bits[i] = (request_registers[i] % 2) as u8;
            }

            num_bit = ADDRESS_END - address;

            // WRITE BIT
            match modbus.write_bit(address as u16,
                                   match request_bits[0] {
                                       0 => false,
                                       _ => true,
                                   }) {
                Err(err) => {
                    // Error
                    println!("ERROR write_bit: '{}'", err);
                    println!("Address = {}, value = {}", address, request_bits[0]);
                    num_failures += 1;
                },
                Ok(_) => {
                    match modbus.read_bits(address as u16, 1, &mut response_bits) {
                        Err(err) => {
                            println!("ERROR read_bits single: '{}')", err);
                            println!("address = {}", address);
                            num_failures += 1;
                        },
                        Ok(len) => {
                            if request_bits[0] != response_bits[0] {
                                println!("ERROR read_bits single ({})", len);
                                println!("address = {}", address);
                                num_failures += 1;
                            }
                        },
                    }
                },
            }

            // MULTIPLE BITS
            match modbus.write_bits(address as u16, num_bit as u16, &request_bits) {
                Err(err) => {
                    println!("ERROR write_bits: '{}'", err);
                    println!("Address = {}, num_bit = {}", address, num_bit);
                    num_failures += 1;
                },
                Ok(_) => {
                    match modbus.read_bits(address as u16, num_bit as u16, &mut response_bits) {
                        Err(err) => {
                            println!("ERROR read_bits: '{}'", err);
                            num_failures += 1;
                        },
                        Ok(len) => {
                            if len != num_bit as u16 {
                                println!("ERROR read_bits");
                                println!("Address = {}, num_bit = {}", address, num_bit);
                                num_failures += 1;
                            } else {
                                for i in 0..num_bit {
                                    if response_bits[i] != request_bits[i] {
                                        println!("ERROR modbus_read_bits");
                                        println!("Address = {address}, value {request} (0x{request:X}) != {response} \
                                                  (0x{response:X})",
                                                 address = address,
                                                 request = request_bits[i],
                                                 response = response_bits[i]);
                                        num_failures += 1;
                                    }
                                }
                            }
                        },
                    }
                },
            }

            //  SINGLE REGISTER
            match modbus.write_register(address as u16, request_registers[0]) {
                Err(err) => {
                    println!("ERROR write_register: '{}'", err);
                    println!("Address = {}, value = {request} (0x{request:X})",
                             address,
                             request = request_registers[0]);
                    num_failures += 1;
                },
                Ok(_) => {
                    match modbus.read_registers(address as u16, 1, &mut response_registers) {
                        Err(err) => {
                            println!("ERROR read_registers single: '{}'", err);
                            println!("Address = {}", address);
                            num_failures += 1;
                        },
                        Ok(_len) => {
                            if request_registers[0] != response_registers[0] {
                                println!("ERROR read_registers single");
                                println!("Address = {}, value {request} (0x{request:X}) != {response} \
                                          (0x{response:X})",
                                         address,
                                         request = request_registers[0],
                                         response = response_registers[0]);
                                num_failures += 1;
                            }
                        },
                    }
                },
            }

            // MULTIPLE REGISTERS
            match modbus.write_registers(address as u16, num_bit as u16, &request_registers) {
                Err(err) => {
                    println!("ERROR write_registers:('{}'", err);
                    println!("Address = {}, num_bit = {}", address, num_bit);
                    num_failures += 1;
                },
                Ok(len) => {
                    if len != num_bit as u16 {
                        println!("ERROR write_registers: ({})", len);
                        println!("Address = {}, num_bit = {}", address, num_bit);
                        num_failures += 1;
                    } else {
                        match modbus.read_registers(address as u16, num_bit as u16, &mut response_registers) {
                            Err(err) => {
                                println!("ERROR read_registers: '{}'", err);
                                println!("Address = {}, num_bit = {}", address, num_bit);
                                num_failures += 1;
                            },
                            Ok(len) => {
                                if len != num_bit as u16 {
                                    println!("ERROR read_registers: ({})", len);
                                    println!("Address = {}, num_bit = {}", address, num_bit);
                                    num_failures += 1;
                                } else {
                                    for i in 0..num_bit {
                                        if request_registers[i] != response_registers[i] {
                                            println!("ERROR modbus_read_registers");
                                            println!("Address = {}, value {request} (0x{request:X}) != {response} \
                                                      (0x{response:X})",
                                                     address,
                                                     request = request_registers[i],
                                                     response = response_registers[i]);
                                            num_failures += 1;
                                        }
                                    }
                                }
                            },
                        }
                    }
                },
            }

            // R/W MULTIPLE REGISTERS
            match modbus.write_and_read_registers(address as u16,
                                                  num_bit as u16,
                                                  &mut rw_request_registers,
                                                  address as u16,
                                                  num_bit as u16,
                                                  &mut response_registers) {
                Err(err) => {
                    println!("ERROR read_and_write_registers: '{}'", err);
                    println!("Address = {}, num_bit = {}", address, num_bit);
                    num_failures += 1;
                },
                Ok(len) => {
                    if len != num_bit as u16 {
                        println!("ERROR read_and_write_registers: '{}'", len);
                        println!("Address = {}, num_bit = {}", address, num_bit);
                        num_failures += 1;
                    } else {
                        for i in 0..num_bit {
                            if response_registers[i] != rw_request_registers[i] {
                                println!("ERROR read_and_write_registers READ");
                                println!("Address = {}, value {response} (0x{response:X}) != {request} \
                                          (0x{request:X})",
                                         address,
                                         response = response_registers[i],
                                         request = rw_request_registers[i]);
                                num_failures += 1;
                            }
                        }
                    }

                    match modbus.read_registers(address as u16, num_bit as u16, &mut response_registers) {
                        Err(err) => {
                            println!("ERROR modbus_read_registers ({:?})", err);
                            println!("Address = {}, num_bit = {}", address, num_bit);
                            num_failures += 1;
                        },
                        Ok(_len) => {
                            for i in 0..num_bit {
                                if rw_request_registers[i] != response_registers[i] {
                                    println!("ERROR modbus_read_and_write_registers WRITE");
                                    println!("Address = {}, value {request} (0x{request:X}) != {response} \
                                              (0x{response:X})",
                                             address,
                                             request = rw_request_registers[i],
                                             response = response_registers[i]);
                                    num_failures += 1;
                                }
                            }
                        },
                    }
                },
            }
        }
    } // End LOOP

    print!("Test: ");
    if num_failures > 0 {
        println!("{} FAILS", num_failures);
    } else {
        println!("SUCCESS");
    }

    Ok(())
}

fn main() {

    if let Err(ref err) = run() {
        println!("Error: {}", err);

        std::process::exit(1)
    }
}