Skip to main content

async_modbus/
client.rs

1//! Client functions for [`embedded_io_async`]-based IO.
2
3use core::error::Error as CoreError;
4use std::fmt::Debug;
5
6use defmt_or_log::*;
7use embedded_io_async::{Read, ReadExactError, Write};
8use zerocopy::{FromBytes, Immutable, IntoBytes};
9
10mod generated {
11    include!(concat!(env!("OUT_DIR"), "/client.rs"));
12}
13
14pub use generated::*;
15
16use crate::pdu::{CrcError, ValidationError};
17
18async fn write_frame<T, E>(mut dst: impl Write<Error = E>, frame: &T) -> Result<(), E>
19where
20    T: IntoBytes + Immutable + Debug,
21{
22    trace!("Writing frame: {:?}", frame);
23    dst.write_all(frame.as_bytes()).await?;
24    dst.flush().await
25}
26
27async fn read_frame<T, E>(mut src: impl Read<Error = E>) -> Result<T, ReadExactError<E>>
28where
29    T: FromBytes + IntoBytes + Debug,
30{
31    let mut message = T::new_zeroed();
32    src.read_exact(message.as_mut_bytes()).await?;
33    trace!("Read frame: {:?}", message);
34    Ok(message)
35}
36
37/// Errors that can occur when talking to a Modbus server.
38#[derive(Debug, thiserror::Error)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40pub enum Error<Io: CoreError> {
41    /// IO error.
42    #[error(transparent)]
43    Io(Io),
44    /// Unexpected end of file when reading.
45    #[error("unexpected end of file")]
46    UnexpectedEof,
47    /// Invalid CRC checksum.
48    #[error(transparent)]
49    Crc(#[from] CrcError),
50    /// Unexpected response from the Modbus server.
51    #[error("unexpected response from server")]
52    UnexpectedResponse,
53}
54
55impl<E: CoreError> From<ValidationError> for Error<E> {
56    fn from(e: ValidationError) -> Self {
57        match e {
58            ValidationError::Crc(crc) => Error::Crc(crc),
59            ValidationError::UnexpectedResponse => Error::UnexpectedResponse,
60        }
61    }
62}
63
64impl<E: CoreError> From<ReadExactError<E>> for Error<E> {
65    fn from(e: ReadExactError<E>) -> Self {
66        match e {
67            ReadExactError::Other(e) => Self::Io(e),
68            ReadExactError::UnexpectedEof => Self::UnexpectedEof,
69        }
70    }
71}