1use crate::internal::common::opcode_with_data_into_payload;
2use crate::measurement::Measurement;
3use core::ops::Range;
4
5pub const I2C_ADDRESS: u8 = 0x61;
7
8pub const WRITE_DELAY_MILLIS: u32 = 5;
17
18pub const BOOT_DELAY_MILLIS: u32 = 2_000;
20
21pub const AMBIENT_PRESSURE_DISABLE_COMPENSATION: u16 = 0;
23pub const AMBIENT_PRESSURE_RANGE_HPA: Range<u16> = 700..1401;
24
25pub const MEASUREMENT_INTERVAL_RANGE: Range<u16> = 2..1801;
27
28pub const FRC_PPM_RANGE: Range<u16> = 400..2001;
30
31pub const START_CONTINUOUS_MEASUREMENT: Command = Command(0x0010);
32pub const STOP_CONTINUOUS_MEASUREMENT: Command = Command(0x0104);
33pub const GET_SET_MEASUREMENT_INTERVAL: Command = Command(0x4600);
34pub const GET_DATA_READY_STATUS: Command = Command(0x0202);
35pub const READ_MEASUREMENT: Command = Command(0x0300);
36pub const MANAGE_AUTOMATIC_SELF_CALIBRATION: Command = Command(0x5306);
37pub const SET_FORCED_RECALIBRATION_VALUE: Command = Command(0x5204);
38pub const GET_SET_TEMPERATURE_OFFSET: Command = Command(0x5403);
39pub const GET_SET_ALTITUDE_COMPENSATION: Command = Command(0x5102);
40pub const READ_FIRMWARE_VERSION: Command = Command(0xD100);
41pub const SOFT_RESET: Command = Command(0xD304);
42
43#[derive(Copy, Clone)]
44pub struct Command(u16);
45
46impl Command {
47 pub const fn prepare(self) -> [u8; 2] {
48 self.0.to_be_bytes()
49 }
50
51 pub const fn prepare_with_data(self, data: u16) -> [u8; 5] {
52 opcode_with_data_into_payload(self.0, data)
53 }
54}
55
56pub fn decode_measurement_data(buf: [u8; 18]) -> Measurement {
57 let co2 = f32::from_be_bytes([buf[0], buf[1], buf[3], buf[4]]);
58 let tmp = f32::from_be_bytes([buf[6], buf[7], buf[9], buf[10]]);
59 let hum = f32::from_be_bytes([buf[12], buf[13], buf[15], buf[16]]);
60
61 Measurement {
62 temperature: tmp,
63 humidity: hum,
64 co2: co2 as u16,
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 const F32_TOLERANCE: f32 = 0.05;
73
74 #[test]
75 fn test_prepare_command() {
76 assert_eq!([0x00, 0x10], START_CONTINUOUS_MEASUREMENT.prepare());
77 }
78
79 #[test]
80 fn test_prepare_command_with_data() {
81 assert_eq!(
82 [0x54, 0x03, 0x01, 0xF4, 0x33],
83 GET_SET_TEMPERATURE_OFFSET.prepare_with_data(0x01F4)
84 );
85 }
86
87 #[test]
88 fn test_decode_measurement_data() {
89 const EXPECTED_HUMIDITY: f32 = 48.8;
90 const EXPECTED_TEMPERATURE: f32 = 27.2;
91
92 let buf = [
93 0x43, 0xDB, 0xCB, 0x8C, 0x2E, 0x8F, 0x41, 0xD9, 0x70, 0xE7, 0xFF, 0xF5, 0x42, 0x43, 0xBF, 0x3A, 0x1B, 0x74, ];
100
101 let m = decode_measurement_data(buf);
102 assert_eq!(439, m.co2);
103 assert!(
104 (EXPECTED_HUMIDITY - m.humidity).abs() < F32_TOLERANCE,
105 "Expected: {}; Actual: {}",
106 EXPECTED_HUMIDITY,
107 m.humidity
108 );
109 assert!(
110 (EXPECTED_TEMPERATURE - m.temperature).abs() < F32_TOLERANCE,
111 "Expected: {}; Actual: {}",
112 EXPECTED_TEMPERATURE,
113 m.temperature
114 );
115 }
116}