scd30_interface/data/
automatic_self_calibration.rs

1use crate::error::DataError;
2use crate::util::check_deserialization;
3
4const ASC_VALUE: &str = "Automatic self-calibration";
5const ASC_EXPECTED: &str = "0 or 1";
6
7/// Arguments for configuring the automatic self calibration.
8#[derive(Clone, Copy, Debug, PartialEq)]
9pub enum AutomaticSelfCalibration {
10    /// Active automatic self calibration
11    Active = 1,
12    /// Inactive automatic self calibration
13    Inactive = 0,
14}
15
16#[cfg(feature = "defmt")]
17impl defmt::Format for AutomaticSelfCalibration {
18    fn format(&self, f: defmt::Formatter) {
19        match self {
20            AutomaticSelfCalibration::Active => defmt::write!(f, "Active"),
21            AutomaticSelfCalibration::Inactive => defmt::write!(f, "Inactive"),
22        }
23    }
24}
25
26impl AutomaticSelfCalibration {
27    /// Returns a big endian byte representation of the automatic self calibration value.
28    pub fn to_be_bytes(&self) -> [u8; 2] {
29        (*self as u16).to_be_bytes()
30    }
31}
32
33impl TryFrom<&[u8]> for AutomaticSelfCalibration {
34    type Error = DataError;
35
36    /// Converts buffered data to an [AutomaticSelfCalibration] value. If `Active` if a `1` is
37    /// received, `Inactive` if a `0` is received.
38    ///
39    /// # Errors
40    ///
41    /// - [ReceivedBufferWrongSize](crate::error::DataError::ReceivedBufferWrongSize) if the `data` buffer is not big enough for the data
42    ///   that should have been received.
43    /// - [CrcFailed](crate::error::DataError::CrcFailed) if the CRC of the received data does not match.
44    /// - [UnexpectedValueReceived](crate::error::DataError::UnexpectedValueReceived) if the received value is not `0` or `1`.
45    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
46        check_deserialization(data, 3)?;
47        match data[1] {
48            1 => Ok(Self::Active),
49            0 => Ok(Self::Inactive),
50            val => Err(DataError::UnexpectedValueReceived {
51                parameter: ASC_VALUE,
52                expected: ASC_EXPECTED,
53                actual: val as u16,
54            }),
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn serialize_inactive_works() {
65        let asc = AutomaticSelfCalibration::Inactive;
66        assert_eq!(asc.to_be_bytes(), [0x00, 0x00]);
67    }
68
69    #[test]
70    fn serialize_active_works() {
71        let asc = AutomaticSelfCalibration::Active;
72        assert_eq!(asc.to_be_bytes(), [0x00, 0x01]);
73    }
74
75    #[test]
76    fn deserialize_inactive_spec_sample_works() {
77        let data = [0x00, 0x00, 0x81];
78        assert_eq!(
79            AutomaticSelfCalibration::try_from(&data[..]).unwrap(),
80            AutomaticSelfCalibration::Inactive
81        );
82    }
83
84    #[test]
85    fn deserialize_active_works() {
86        let data = [0x00, 0x01, 0xB0];
87        assert_eq!(
88            AutomaticSelfCalibration::try_from(&data[..]).unwrap(),
89            AutomaticSelfCalibration::Active
90        );
91    }
92
93    #[test]
94    fn deserialize_out_of_specification_value_errors() {
95        let data = [0x00, 0x02, 0xE3];
96        assert_eq!(
97            AutomaticSelfCalibration::try_from(&data[..]).unwrap_err(),
98            DataError::UnexpectedValueReceived {
99                parameter: ASC_VALUE,
100                expected: ASC_EXPECTED,
101                actual: 2
102            }
103        );
104    }
105}