1#![no_std]
2
3use embedded_io::{Read, Write, ErrorType, ReadExactError};
4
5const CMD_FRAME_SIZE: usize = 7;
6const OUTPUT_FRAME_SIZE: usize = 32;
7const RESPONSE_FRAME_SIZE: usize = 8;
8const CHECKSUM_SIZE: usize = 2;
9
10type Response = [u8; RESPONSE_FRAME_SIZE];
11
12pub const MN1: u8 = 0x42;
13pub const MN2: u8 = 0x4D;
14const PASSIVE_MODE_RESPONSE: Response = [MN1, MN1, 0x00, 0x04, 0xE1, 0x00, 0x01, 0x74];
15const ACTIVE_MODE_RESPONSE: Response = [MN1, MN2, 0x00, 0x04, 0xE1, 0x01, 0x01, 0x75];
16const SLEEP_RESPONSE: Response = [MN1, MN2, 0x00, 0x04, 0xE4, 0x00, 0x01, 0x77];
17
18#[derive(Debug)]
19pub enum Error<E> {
20 Read(ReadExactError<E>),
21 Write(E),
22 ChecksumError,
23 IncorrectResponse,
24 NoResponse,
25}
26
27pub struct PmsX003Sensor<UART> {
29 uart: UART,
30}
31
32impl<UART> PmsX003Sensor<UART>
33where
34 UART: Read + Write + ErrorType,
35{
36 pub fn new(uart: UART) -> Self {
39 Self { uart }
40 }
41
42 fn read_from_device<T: AsMut<[u8]>>(&mut self, mut buffer: T) -> Result<T, Error<UART::Error>> {
43 let buf = buffer.as_mut();
44
45 let mut temp_buf = [0u8; 1];
47 loop {
48 loop {
50 match self.uart.read_exact(&mut temp_buf) {
51 Ok(()) => {
52 if temp_buf[0] == MN1 {
53 break;
54 }
55 }
56 Err(e) => return Err(Error::Read(e)),
57 }
58 }
59
60 match self.uart.read_exact(&mut temp_buf) {
62 Ok(()) => {
63 if temp_buf[0] == MN2 {
64 buf[0] = MN1;
66 buf[1] = MN2;
67 match self.uart.read_exact(&mut buf[2..]) {
68 Ok(()) => break,
69 Err(e) => return Err(Error::Read(e)),
70 }
71 }
72 }
74 Err(e) => return Err(Error::Read(e)),
75 }
76 }
77
78 Ok(buffer)
79 }
80
81 pub fn read(&mut self) -> Result<OutputFrame, Error<UART::Error>> {
83 OutputFrame::from_buffer(&self.read_from_device([0_u8; OUTPUT_FRAME_SIZE])?)
84 }
85
86 pub fn sleep(&mut self) -> Result<(), Error<UART::Error>> {
88 self.send_cmd(&create_command(0xe4, 0))?;
89 self.receive_response(SLEEP_RESPONSE)
90 }
91
92 pub fn wake(&mut self) -> Result<(), Error<UART::Error>> {
93 self.send_cmd(&create_command(0xe4, 1))
94 }
95
96 pub fn passive(&mut self) -> Result<(), Error<UART::Error>> {
98 self.send_cmd(&create_command(0xe1, 0))?;
99 self.receive_response(PASSIVE_MODE_RESPONSE)
100 }
101
102 pub fn active(&mut self) -> Result<(), Error<UART::Error>> {
104 self.send_cmd(&create_command(0xe1, 1))?;
105 self.receive_response(ACTIVE_MODE_RESPONSE)
106 }
107
108 pub fn request(&mut self) -> Result<(), Error<UART::Error>> {
110 self.send_cmd(&create_command(0xe2, 0))
111 }
112
113 fn send_cmd(&mut self, cmd: &[u8]) -> Result<(), Error<UART::Error>> {
114 match self.uart.write_all(cmd) {
115 Ok(()) => Ok(()),
116 Err(_) => Err(Error::NoResponse), }
118 }
119
120 fn receive_response(&mut self, expected_response: Response) -> Result<(), Error<UART::Error>> {
121 if self.read_from_device([0u8; RESPONSE_FRAME_SIZE])? != expected_response {
122 Err(Error::IncorrectResponse)
123 } else {
124 Ok(())
125 }
126 }
127}
128
129fn create_command(cmd: u8, data: u16) -> [u8; CMD_FRAME_SIZE] {
130 let mut buffer = [0_u8; CMD_FRAME_SIZE];
131 let mut offset = 0usize;
132
133 buffer[offset] = MN1;
135 offset += 1;
136 buffer[offset] = MN2;
137 offset += 1;
138 buffer[offset] = cmd;
139 offset += 1;
140
141 let data_bytes = data.to_be_bytes();
143 buffer[offset..offset + 2].copy_from_slice(&data_bytes);
144 offset += 2;
145
146 let checksum = buffer
148 .iter()
149 .take(CMD_FRAME_SIZE - CHECKSUM_SIZE)
150 .map(|b| *b as u16)
151 .sum::<u16>();
152
153 let checksum_bytes = checksum.to_be_bytes();
155 buffer[offset..offset + 2].copy_from_slice(&checksum_bytes);
156
157 buffer
158}
159
160#[derive(Default, Debug)]
162pub struct OutputFrame {
163 pub start1: u8,
164 pub start2: u8,
165 pub frame_length: u16,
166 pub pm1_0: u16,
167 pub pm2_5: u16,
168 pub pm10: u16,
169 pub pm1_0_atm: u16,
170 pub pm2_5_atm: u16,
171 pub pm10_atm: u16,
172 pub beyond_0_3: u16,
173 pub beyond_0_5: u16,
174 pub beyond_1_0: u16,
175 pub beyond_2_5: u16,
176 pub beyond_5_0: u16,
177 pub beyond_10_0: u16,
178 pub reserved: u16,
179 pub check: u16,
180}
181
182impl OutputFrame {
183 pub fn from_buffer<E>(buffer: &[u8; OUTPUT_FRAME_SIZE]) -> Result<Self, Error<E>> {
184 let sum: usize = buffer
185 .iter()
186 .take(OUTPUT_FRAME_SIZE - CHECKSUM_SIZE)
187 .map(|e| *e as usize)
188 .sum();
189
190 let mut frame = OutputFrame::default();
191 let mut offset = 0usize;
192
193 frame.start1 = buffer[offset];
195 offset += 1;
196 frame.start2 = buffer[offset];
197 offset += 1;
198
199 frame.frame_length = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
201 offset += 2;
202 frame.pm1_0 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
203 offset += 2;
204 frame.pm2_5 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
205 offset += 2;
206 frame.pm10 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
207 offset += 2;
208 frame.pm1_0_atm = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
209 offset += 2;
210 frame.pm2_5_atm = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
211 offset += 2;
212 frame.pm10_atm = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
213 offset += 2;
214 frame.beyond_0_3 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
215 offset += 2;
216 frame.beyond_0_5 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
217 offset += 2;
218 frame.beyond_1_0 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
219 offset += 2;
220 frame.beyond_2_5 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
221 offset += 2;
222 frame.beyond_5_0 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
223 offset += 2;
224 frame.beyond_10_0 = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
225 offset += 2;
226 frame.reserved = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
227 offset += 2;
228 frame.check = u16::from_be_bytes([buffer[offset], buffer[offset + 1]]);
229
230 if sum != frame.check as usize {
231 return Err(Error::ChecksumError);
232 }
233
234 Ok(frame)
235 }
236}
237
238