scd30_interface/data/
ambient_pressure.rs

1use crate::error::DataError;
2
3/// A runtime checked representation of the ambient pressure compensation value used as an argument
4/// for the ambient pressure compensation during continuous measurements. Accepted value range:
5/// [700...1400] mBar.
6#[derive(Debug, PartialEq)]
7pub struct AmbientPressure(u16);
8
9const MIN_AMBIENT_PRESSURE: u16 = 700;
10const MAX_AMBIENT_PRESSURE: u16 = 1400;
11const AMBIENT_PRESSURE_VAL: &str = "Ambient pressure compensation";
12const PRESSURE_UNIT: &str = "mBar";
13
14impl AmbientPressure {
15    /// Returns a big endian byte representation of the ambient pressure value.
16    pub const fn to_be_bytes(&self) -> [u8; 2] {
17        self.0.to_be_bytes()
18    }
19}
20
21#[cfg(feature = "defmt")]
22impl defmt::Format for AmbientPressure {
23    fn format(&self, f: defmt::Formatter) {
24        defmt::write!(f, "{}mBar", self.0)
25    }
26}
27
28impl TryFrom<u16> for AmbientPressure {
29    type Error = DataError;
30
31    /// Converts a u16 value to an [AmbientPressure]. The value must be between 700 and 1400 in mBar.
32    ///
33    /// # Errors
34    ///
35    /// - [ValueOutOfRange](crate::error::DataError::ValueOutOfRange) if `pressure` is lower than 700 or higher than
36    ///   1400 mBar.
37    /// - [UseDefaultPressure](crate::error::DataError::UseDefaultPressure) if `pressure` is 0.
38    fn try_from(pressure: u16) -> Result<Self, Self::Error> {
39        match pressure {
40            0 => Err(DataError::UseDefaultPressure),
41            p if !(MIN_AMBIENT_PRESSURE..=MAX_AMBIENT_PRESSURE).contains(&p) => {
42                Err(DataError::ValueOutOfRange {
43                    parameter: AMBIENT_PRESSURE_VAL,
44                    min: MIN_AMBIENT_PRESSURE,
45                    max: MAX_AMBIENT_PRESSURE,
46                    unit: PRESSURE_UNIT,
47                })
48            }
49            _ => Ok(Self(pressure)),
50        }
51    }
52}
53
54/// Arguments for setting the ambient pressure compensation value.
55#[derive(Debug)]
56pub enum AmbientPressureCompensation {
57    /// Configures ambient pressure compensation to the default value of 1013.25 mBar
58    DefaultPressure,
59    /// Configures ambient pressure compensation to a custom value.
60    CompensationPressure(AmbientPressure),
61}
62
63impl AmbientPressureCompensation {
64    /// Returns a byte representation of the ambient pressure compensation value.
65    pub const fn to_be_bytes(&self) -> [u8; 2] {
66        match self {
67            AmbientPressureCompensation::DefaultPressure => [0x00, 0x00],
68            AmbientPressureCompensation::CompensationPressure(ambient_pressure) => {
69                ambient_pressure.to_be_bytes()
70            }
71        }
72    }
73}
74
75#[cfg(feature = "defmt")]
76impl defmt::Format for AmbientPressureCompensation {
77    fn format(&self, f: defmt::Formatter) {
78        match self {
79            AmbientPressureCompensation::DefaultPressure => defmt::write!(f, "Default Pressure"),
80            AmbientPressureCompensation::CompensationPressure(pres) => {
81                defmt::write!(f, "Compensation Pressure: {}mBar", pres)
82            }
83        }
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn serialize_sample_works() {
93        let pressure = AmbientPressure(700);
94        assert_eq!(pressure.to_be_bytes(), [0x02, 0xBC]);
95    }
96
97    #[test]
98    fn create_allowed_value_from_u16_works() {
99        let values = [700, 1000, 1400];
100        for value in values {
101            assert_eq!(
102                AmbientPressure::try_from(value).unwrap(),
103                AmbientPressure(value)
104            );
105        }
106    }
107
108    #[test]
109    fn create_from_u16_non_null_out_of_spec_value_errors() {
110        let values = [500, 2000];
111        for value in values {
112            assert_eq!(
113                AmbientPressure::try_from(value).unwrap_err(),
114                DataError::ValueOutOfRange {
115                    parameter: AMBIENT_PRESSURE_VAL,
116                    min: 700,
117                    max: 1400,
118                    unit: PRESSURE_UNIT
119                }
120            );
121        }
122    }
123
124    #[test]
125    fn create_from_u16_null_value_errors() {
126        assert_eq!(
127            AmbientPressure::try_from(0).unwrap_err(),
128            DataError::UseDefaultPressure
129        );
130    }
131}