use crate::{
protocol as proto,
tokio_async::SDM72,
tokio_common::{AllSettings, AllValues, Result},
};
use std::sync::Arc;
use tokio::sync::Mutex;
use tokio_modbus::{client::Context, prelude::SlaveContext};
#[derive(Clone)]
pub struct SafeClient {
ctx: Arc<Mutex<Context>>,
}
macro_rules! read_holding {
($func_name:ident, $ty:ident) => {
paste::item! {
#[doc = "Reads the [`proto::" $ty "`] value from the Modbus holding register."]
pub async fn $func_name(&mut self) -> Result<proto::$ty> {
let mut ctx = self.ctx.lock().await;
SDM72::$func_name(&mut ctx).await
}
}
};
}
macro_rules! write_holding {
($func_name:ident, $ty:ident) => {
paste::item! {
#[doc = "Writes the [`proto::" $ty "`] value to the Modbus holding register."]
pub async fn [< set_ $func_name >](&mut self, value: proto::$ty) -> Result<()> {
let mut ctx = self.ctx.lock().await;
SDM72::[< set_ $func_name >](&mut ctx, value).await
}
}
};
}
impl SafeClient {
pub fn new(ctx: Context) -> Self {
Self {
ctx: Arc::new(Mutex::new(ctx)),
}
}
pub fn from_shared(ctx: Arc<Mutex<Context>>) -> Self {
Self { ctx }
}
pub fn clone_shared(&self) -> Arc<Mutex<Context>> {
self.ctx.clone()
}
read_holding!(system_type, SystemType);
write_holding!(system_type, SystemType);
read_holding!(pulse_width, PulseWidth);
write_holding!(pulse_width, PulseWidth);
read_holding!(kppa, KPPA);
pub async fn set_kppa(&mut self, password: proto::Password) -> Result<()> {
let mut ctx = self.ctx.lock().await;
SDM72::set_kppa(&mut ctx, password).await
}
read_holding!(parity_and_stop_bit, ParityAndStopBit);
write_holding!(parity_and_stop_bit, ParityAndStopBit);
read_holding!(address, Address);
pub async fn set_address(&mut self, value: proto::Address) -> Result<()> {
let mut ctx = self.ctx.lock().await;
SDM72::set_address(&mut ctx, value).await?;
ctx.set_slave(tokio_modbus::Slave(*value));
Ok(())
}
read_holding!(pulse_constant, PulseConstant);
write_holding!(pulse_constant, PulseConstant);
read_holding!(password, Password);
write_holding!(password, Password);
read_holding!(baud_rate, BaudRate);
write_holding!(baud_rate, BaudRate);
read_holding!(auto_scroll_time, AutoScrollTime);
write_holding!(auto_scroll_time, AutoScrollTime);
read_holding!(backlight_time, BacklightTime);
write_holding!(backlight_time, BacklightTime);
read_holding!(pulse_energy_type, PulseEnergyType);
write_holding!(pulse_energy_type, PulseEnergyType);
pub async fn reset_historical_data(&mut self) -> Result<()> {
let mut ctx = self.ctx.lock().await;
SDM72::reset_historical_data(&mut ctx).await
}
read_holding!(serial_number, SerialNumber);
read_holding!(meter_code, MeterCode);
read_holding!(software_version, SoftwareVersion);
pub async fn read_all_settings(&mut self, delay: &std::time::Duration) -> Result<AllSettings> {
let mut ctx = self.ctx.lock().await;
SDM72::read_all_settings(&mut ctx, delay).await
}
pub async fn read_all(&mut self, delay: &std::time::Duration) -> Result<AllValues> {
let mut ctx = self.ctx.lock().await;
SDM72::read_all(&mut ctx, delay).await
}
}