1use core::marker::PhantomData;
12
13use log::debug;
14
15use embedded_hal_async::delay::DelayNs;
16use embedded_hal_async::i2c::I2c;
17
18use crate::constants::DEFAULT_ADDRESS;
19use crate::sample::Sample;
20use crate::Altitude;
21use crate::Co2;
22use crate::Error;
23use crate::Idle;
24use crate::Measuring;
25use crate::Pressure;
26use crate::State;
27use crate::Temperature;
28
29use super::commands;
30use super::Command;
31
32pub struct Scd4x<I2c, Delay, State> {
34 i2c: I2c,
36
37 address: u8,
39
40 delay: Delay,
42
43 _state: PhantomData<State>,
45}
46
47impl<I2C, D> Scd4x<I2C, D, Idle>
48where
49 I2C: I2c,
50 D: DelayNs,
51{
52 pub fn new(i2c: I2C, delay: D) -> Self {
55 Self::new_with_address(i2c, DEFAULT_ADDRESS, delay)
56 }
57
58 pub fn new_with_address(i2c: I2C, address: u8, delay: D) -> Self {
61 Self {
62 i2c,
63 address,
64 delay,
65 _state: PhantomData,
66 }
67 }
68
69 pub async fn start_periodic_measurement(mut self) -> Result<Scd4x<I2C, D, Measuring>, Error> {
75 debug!("Send command 'start_periodic_measurement'");
76
77 commands::StartPeriodicMeasurement
78 .execute(self.address, &mut self.i2c, &mut self.delay, ())
79 .await?;
80
81 Ok(Scd4x {
82 i2c: self.i2c,
83 address: self.address,
84 delay: self.delay,
85 _state: PhantomData,
86 })
87 }
88
89 pub async fn set_temperature_offset(
95 &mut self,
96 temperature_offset: Temperature,
97 ) -> Result<(), Error> {
98 debug!("Send command 'set_temperature_offset'");
99
100 commands::SetTemperatureOffset
101 .execute(
102 self.address,
103 &mut self.i2c,
104 &mut self.delay,
105 temperature_offset,
106 )
107 .await
108 }
109
110 pub async fn get_temperature_offset(&mut self) -> Result<Temperature, Error> {
116 debug!("Send command 'get_temperature_offset'");
117
118 commands::GetTemperatureOffset
119 .execute(self.address, &mut self.i2c, &mut self.delay, ())
120 .await
121 }
122
123 pub async fn set_sensor_altitude(&mut self, sensor_altitude: Altitude) -> Result<(), Error> {
129 debug!("Send command 'set_sensor_altitude'");
130
131 commands::SetSensorAltitude
132 .execute(
133 self.address,
134 &mut self.i2c,
135 &mut self.delay,
136 sensor_altitude,
137 )
138 .await
139 }
140
141 pub async fn get_sensor_altitude(&mut self) -> Result<Altitude, Error> {
147 debug!("Send command 'get_sensor_altitude'");
148
149 commands::GetSensorAltitude
150 .execute(self.address, &mut self.i2c, &mut self.delay, ())
151 .await
152 }
153
154 pub async fn perform_forced_recalibration(&mut self, co2: Co2) -> Result<Option<Co2>, Error> {
160 debug!("Send command 'perform_forced_recalibration'");
161
162 commands::PerformForcedRecalibration
163 .execute(self.address, &mut self.i2c, &mut self.delay, co2)
164 .await
165 }
166
167 pub async fn set_automatic_self_calibration_enabled(
173 &mut self,
174 enabled: bool,
175 ) -> Result<(), Error> {
176 debug!("Send command 'set_automatic_self_calibration_enabled'");
177
178 commands::SetAutomaticSelfCalibrationEnabled
179 .execute(self.address, &mut self.i2c, &mut self.delay, enabled)
180 .await
181 }
182
183 pub async fn get_automatic_self_calibration_enabled(&mut self) -> Result<bool, Error> {
189 debug!("Send command 'get_automatic_self_calibration_enabled'");
190
191 commands::GetAutomaticSelfCalibrationEnabled
192 .execute(self.address, &mut self.i2c, &mut self.delay, ())
193 .await
194 }
195
196 pub async fn start_low_power_periodic_measurement(
202 mut self,
203 ) -> Result<Scd4x<I2C, D, Measuring>, Error> {
204 debug!("Send command 'start_low_power_periodic_measurement'");
205
206 commands::StartLowPowerPeriodicMeasurement
207 .execute(self.address, &mut self.i2c, &mut self.delay, ())
208 .await?;
209
210 Ok(Scd4x {
211 i2c: self.i2c,
212 address: self.address,
213 delay: self.delay,
214 _state: PhantomData,
215 })
216 }
217
218 pub async fn persist_settings(&mut self) -> Result<(), Error> {
224 debug!("Send command 'persist_settings'");
225
226 commands::PersistSettings
227 .execute(self.address, &mut self.i2c, &mut self.delay, ())
228 .await
229 }
230
231 pub async fn get_serial_number(&mut self) -> Result<u64, Error> {
237 debug!("Send command 'get_serial_number'");
238
239 commands::GetSerialNumber
240 .execute(self.address, &mut self.i2c, &mut self.delay, ())
241 .await
242 }
243
244 pub async fn perform_self_test(&mut self) -> Result<bool, Error> {
250 debug!("Send command 'perform_self_test'");
251
252 commands::PerformSelfTest
253 .execute(self.address, &mut self.i2c, &mut self.delay, ())
254 .await
255 }
256
257 pub async fn perform_factory_reset(&mut self) -> Result<(), Error> {
263 debug!("Send command 'perform_factory_reset'");
264
265 commands::PerformFactoryReset
266 .execute(self.address, &mut self.i2c, &mut self.delay, ())
267 .await
268 }
269
270 pub async fn reinit(&mut self) -> Result<(), Error> {
282 debug!("Send command 'reinit'");
283
284 commands::Reinitialize
285 .execute(self.address, &mut self.i2c, &mut self.delay, ())
286 .await
287 }
288
289 pub async fn measure_single_shot(mut self) -> Result<Scd4x<I2C, D, Measuring>, Error> {
295 debug!("Send command 'measure_single_shot'");
296
297 commands::MeasureSingleShot
298 .execute(self.address, &mut self.i2c, &mut self.delay, ())
299 .await?;
300
301 Ok(Scd4x {
302 i2c: self.i2c,
303 address: self.address,
304 delay: self.delay,
305 _state: PhantomData,
306 })
307 }
308
309 pub async fn measure_single_shot_rht_only(mut self) -> Result<Scd4x<I2C, D, Measuring>, Error> {
315 debug!("Send command 'measure_single_shot_rht_only'");
316
317 commands::MeasureSingleShotRhtOnly
318 .execute(self.address, &mut self.i2c, &mut self.delay, ())
319 .await?;
320
321 Ok(Scd4x {
322 i2c: self.i2c,
323 address: self.address,
324 delay: self.delay,
325 _state: PhantomData,
326 })
327 }
328}
329
330impl<I2C, D> Scd4x<I2C, D, Measuring>
331where
332 I2C: I2c,
333 D: DelayNs,
334{
335 pub fn new_in_measuring(i2c: I2C, delay: D) -> Self {
338 Self::new_in_measuring_with_address(i2c, DEFAULT_ADDRESS, delay)
339 }
340
341 pub fn new_in_measuring_with_address(i2c: I2C, address: u8, delay: D) -> Self {
344 Self {
345 i2c,
346 address,
347 delay,
348 _state: PhantomData,
349 }
350 }
351
352 pub async fn read_measurement(&mut self) -> Result<Sample, Error> {
358 debug!("Send command 'read_measurement'");
359
360 commands::ReadMeasurement
361 .execute(self.address, &mut self.i2c, &mut self.delay, ())
362 .await
363 }
364
365 pub async fn get_data_ready_status(&mut self) -> Result<bool, Error> {
371 debug!("Send command 'get_data_ready_status'");
372
373 commands::GetDataReadyStatus
374 .execute(self.address, &mut self.i2c, &mut self.delay, ())
375 .await
376 }
377}
378
379impl<I2C, D, S> Scd4x<I2C, D, S>
380where
381 I2C: I2c,
382 D: DelayNs,
383 S: State,
384{
385 pub fn release(self) -> I2C {
387 self.i2c
388 }
389
390 pub async fn stop_periodic_measurement(mut self) -> Result<Scd4x<I2C, D, Idle>, Error> {
396 debug!("Send command 'stop_periodic_measurement'");
397
398 commands::StopPeriodicMeasurement
399 .execute(self.address, &mut self.i2c, &mut self.delay, ())
400 .await?;
401
402 Ok(Scd4x {
403 i2c: self.i2c,
404 address: self.address,
405 delay: self.delay,
406 _state: PhantomData,
407 })
408 }
409
410 pub async fn set_ambient_pressure(&mut self, ambient_pressure: Pressure) -> Result<(), Error> {
416 debug!("Send command 'set_ambient_pressure'");
417
418 commands::SetAmbientPressure
419 .execute(
420 self.address,
421 &mut self.i2c,
422 &mut self.delay,
423 ambient_pressure,
424 )
425 .await
426 }
427}