1use crate::{error::DataError, util::check_deserialization};
2
3#[derive(Debug, PartialEq)]
6pub struct Measurement {
7 pub pm1_0: f32,
9 pub pm2_5: f32,
11 pub pm4_0: f32,
13 pub pm10_0: f32,
15 pub relative_humidity: f32,
17 pub temperature: f32,
19 pub voc_index: f32,
21 pub nox_index: f32,
23 pub co2: u16,
25}
26
27impl TryFrom<&[u8]> for Measurement {
28 type Error = DataError;
29
30 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
39 check_deserialization(data, 27)?;
40 Ok(Self {
41 pm1_0: u16::from_be_bytes([data[0], data[1]]) as f32 / 10.,
42 pm2_5: u16::from_be_bytes([data[3], data[4]]) as f32 / 10.,
43 pm4_0: u16::from_be_bytes([data[6], data[7]]) as f32 / 10.,
44 pm10_0: u16::from_be_bytes([data[9], data[10]]) as f32 / 10.,
45 relative_humidity: i16::from_be_bytes([data[12], data[13]]) as f32 / 100.,
46 temperature: i16::from_be_bytes([data[15], data[16]]) as f32 / 200.,
47 voc_index: i16::from_be_bytes([data[18], data[19]]) as f32 / 10.,
48 nox_index: i16::from_be_bytes([data[21], data[22]]) as f32 / 10.,
49 co2: u16::from_be_bytes([data[24], data[25]]),
50 })
51 }
52}
53
54#[cfg(feature = "defmt")]
55impl defmt::Format for Measurement {
56 fn format(&self, f: defmt::Formatter) {
57 defmt::write!(
58 f,
59 "PM1.0: {} ug/m³
60PM2.5: {} ug/m³
61PM4.0: {} ug/m³
62PM10.0: {} ug/m³
63RH: {} %
64Temp: {} °C
65VOC Index: {} / 1
66NOx Index: {} / 100
67CO2: {} ppm",
68 self.pm1_0,
69 self.pm2_5,
70 self.pm4_0,
71 self.pm10_0,
72 self.relative_humidity,
73 self.temperature,
74 self.voc_index,
75 self.nox_index,
76 self.co2
77 )
78 }
79}
80
81#[derive(Debug, PartialEq)]
84pub struct RawMeasurement {
85 pub relative_humidity: f32,
87 pub temperature: f32,
89 pub voc: u16,
91 pub nox: u16,
93 pub co2: u16,
95}
96
97impl TryFrom<&[u8]> for RawMeasurement {
98 type Error = DataError;
99
100 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
109 check_deserialization(data, 15)?;
110 Ok(Self {
111 relative_humidity: i16::from_be_bytes([data[0], data[1]]) as f32 / 100.,
112 temperature: i16::from_be_bytes([data[3], data[4]]) as f32 / 200.,
113 voc: u16::from_be_bytes([data[6], data[7]]),
114 nox: u16::from_be_bytes([data[9], data[10]]),
115 co2: u16::from_be_bytes([data[12], data[13]]),
116 })
117 }
118}
119
120#[cfg(feature = "defmt")]
121impl defmt::Format for RawMeasurement {
122 fn format(&self, f: defmt::Formatter) {
123 defmt::write!(
124 f,
125 "RH: {} %
126Temp: {} °C
127VOC: {} ticks
128NOx: {} ticks
129CO2: {} ppm",
130 self.relative_humidity,
131 self.temperature,
132 self.voc,
133 self.nox,
134 self.co2
135 )
136 }
137}
138
139#[derive(Debug, PartialEq)]
142pub struct Concentrations {
143 pub pm0_5: f32,
145 pub pm1_0: f32,
147 pub pm2_5: f32,
149 pub pm4_0: f32,
151 pub pm10_0: f32,
153}
154
155impl TryFrom<&[u8]> for Concentrations {
156 type Error = DataError;
157
158 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
167 check_deserialization(data, 15)?;
168 Ok(Self {
169 pm0_5: u16::from_be_bytes([data[0], data[1]]) as f32 / 10.,
170 pm1_0: u16::from_be_bytes([data[3], data[4]]) as f32 / 10.,
171 pm2_5: u16::from_be_bytes([data[6], data[7]]) as f32 / 10.,
172 pm4_0: u16::from_be_bytes([data[9], data[10]]) as f32 / 10.,
173 pm10_0: u16::from_be_bytes([data[12], data[13]]) as f32 / 10.,
174 })
175 }
176}
177
178#[cfg(feature = "defmt")]
179impl defmt::Format for Concentrations {
180 fn format(&self, f: defmt::Formatter) {
181 defmt::write!(
182 f,
183 "PM0.5: {} p/cm³
184PM1.0: {} p/cm³
185PM2.5: {} p/cm³
186PM4.0: {} p/cm³
187PM10.0: {} p/cm³",
188 self.pm0_5,
189 self.pm1_0,
190 self.pm2_5,
191 self.pm4_0,
192 self.pm10_0
193 )
194 }
195}