modbus_rtu/common/
exception.rs

1/// Modbus RTU exception codes.
2/// 
3/// ---
4/// # Supports
5/// - [`u8`] -> [`Exception`]
6/// - [`Exception`] -> [`u8`]
7/// 
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[repr(u8)]
10pub enum Exception {
11    /// An undefined exception code not covered by this crate.
12    Undefined(u8),
13
14    /// The function code received is not supported by the device or is invalid in the current state.
15    IllegalFunction = 0x01,
16
17    /// The requested address range is invalid for the device.
18    IllegalDataAddress = 0x02,
19
20    /// A value in the request is not valid or does not match the expected structure.
21    IllegalDataValue = 0x03,
22
23    /// An unrecoverable device error occurred during processing.
24    DeviceFailure = 0x04,
25
26    /// The request was accepted but requires a long time to complete. Prevents master timeout.
27    Acknowledge = 0x05,
28
29    /// The device is busy processing a long-duration command. Try again later.
30    DeviceBusy = 0x06,
31
32    /// Memory parity error.
33    MemoryParityError = 0x08,
34
35    /// The gateway could not establish a communication path. Check configuration or load.
36    GatewayPathUnavailable = 0x0A,
37
38    /// The gateway received no response from the target device.
39    GatewayTargetDeviceFailedToRespond = 0x0B,
40}
41
42
43impl Exception {
44    /// Returns `true` if the exception is [`Exception::Acknowledge`].
45    ///
46    /// ---
47    /// # Returns
48    /// `true` if the exception is [`Exception::Acknowledge`], otherwise `false`.
49    /// 
50    pub fn is_ack(&self) -> bool {
51        matches!(self, Exception::Acknowledge)
52    }
53}
54
55
56// u8 -> Exception
57impl From<u8> for Exception {
58    fn from(value: u8) -> Self {
59        match value {
60            0x01 => Exception::IllegalFunction,
61            0x02 => Exception::IllegalDataAddress,
62            0x03 => Exception::IllegalDataValue,
63            0x04 => Exception::DeviceFailure,
64            0x05 => Exception::Acknowledge,
65            0x06 => Exception::DeviceBusy,
66            0x08 => Exception::MemoryParityError,
67            0x0A => Exception::GatewayPathUnavailable,
68            0x0B => Exception::GatewayTargetDeviceFailedToRespond,
69            _ => Exception::Undefined(value),
70        }
71    }
72}
73
74
75// Exception -> u8
76impl From<Exception> for u8 {
77    fn from(value: Exception) -> Self {
78        match value {
79            Exception::Undefined(c) => c,
80            Exception::IllegalFunction => 0x01,
81            Exception::IllegalDataAddress => 0x02,
82            Exception::IllegalDataValue => 0x03,
83            Exception::DeviceFailure => 0x04,
84            Exception::Acknowledge => 0x05,
85            Exception::DeviceBusy => 0x06,
86            Exception::MemoryParityError => 0x08,
87            Exception::GatewayPathUnavailable => 0x0A,
88            Exception::GatewayTargetDeviceFailedToRespond => 0x0B,
89        }
90    }
91}
92
93
94// &Exception -> u8
95impl From<&Exception> for u8 {
96    fn from(value: &Exception) -> Self {
97        match value {
98            Exception::Undefined(c) => *c,
99            Exception::IllegalFunction => 0x01,
100            Exception::IllegalDataAddress => 0x02,
101            Exception::IllegalDataValue => 0x03,
102            Exception::DeviceFailure => 0x04,
103            Exception::Acknowledge => 0x05,
104            Exception::DeviceBusy => 0x06,
105            Exception::MemoryParityError => 0x08,
106            Exception::GatewayPathUnavailable => 0x0A,
107            Exception::GatewayTargetDeviceFailedToRespond => 0x0B,
108        }
109    }
110}
111
112
113// Display
114#[cfg(not(feature = "no_std"))]
115impl std::fmt::Display for Exception {
116    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
117        use Exception::*;
118        match self {
119            Undefined(c) => write!(f, "Undefined exception code 0x{c:02}({c})"),
120            IllegalFunction => write!(f, "Illegal function"),
121            IllegalDataAddress => write!(f, "Illegal data address"),
122            IllegalDataValue => write!(f, "Illegal data value"),
123            DeviceFailure => write!(f, "Device failure"),
124            Acknowledge => write!(f, "Acknowledge"),
125            DeviceBusy => write!(f, "Device busy"),
126            MemoryParityError => write!(f, "Memory parity error"),
127            GatewayPathUnavailable => write!(f, "Gateway path unavailable"),
128            GatewayTargetDeviceFailedToRespond => write!(f, "Gateway target device failed to respond"),
129        }
130    }
131}