Skip to main content

async_modbus/
client.rs

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