1use crate::shdlc::TranslationError;
4
5use arrayvec::CapacityError;
6
7use std::fmt::Display;
8
9#[derive(Debug)]
12pub enum DeviceError {
13 IoError(std::io::Error),
15 ShdlcError(TranslationError),
16 StateResponse(StateResponseError),
17 PortError(serialport::Error),
18 InvalidChecksum(u8, u8),
21 InvalidString,
24}
25
26impl Display for DeviceError {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 Self::IoError(e) => e.fmt(f),
30 Self::ShdlcError(e) => e.fmt(f),
31 Self::StateResponse(e) => e.fmt(f),
32 Self::PortError(e) => e.fmt(f),
33 Self::InvalidChecksum(recived, expected) => write!(
34 f,
35 "checksum recived: {:#02x} did not match expected value: {:#02x}",
36 recived, expected
37 ),
38 Self::InvalidString => write!(f, "invalid string data found"),
39 }
40 }
41}
42
43impl From<std::io::Error> for DeviceError {
44 fn from(value: std::io::Error) -> Self {
45 Self::IoError(value)
46 }
47}
48
49impl From<TranslationError> for DeviceError {
50 fn from(value: TranslationError) -> Self {
51 Self::ShdlcError(value)
52 }
53}
54
55impl From<StateResponseError> for DeviceError {
56 fn from(value: StateResponseError) -> Self {
57 Self::StateResponse(value)
58 }
59}
60
61impl From<serialport::Error> for DeviceError {
62 fn from(value: serialport::Error) -> Self {
63 Self::PortError(value)
64 }
65}
66
67impl From<CapacityError> for DeviceError {
68 fn from(_: CapacityError) -> Self {
69 Self::ShdlcError(TranslationError::DataTooLarge)
70 }
71}
72
73#[derive(Debug, PartialEq)]
75pub enum StateResponseError {
76 DataSizeError,
79 UnknownCommand,
81 ParameterError,
83 I2CNackError,
85 I2CMasterHoldError,
87 CRCError,
89 DataWriteError,
91 MeasureLoopNotRunning,
93 InvalidCalibration,
95 SensorBusy,
97 CommandNotAllowed,
99 FatalError,
101}
102
103impl From<u8> for StateResponseError {
104 fn from(value: u8) -> Self {
105 match value {
106 0x01 => Self::DataSizeError,
107 0x02 => Self::UnknownCommand,
108 0x04 => Self::ParameterError,
109 0x29 => Self::I2CNackError,
110 0x2A => Self::I2CMasterHoldError,
111 0x2B => Self::CRCError,
112 0x2C => Self::DataWriteError,
113 0x2D => Self::MeasureLoopNotRunning,
114 0x33 => Self::InvalidCalibration,
115 0x42 => Self::SensorBusy,
116 0x32 => Self::CommandNotAllowed,
117 0x7F => Self::FatalError,
118 _ => Self::FatalError,
119 }
120 }
121}
122
123impl Display for StateResponseError {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 match self {
126 Self::DataSizeError => write!(f, "illegal data size of MOSI frame or invalid frame"),
127 Self::UnknownCommand => write!(f, "the device does not support or know this command"),
128 Self::ParameterError => write!(f, "the sent parameter was out of range"),
129 Self::I2CNackError => write!(f, "NACK recived from the I2C device"),
130 Self::I2CMasterHoldError => write!(f, "master hold not released from I2C device"),
131 Self::CRCError => write!(f, "checksum miss match occured"),
132 Self::DataWriteError => write!(f, "sensor data read back differs from written value"),
133 Self::MeasureLoopNotRunning => write!(
134 f,
135 "sensor mesaure loop not running or runs on wrong gas number"
136 ),
137 Self::InvalidCalibration => write!(f, "no valid gas calibration at given index"),
138 Self::SensorBusy => write!(
139 f,
140 "the sensor is busy at the moment, it takes 300ms to power-up after reset"
141 ),
142 Self::CommandNotAllowed => write!(f, "command is not allowed in the current state"),
143 Self::FatalError => write!(f, "an error without a specific code occured"), }
145 }
146}