📟 pmme-device: wifi.rs added along with lib.rs and ran cargo fmt
This commit is contained in:
parent
385988401c
commit
a164f3dda1
2
pmme-device/rust-version/.dir-locals.el
Normal file
2
pmme-device/rust-version/.dir-locals.el
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
((nil
|
||||||
|
(lsp-rust-analyzer-exclude-dirs . ["./.embuild/"])))
|
1
pmme-device/rust-version/src/lib.rs
Normal file
1
pmme-device/rust-version/src/lib.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod wifi;
|
@ -1,29 +1,27 @@
|
|||||||
use anyhow::{Result, anyhow};
|
use anyhow::{anyhow, Result};
|
||||||
use esp_idf_svc::hal::gpio;
|
use esp_idf_svc::hal::{
|
||||||
use esp_idf_svc::hal::delay::FreeRtos;
|
delay::{FreeRtos, BLOCK},
|
||||||
use esp_idf_svc::hal::i2c::{I2cConfig, I2cDriver};
|
gpio,
|
||||||
use esp_idf_svc::hal::peripherals::Peripherals;
|
i2c::{I2cConfig, I2cDriver},
|
||||||
use esp_idf_svc::hal::delay::BLOCK;
|
peripherals::Peripherals,
|
||||||
use esp_idf_svc::hal::prelude::FromValueType;
|
prelude::FromValueType,
|
||||||
use esp_idf_svc::hal::units::Hertz;
|
uart::{config, UartDriver},
|
||||||
use esp_idf_svc::hal::uart::{config, UartDriver};
|
units::Hertz,
|
||||||
|
};
|
||||||
|
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
mono_font::{
|
|
||||||
ascii::{FONT_10X20},
|
|
||||||
MonoTextStyle,
|
|
||||||
},
|
|
||||||
image::{Image, ImageRaw},
|
image::{Image, ImageRaw},
|
||||||
|
mono_font::{ascii::FONT_10X20, MonoTextStyle},
|
||||||
pixelcolor::BinaryColor,
|
pixelcolor::BinaryColor,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
text::Text,
|
text::Text,
|
||||||
};
|
};
|
||||||
use ssd1306::{I2CDisplayInterface, Ssd1306, size::*, rotation::*};
|
|
||||||
use ssd1306::mode::DisplayConfig;
|
use ssd1306::mode::DisplayConfig;
|
||||||
|
use ssd1306::{rotation::*, size::*, I2CDisplayInterface, Ssd1306};
|
||||||
|
|
||||||
use std::thread;
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Pms7003Data {
|
pub struct Pms7003Data {
|
||||||
@ -47,14 +45,16 @@ pub struct Pms7003Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// u16::from_be_bytes is too verbose
|
// u16::from_be_bytes is too verbose
|
||||||
fn get_u16(buf: &[u8]) -> u16 { ((buf[0] as u16) << 8) | buf[1] as u16 }
|
fn get_u16(buf: &[u8]) -> u16 {
|
||||||
|
((buf[0] as u16) << 8) | buf[1] as u16
|
||||||
|
}
|
||||||
|
|
||||||
fn read_pm_data(buf: &[u8; 32]) -> Option<Pms7003Data> {
|
fn read_pm_data(buf: &[u8; 32]) -> Option<Pms7003Data> {
|
||||||
let checksum: u16 = buf.iter().take(29).copied().map(u16::from).sum();
|
let checksum: u16 = buf.iter().take(29).copied().map(u16::from).sum();
|
||||||
let csum_target = get_u16(&buf[30..32]);
|
let csum_target = get_u16(&buf[30..32]);
|
||||||
if checksum != csum_target {
|
if checksum != csum_target {
|
||||||
warn!("Checksum from PMS7003 READ does not match, skipping read");
|
warn!("Checksum from PMS7003 READ does not match, skipping read");
|
||||||
return None
|
return None;
|
||||||
}
|
}
|
||||||
Some(Pms7003Data {
|
Some(Pms7003Data {
|
||||||
pm1_0_cf1: get_u16(&buf[ 4..6 ]),
|
pm1_0_cf1: get_u16(&buf[ 4..6 ]),
|
||||||
@ -75,10 +75,7 @@ fn read_pm_data(buf: &[u8; 32]) -> Option<Pms7003Data> {
|
|||||||
fn send_pms7003_command(uart: &UartDriver, cmd: u8, datah: u8, datal: u8) -> Result<()> {
|
fn send_pms7003_command(uart: &UartDriver, cmd: u8, datah: u8, datal: u8) -> Result<()> {
|
||||||
let mut command = [0x42u8, 0x4D, cmd, datah, datal, 0, 0];
|
let mut command = [0x42u8, 0x4D, cmd, datah, datal, 0, 0];
|
||||||
|
|
||||||
let mut checksum: u16 = 0;
|
let checksum: u16 = command.iter().take(5).copied().map(u16::from).sum();
|
||||||
for i in 0..5 {
|
|
||||||
checksum += command[i] as u16;
|
|
||||||
}
|
|
||||||
command[5] = ((checksum >> 8) & 0xFF) as u8;
|
command[5] = ((checksum >> 8) & 0xFF) as u8;
|
||||||
command[6] = (checksum & 0xFF) as u8;
|
command[6] = (checksum & 0xFF) as u8;
|
||||||
|
|
||||||
@ -122,18 +119,26 @@ fn oled_task(pm_data: Arc<Mutex<Pms7003Data>>, i2c: I2cDriver) -> Result<()> {
|
|||||||
let im = Image::new(&raw, Point::new(32, 0));
|
let im = Image::new(&raw, Point::new(32, 0));
|
||||||
|
|
||||||
im.draw(&mut display).unwrap();
|
im.draw(&mut display).unwrap();
|
||||||
display.flush().map_err(|e| anyhow!("Could not flush display! {:?}", e))?;
|
display
|
||||||
|
.flush()
|
||||||
|
.map_err(|e| anyhow!("Could not flush display! {:?}", e))?;
|
||||||
|
|
||||||
FreeRtos::delay_ms(2000);
|
FreeRtos::delay_ms(2000);
|
||||||
loop {
|
loop {
|
||||||
let current_pm_data = pm_data.lock().unwrap().clone();
|
let current_pm_data = pm_data.lock().unwrap().clone();
|
||||||
display.clear(BinaryColor::Off).map_err(|e| anyhow!("Could not clear display! {:?}", e))?;
|
display
|
||||||
|
.clear(BinaryColor::Off)
|
||||||
|
.map_err(|e| anyhow!("Could not clear display! {:?}", e))?;
|
||||||
Text::new(
|
Text::new(
|
||||||
&format!("PM 2.5: {}", current_pm_data.pm2_5_atm),
|
&format!("PM 2.5: {}", current_pm_data.pm2_5_atm),
|
||||||
Point::new(20, 40),
|
Point::new(20, 40),
|
||||||
MonoTextStyle::new(&FONT_10X20, BinaryColor::On),
|
MonoTextStyle::new(&FONT_10X20, BinaryColor::On),
|
||||||
).draw(&mut display).map_err(|e| anyhow!("Could not draw text! {:?}", e))?;
|
)
|
||||||
display.flush().map_err(|e| anyhow!("Could not flush display! {:?}", e))?;
|
.draw(&mut display)
|
||||||
|
.map_err(|e| anyhow!("Could not draw text! {:?}", e))?;
|
||||||
|
display
|
||||||
|
.flush()
|
||||||
|
.map_err(|e| anyhow!("Could not flush display! {:?}", e))?;
|
||||||
FreeRtos::delay_ms(500);
|
FreeRtos::delay_ms(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +179,7 @@ fn main() -> Result<()> {
|
|||||||
let pm_data1 = Arc::clone(&pm_data);
|
let pm_data1 = Arc::clone(&pm_data);
|
||||||
let pm_data2 = Arc::clone(&pm_data);
|
let pm_data2 = Arc::clone(&pm_data);
|
||||||
|
|
||||||
let handles = vec! [
|
let handles = vec![
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
if let Err(e) = oled_task(pm_data1, i2c) {
|
if let Err(e) = oled_task(pm_data1, i2c) {
|
||||||
log::error!("OLED Task Error: {:?}", e);
|
log::error!("OLED Task Error: {:?}", e);
|
||||||
|
78
pmme-device/rust-version/src/wifi.rs
Normal file
78
pmme-device/rust-version/src/wifi.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use anyhow::bail;
|
||||||
|
use esp_idf_svc::{
|
||||||
|
eventloop::EspSystemEventLoop,
|
||||||
|
hal::peripheral,
|
||||||
|
wifi::{AuthMethod, BlockingWifi, ClientConfiguration, Configuration, EspWifi},
|
||||||
|
};
|
||||||
|
use log::info;
|
||||||
|
|
||||||
|
pub fn wifi(
|
||||||
|
ssid: &str,
|
||||||
|
pass: &str,
|
||||||
|
modem: impl peripheral::Peripheral<P = esp_idf_svc::hal::modem::Modem> + 'static,
|
||||||
|
sysloop: EspSystemEventLoop,
|
||||||
|
) -> anyhow::Result<Box<EspWifi<'static>>> {
|
||||||
|
let mut auth_method = AuthMethod::WPA2Personal;
|
||||||
|
if ssid.is_empty() {
|
||||||
|
bail!("Missing WiFi name")
|
||||||
|
}
|
||||||
|
if pass.is_empty() {
|
||||||
|
auth_method = AuthMethod::None;
|
||||||
|
info!("Wifi password is empty");
|
||||||
|
}
|
||||||
|
let mut esp_wifi = EspWifi::new(modem, sysloop.clone(), None)?;
|
||||||
|
|
||||||
|
let mut wifi = BlockingWifi::wrap(&mut esp_wifi, sysloop)?;
|
||||||
|
|
||||||
|
wifi.set_configuration(&Configuration::Client(ClientConfiguration::default()))?;
|
||||||
|
|
||||||
|
info!("Starting wifi...");
|
||||||
|
|
||||||
|
wifi.start()?;
|
||||||
|
|
||||||
|
info!("Scanning...");
|
||||||
|
|
||||||
|
let ap_infos = wifi.scan()?;
|
||||||
|
|
||||||
|
let ours = ap_infos.into_iter().find(|a| a.ssid == ssid);
|
||||||
|
|
||||||
|
let channel = if let Some(ours) = ours {
|
||||||
|
info!(
|
||||||
|
"Found configured access point {} on channel {}",
|
||||||
|
ssid, ours.channel
|
||||||
|
);
|
||||||
|
Some(ours.channel)
|
||||||
|
} else {
|
||||||
|
info!(
|
||||||
|
"Configured access point {} not found during scanning, will go with unknown channel",
|
||||||
|
ssid
|
||||||
|
);
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
wifi.set_configuration(&Configuration::Client(ClientConfiguration {
|
||||||
|
ssid: ssid
|
||||||
|
.try_into()
|
||||||
|
.expect("Could not parse the given SSID into WiFi config"),
|
||||||
|
password: pass
|
||||||
|
.try_into()
|
||||||
|
.expect("Could not parse the given password into WiFi config"),
|
||||||
|
channel,
|
||||||
|
auth_method,
|
||||||
|
..Default::default()
|
||||||
|
}))?;
|
||||||
|
|
||||||
|
info!("Connecting wifi...");
|
||||||
|
|
||||||
|
wifi.connect()?;
|
||||||
|
|
||||||
|
info!("Waiting for DHCP lease...");
|
||||||
|
|
||||||
|
wifi.wait_netif_up()?;
|
||||||
|
|
||||||
|
let ip_info = wifi.wifi().sta_netif().get_ip_info()?;
|
||||||
|
|
||||||
|
info!("Wifi DHCP info: {:?}", ip_info);
|
||||||
|
|
||||||
|
Ok(Box::new(esp_wifi))
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user