async_modbus/
embedded_io.rs1use embedded_io_async::{Read, ReadExactError, Write};
4use zerocopy::{FromBytes, Immutable, IntoBytes};
5
6use crate::{
7 Error, request,
8 response::{self, Response},
9};
10
11pub async fn read_holdings<const N: usize, E>(
13 mut serial: impl Read<Error = E> + Write<Error = E>,
14 addr: u8,
15 starting_register: u16,
16) -> Result<[u16; N], Error<E>> {
17 let req = request::ReadHoldings::new(addr, starting_register, N as u16);
18 write_message(&mut serial, &req).await.map_err(Error::Io)?;
19
20 let res: response::ReadHoldings<N> = read_message(&mut serial).await?;
21 let data = res.into_data(&req)?;
22 Ok(data.map(|holding| holding.get()))
23}
24
25pub async fn write_holding<E>(
27 mut serial: impl Read<Error = E> + Write<Error = E>,
28 addr: u8,
29 register: u16,
30 value: u16,
31) -> Result<(), Error<E>> {
32 let req = request::WriteHolding::new(addr, register, value);
33 write_message(&mut serial, &req).await.map_err(Error::Io)?;
34
35 let res: response::WriteHolding = read_message(&mut serial).await?;
36 Ok(res.into_data(&req)?)
37}
38
39pub async fn write_holdings<const N: usize, E>(
41 mut serial: impl Read<Error = E> + Write<Error = E>,
42 addr: u8,
43 starting_register: u16,
44 data: [u16; N],
45) -> Result<(), Error<E>> {
46 let req = request::WriteHoldings::new(addr, starting_register, data);
47 write_message(&mut serial, &req).await.map_err(Error::Io)?;
48
49 let res: response::WriteHoldings = read_message(&mut serial).await?;
50 Ok(res.into_data(&req)?)
51}
52
53pub async fn read_inputs<const N: usize, E>(
55 mut serial: impl Read<Error = E> + Write<Error = E>,
56 addr: u8,
57 starting_register: u16,
58) -> Result<[u16; N], Error<E>> {
59 let req = request::ReadInputs::new(addr, starting_register, N as u16);
60 write_message(&mut serial, &req).await.map_err(Error::Io)?;
61
62 let res: response::ReadInputs<N> = read_message(&mut serial).await?;
63 let data = res.into_data(&req)?;
64 Ok(data.map(|input| input.get()))
65}
66
67async fn write_message<T, E>(mut dst: impl Write<Error = E>, message: &T) -> Result<(), E>
68where
69 T: IntoBytes + Immutable,
70{
71 dst.write_all(message.as_bytes()).await?;
72 dst.flush().await
73}
74
75async fn read_message<T, E>(mut src: impl Read<Error = E>) -> Result<T, ReadExactError<E>>
76where
77 T: FromBytes + IntoBytes,
78{
79 let mut message = T::new_zeroed();
80 src.read_exact(message.as_mut_bytes()).await?;
81 Ok(message)
82}
83
84impl<E> From<ReadExactError<E>> for crate::Error<E> {
85 fn from(e: ReadExactError<E>) -> Self {
86 match e {
87 ReadExactError::Other(e) => Self::Io(e),
88 ReadExactError::UnexpectedEof => Self::UnexpectedEof,
89 }
90 }
91}