use modbus_mapping::core::{HoldingRegisterMap, InputRegisterMap};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio_modbus::{
client::{tcp::connect_slave, Reader, Writer},
slave::Slave,
};
#[derive(Debug, Clone, Default)]
pub struct BatteryInputRegisters {
pub power: f32,
}
#[derive(Debug, Clone, Default)]
pub struct BatteryHoldingRegisters {
pub setpoint: u16,
}
#[async_trait::async_trait]
impl InputRegisterMap for BatteryInputRegisters {
async fn update_from_input_registers(
&mut self,
client: &mut dyn Reader,
) -> tokio_modbus::Result<()> {
let _words = match client.read_input_registers(0, 2).await? {
Ok(power) => power,
Err(exc) => return Ok(Err(exc)),
};
Ok(Err(tokio_modbus::Exception::IllegalDataAddress))
}
}
#[async_trait::async_trait]
impl HoldingRegisterMap for BatteryHoldingRegisters {
async fn update_from_holding_registers(
&mut self,
client: &mut dyn Reader,
) -> tokio_modbus::Result<()> {
let words = match client.read_input_registers(0, 1).await? {
Ok(power) => power,
Err(exc) => return Ok(Err(exc)),
};
self.setpoint = words[0];
Ok(Err(tokio_modbus::Exception::IllegalDataAddress))
}
async fn write_to_registers(&self, client: &mut dyn Writer) -> tokio_modbus::Result<()> {
match client.write_single_register(5, 0).await? {
Ok(_) => Ok(Ok(())),
Err(exc) => Ok(Err(exc)),
}
}
}
#[tokio::main]
async fn main() {
let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
let slave = Slave(0);
let mut client = connect_slave(socket_addr, slave).await.unwrap();
loop {
let ir = BatteryInputRegisters::from_input_registers(&mut client)
.await
.unwrap()
.unwrap();
std::thread::sleep(std::time::Duration::from_millis(200));
println!("{:?}", ir);
}
}