Skip to main content

pamoja_modbus/
error.rs

1//! The error type for Modbus framing.
2
3/// What can go wrong building or reading a Modbus RTU frame.
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub enum ModbusError {
6    /// A frame is shorter than the smallest valid RTU ADU (address, function, CRC).
7    FrameTooShort,
8    /// A frame or PDU is longer than the 256-byte RTU maximum allows.
9    FrameTooLong,
10    /// A received frame's CRC does not match its contents, so the frame is corrupt.
11    CrcMismatch {
12        /// The CRC computed over the frame's contents.
13        expected: u16,
14        /// The CRC the frame carried.
15        found: u16,
16    },
17    /// A request or a reply named a number of values one frame cannot carry: none, or more
18    /// than its function allows.
19    InvalidValueCount,
20    /// A response PDU is truncated or its declared byte count does not match its data.
21    MalformedResponse,
22    /// A unit address outside 1 to 247: 0 is the broadcast address, and 248 to 255 are
23    /// reserved.
24    UnitOutOfRange {
25        /// The address given.
26        unit: u8,
27    },
28}
29
30impl core::fmt::Display for ModbusError {
31    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32        match self {
33            ModbusError::FrameTooShort => {
34                f.write_str("modbus frame is shorter than a valid RTU ADU")
35            }
36            ModbusError::FrameTooLong => {
37                f.write_str("modbus frame exceeds the 256-byte RTU maximum")
38            }
39            ModbusError::CrcMismatch { expected, found } => {
40                write!(
41                    f,
42                    "modbus CRC mismatch: expected {expected:#06x}, found {found:#06x}"
43                )
44            }
45            ModbusError::InvalidValueCount => {
46                f.write_str("the number of values is outside what one modbus frame carries")
47            }
48            ModbusError::MalformedResponse => f.write_str("modbus response PDU is malformed"),
49            ModbusError::UnitOutOfRange { unit } => write!(
50                f,
51                "unit {unit} is not a device address: 0 is broadcast, and 248 to 255 are reserved"
52            ),
53        }
54    }
55}
56
57// `core::error::Error` rather than `std::error::Error`, so a caller on a
58// microcontroller gets the same trait a caller on a gateway does.
59impl core::error::Error for ModbusError {}