use crate::Pms7003Data; use anyhow::Result; use log::{info, warn}; use std::sync::{Arc, Mutex}; use esp_idf_svc::hal::{ delay::{FreeRtos, BLOCK}, uart::UartDriver, }; // u16::from_be_bytes is too verbose fn get_u16(buf: &[u8]) -> u16 { ((buf[0] as u16) << 8) | buf[1] as u16 } fn read_pm_data(buf: &[u8; 32]) -> Option { let checksum: u16 = buf.iter().take(29).copied().map(u16::from).sum(); let csum_target = get_u16(&buf[30..32]); if checksum != csum_target { warn!("Checksum from PMS7003 READ does not match, skipping read"); return None; } Some(Pms7003Data { pm1_0_cf1: get_u16(&buf[ 4..6 ]), pm2_5_cf1: get_u16(&buf[ 6..8 ]), pm10_cf1: get_u16(&buf[ 8..10]), pm1_0_atm: get_u16(&buf[10..12]), pm2_5_atm: get_u16(&buf[12..14]), pm10_atm: get_u16(&buf[14..16]), particles_0_3um: get_u16(&buf[16..18]), particles_0_5um: get_u16(&buf[18..20]), particles_1_0um: get_u16(&buf[20..22]), particles_2_5um: get_u16(&buf[22..24]), particles_5_0um: get_u16(&buf[24..26]), particles_10um: get_u16(&buf[26..28]), }) } fn send_pms7003_command(uart: &UartDriver, cmd: u8, datah: u8, datal: u8) -> Result<()> { let mut command = [0x42u8, 0x4D, cmd, datah, datal, 0, 0]; let checksum: u16 = command.iter().take(5).copied().map(u16::from).sum(); command[5] = ((checksum >> 8) & 0xFF) as u8; command[6] = (checksum & 0xFF) as u8; uart.write(&command)?; Ok(()) } pub fn sensors_task(pm_data: Arc>, uart: &UartDriver) -> Result<()> { info!("Staring UART PM Sensor Task"); send_pms7003_command(uart, 0xE1, 0x00, 0x00)?; loop { send_pms7003_command(uart, 0xE2, 0x00, 0x00)?; let mut buf = [0_u8; 32]; let len = uart.read(&mut buf, BLOCK)?; if len > 0 { if let Some(data) = read_pm_data(&buf) { let mut pm_data = pm_data.lock().unwrap(); *pm_data = data; } } else { // info!("No bytes read"); } uart.clear_rx()?; FreeRtos::delay_ms(5000); } }