modbus-mapping 0.4.0

Modbus register mapping traits and derive macros
Documentation
/// Battery RTU Modbus simulator
use futures::future;
use modbus_mapping::derive::{HoldingRegisterModel, InputRegisterModel};
use modbus_mapping::simulator::{
    run_rtu_simulator, DataStore, Device, InputRegisterModel, Simulator,
};
use tokio_modbus::{Exception, Request, Response};

#[derive(Debug, Clone, Default, InputRegisterModel)]
pub struct BatteryInputRegisters {
    #[modbus(addr = 0, ty = "u32", ord = "be", x = 1.0, unit = "W")]
    pub power: f32,
    #[modbus(addr = 2, ty = "u32", ord = "be", x = 100.0, unit = "Wh")]
    pub state_of_energy: f32,
    #[modbus(addr = 4, ty = "u32", ord = "be", x = 0.01, unit = "V")]
    pub voltage: f32,
    #[modbus(addr = 6, ty = "u32", ord = "be", x = 0.01, unit = "Hz")]
    pub grid_frequency: f32,
}

#[derive(Debug, Clone, Default, HoldingRegisterModel)]
pub struct BatteryHoldingRegisters {
    #[modbus(addr = 0, ty = "i32", ord = "be", x = 0.01, unit = "W")]
    pub setpoint: f32,
}

#[derive(Debug, Clone, Default)]
struct Battery {
    ir: BatteryInputRegisters,
    hr: BatteryHoldingRegisters,
    data_store: DataStore<BatteryInputRegisters, BatteryHoldingRegisters>,
}

impl Device for Battery {
    type InputRegisters = BatteryInputRegisters;
    type HoldingRegisters = BatteryHoldingRegisters;

    fn service_call(&mut self, req: Request) -> future::Ready<Result<Response, Exception>> {
        self.data_store.service_call(&mut self.hr, req)
    }

    fn update_state(&mut self) {
        eprintln!("Updating state");
        self.ir.power += 1.0;

        let _ = self
            .ir
            .update_registers(&mut self.data_store.input_registers);
    }
}

#[tokio::main]
async fn main() {
    let device = Battery::default();
    let simulator = Simulator::new(device);
    let state_update_period: std::time::Duration = std::time::Duration::from_millis(200);

    let path = "/tmp/ttys001";
    let baud_rate = 0;

    run_rtu_simulator(path, baud_rate, simulator, state_update_period).await;
}