use crate::{protocol as proto, tokio_common::Result};
use tokio_modbus::prelude::{Reader, Writer};
pub struct R413D08 {}
impl R413D08 {
fn map_tokio_result<T>(result: tokio_modbus::Result<T>) -> Result<T> {
match result {
Ok(Ok(result)) => Ok(result),
Ok(Err(err)) => Err(err.into()), Err(err) => Err(err.into()), }
}
async fn read_and_decode<T, F>(
ctx: &mut tokio_modbus::client::Context,
address: u16,
quantity: u16,
decoder: F,
) -> Result<T>
where
F: FnOnce(&[u16]) -> Result<T>,
{
decoder(&Self::map_tokio_result(
ctx.read_holding_registers(address, quantity).await,
)?)
}
pub async fn read_ports(ctx: &mut tokio_modbus::client::Context) -> Result<proto::PortStates> {
Self::read_and_decode(
ctx,
proto::PortStates::ADDRESS,
proto::PortStates::QUANTITY,
|words| Ok(proto::PortStates::decode_from_holding_registers(words)),
)
.await
}
pub async fn set_port_open(
ctx: &mut tokio_modbus::client::Context,
port: proto::Port,
) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
port.address_for_write_register(),
proto::Port::REG_DATA_SET_PORT_OPEN,
)
.await,
)
}
pub async fn set_all_open(ctx: &mut tokio_modbus::client::Context) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
proto::PortsAll::ADDRESS,
proto::PortsAll::REG_DATA_SET_ALL_OPEN,
)
.await,
)
}
pub async fn set_port_close(
ctx: &mut tokio_modbus::client::Context,
port: proto::Port,
) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
port.address_for_write_register(),
proto::Port::REG_DATA_SET_PORT_CLOSE,
)
.await,
)
}
pub async fn set_all_close(ctx: &mut tokio_modbus::client::Context) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
proto::PortsAll::ADDRESS,
proto::PortsAll::REG_DATA_SET_ALL_CLOSE,
)
.await,
)
}
pub async fn set_port_toggle(
ctx: &mut tokio_modbus::client::Context,
port: proto::Port,
) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
port.address_for_write_register(),
proto::Port::REG_DATA_SET_PORT_TOGGLE,
)
.await,
)
}
pub async fn set_port_latch(
ctx: &mut tokio_modbus::client::Context,
port: proto::Port,
) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
port.address_for_write_register(),
proto::Port::REG_DATA_SET_PORT_LATCH,
)
.await,
)
}
pub async fn set_port_momentary(
ctx: &mut tokio_modbus::client::Context,
port: proto::Port,
) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
port.address_for_write_register(),
proto::Port::REG_DATA_SET_PORT_MOMENTARY,
)
.await,
)
}
pub async fn set_port_delay(
ctx: &mut tokio_modbus::client::Context,
port: proto::Port,
delay: u8,
) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(
port.address_for_write_register(),
proto::Port::encode_delay_for_write_register(delay),
)
.await,
)
}
pub async fn read_address(ctx: &mut tokio_modbus::client::Context) -> Result<proto::Address> {
Self::read_and_decode(
ctx,
proto::Address::ADDRESS,
proto::Address::QUANTITY,
|words| Ok(proto::Address::decode_from_holding_registers(words)?),
)
.await
}
pub async fn set_address(
ctx: &mut tokio_modbus::client::Context,
address: proto::Address,
) -> Result<()> {
Self::map_tokio_result(
ctx.write_single_register(proto::Address::ADDRESS, address.encode_for_write_register())
.await,
)
}
}