rework wifi controller share

This commit is contained in:
Empire Phoenix 2025-09-16 02:24:03 +02:00
parent 1397f5d775
commit 1c84cd00da
3 changed files with 89 additions and 47 deletions

View File

@ -7,6 +7,7 @@ use chrono::{DateTime, Utc};
use serde::Serialize; use serde::Serialize;
use alloc::string::ToString; use alloc::string::ToString;
use alloc::sync::Arc;
use alloc::{format, string::String, vec::Vec}; use alloc::{format, string::String, vec::Vec};
use core::marker::PhantomData; use core::marker::PhantomData;
use core::net::{IpAddr, Ipv4Addr}; use core::net::{IpAddr, Ipv4Addr};
@ -14,7 +15,11 @@ use core::str::FromStr;
use embassy_executor::{SendSpawner, Spawner}; use embassy_executor::{SendSpawner, Spawner};
use embassy_net::tcp::TcpSocket; use embassy_net::tcp::TcpSocket;
use embassy_net::{IpListenEndpoint, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4}; use embassy_net::{IpListenEndpoint, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::Mutex;
use embassy_time::{Duration, Instant, Timer}; use embassy_time::{Duration, Instant, Timer};
use embedded_storage::nor_flash::ReadNorFlash;
use embedded_storage::Storage;
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState, Slot}; use esp_bootloader_esp_idf::ota::{Ota, OtaImageState, Slot};
use esp_bootloader_esp_idf::partitions::{Error, FlashRegion, PartitionEntry, PartitionTable}; use esp_bootloader_esp_idf::partitions::{Error, FlashRegion, PartitionEntry, PartitionTable};
use esp_hal::gpio::Input; use esp_hal::gpio::Input;
@ -23,8 +28,8 @@ use esp_hal::rtc_cntl::sleep::RtcSleepConfig;
use esp_println::{print, println}; use esp_println::{print, println};
use esp_storage::FlashStorage; use esp_storage::FlashStorage;
use esp_wifi::wifi::{ use esp_wifi::wifi::{
AccessPointConfiguration, Configuration, Interfaces, WifiController, WifiDevice, WifiEvent, AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
WifiState, WifiController, WifiDevice, WifiEvent, WifiState,
}; };
use log::{info, warn}; use log::{info, warn};
@ -67,7 +72,7 @@ pub struct Esp<'a> {
pub rng: Rng, pub rng: Rng,
//first starter (ap or sta will take these) //first starter (ap or sta will take these)
pub interfaces: Option<Interfaces<'static>>, pub interfaces: Option<Interfaces<'static>>,
pub controller: Option<WifiController<'static>>, pub controller: Arc<Mutex<CriticalSectionRawMutex, WifiController<'static>>>,
//only filled, if a useable mqtt client with working roundtrip could be established //only filled, if a useable mqtt client with working roundtrip could be established
pub(crate) mqtt_client: Option<MqttClient<'a>>, pub(crate) mqtt_client: Option<MqttClient<'a>>,
@ -76,7 +81,7 @@ pub struct Esp<'a> {
pub(crate) wall_clock_offset: u64, pub(crate) wall_clock_offset: u64,
pub ota: Ota<'static, FlashStorage>, pub ota: Ota<'static, FlashStorage>,
pub ota_next: &'static PartitionEntry<'static>, pub ota_next: &'static mut FlashRegion<'static, FlashStorage>,
} }
pub struct IpInfo { pub struct IpInfo {
@ -85,8 +90,6 @@ pub struct IpInfo {
gateway: IpAddr, gateway: IpAddr,
} }
struct AccessPointInfo {}
macro_rules! mk_static { macro_rules! mk_static {
($t:ty,$val:expr) => {{ ($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new(); static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
@ -151,8 +154,7 @@ impl Esp<'_> {
} }
pub async fn flash_ota(&mut self) -> anyhow::Result<()> { pub async fn flash_ota(&mut self) -> anyhow::Result<()> {
let mut storage_ota_next = FlashStorage::new(); let capacity = self.ota_next.capacity();
let ota_next = self.ota_next.as_embedded_storage(&mut storage_ota_next);
bail!("not implemented") bail!("not implemented")
} }
@ -162,17 +164,14 @@ impl Esp<'_> {
DateTime::from_timestamp_millis(wall_clock as i64).unwrap() DateTime::from_timestamp_millis(wall_clock as i64).unwrap()
} }
pub(crate) async fn wifi_scan(&mut self) -> anyhow::Result<Vec<AccessPointInfo>> { pub(crate) async fn wifi_scan(&mut self) -> Vec<AccessPointInfo> {
bail!("todo"); info!("start wifi scan");
// self.wifi_driver.start_scan( let mut lock = self.controller.try_lock().unwrap();
// &ScanConfig { info!("start wifi scan lock");
// scan_type: ScanType::Passive(Duration::from_secs(5)), let scan_config = ScanConfig::default();
// show_hidden: false, let rv = lock.scan_with_config_sync(scan_config).unwrap();
// ..Default::default() info!("end wifi scan lock");
// }, return rv;
// true,
// )?;
// anyhow::Ok(self.wifi_driver.get_scan_result()?)
} }
pub(crate) fn last_pump_time(&self, plant: usize) -> Option<DateTime<Utc>> { pub(crate) fn last_pump_time(&self, plant: usize) -> Option<DateTime<Utc>> {
@ -244,8 +243,9 @@ impl Esp<'_> {
); );
let stack = mk_static!(Stack, stack); let stack = mk_static!(Stack, stack);
let controller = self.controller.take().unwrap(); spawner
spawner.spawn(connection(controller, ssid)).ok(); .spawn(connection(self.controller.clone(), ssid))
.ok();
spawner.spawn(net_task(runner)).ok(); spawner.spawn(net_task(runner)).ok();
spawner.spawn(run_dhcp(stack.clone(), gw_ip_addr_str)).ok(); spawner.spawn(run_dhcp(stack.clone(), gw_ip_addr_str)).ok();
@ -809,29 +809,27 @@ async fn run_dhcp(stack: Stack<'static>, gw_ip_addr: &'static str) {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn connection(mut controller: WifiController<'static>, ssid: String) { async fn connection(
controller: Arc<Mutex<CriticalSectionRawMutex, WifiController<'static>>>,
ssid: String,
) {
println!("start connection task"); println!("start connection task");
println!("Device capabilities: {:?}", controller.capabilities()); println!(
loop { "Device capabilities: {:?}",
match esp_wifi::wifi::wifi_state() { controller.lock().await.capabilities()
WifiState::ApStarted => { );
// wait until we're no longer connected let client_config = Configuration::AccessPoint(AccessPointConfiguration {
controller.wait_for_event(WifiEvent::ApStop).await; ssid: ssid.clone(),
Timer::after(Duration::from_millis(5000)).await ..Default::default()
} });
_ => {} controller
} .lock()
if !matches!(controller.is_started(), core::result::Result::Ok(true)) { .await
let client_config = Configuration::AccessPoint(AccessPointConfiguration { .set_configuration(&client_config)
ssid: ssid.clone(), .unwrap();
..Default::default() println!("Starting wifi");
}); controller.lock().await.start_async().await.unwrap();
controller.set_configuration(&client_config).unwrap(); println!("Wifi started!");
println!("Starting wifi");
controller.start_async().await.unwrap();
println!("Wifi started!");
}
}
} }
#[embassy_executor::task] #[embassy_executor::task]

View File

@ -21,6 +21,7 @@ use crate::{
}; };
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::format; use alloc::format;
use alloc::sync::Arc;
use anyhow::{Ok, Result}; use anyhow::{Ok, Result};
use async_trait::async_trait; use async_trait::async_trait;
use embassy_executor::Spawner; use embassy_executor::Spawner;
@ -273,10 +274,15 @@ impl PlantHal {
}; };
let ota_next = mk_static!(PartitionEntry, ota_partition); let ota_next = mk_static!(PartitionEntry, ota_partition);
let storage_ota_next = mk_static!(FlashStorage, FlashStorage::new());
let ota_next = mk_static!(
FlashRegion<FlashStorage>,
ota_next.as_embedded_storage(storage_ota_next)
);
let mut esp = Esp { let mut esp = Esp {
rng, rng,
controller: Some(controller), controller: Arc::new(Mutex::new(controller)),
interfaces: Some(interfaces), interfaces: Some(interfaces),
boot_button, boot_button,
mqtt_client: None, mqtt_client: None,

View File

@ -21,8 +21,8 @@ use log::info;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Debug)] #[derive(Serialize, Debug)]
struct SSIDList<'a> { struct SSIDList {
ssids: Vec<&'a String>, ssids: Vec<String>,
} }
#[derive(Serialize, Debug)] #[derive(Serialize, Debug)]
@ -369,6 +369,7 @@ impl Handler for HttpHandler {
"/files" => Some(list_files(conn).await), "/files" => Some(list_files(conn).await),
"/log_localization" => Some(get_log_localization_config(conn).await), "/log_localization" => Some(get_log_localization_config(conn).await),
"/log" => Some(get_log(conn).await), "/log" => Some(get_log(conn).await),
"/wifiscan" => Some(wifi_scan(conn).await),
_ => None, _ => None,
}; };
match json { match json {
@ -377,7 +378,17 @@ impl Handler for HttpHandler {
} }
} }
}, },
Method::Options | Method::Delete | Method::Head | Method::Post | Method::Put => None, Method::Post => {
let json = match path {
"/wifiscan" => Some(wifi_scan(conn).await),
_ => None,
};
match json {
None => None,
Some(json) => Some(handle_json(conn, json).await?),
}
}
Method::Options | Method::Delete | Method::Head | Method::Put => None,
_ => None, _ => None,
}; };
let code = match status { let code = match status {
@ -406,6 +417,33 @@ impl Handler for HttpHandler {
// reboot_now_for_reboot.store(true, std::sync::atomic::Ordering::Relaxed); // reboot_now_for_reboot.store(true, std::sync::atomic::Ordering::Relaxed);
// anyhow::Ok(()) // anyhow::Ok(())
// fn wifi_scan(
// _request: &mut Request<&mut EspHttpConnection>,
// ) -> Result<Option<std::string::String>, anyhow::Error> {
// let mut board = BOARD_ACCESS.lock().unwrap();
// let scan_result = board.board_hal.get_esp().wifi_scan()?;
// let mut ssids: Vec<&String<32>> = Vec::new();
// scan_result.iter().for_each(|s| ssids.push(&s.ssid));
// let ssid_json = serde_json::to_string(&SSIDList { ssids })?;
// log::info!("Sending ssid list {}", &ssid_json);
// anyhow::Ok(Some(ssid_json))
// }
async fn wifi_scan<T, const N: usize>(
_request: &mut Connection<'_, T, N>,
) -> Result<Option<String>, anyhow::Error> {
let mut board = BOARD_ACCESS.get().await.lock().await;
info!("start wifi scan");
let scan_result = board.board_hal.get_esp().wifi_scan().await;
let mut ssids: Vec<String> = Vec::new();
scan_result
.iter()
.for_each(|s| ssids.push(s.ssid.to_string()));
let ssid_json = serde_json::to_string(&SSIDList { ssids })?;
info!("Sending ssid list {}", &ssid_json);
anyhow::Ok(Some(ssid_json))
}
async fn get_log<T, const N: usize>( async fn get_log<T, const N: usize>(
_request: &mut Connection<'_, T, N>, _request: &mut Connection<'_, T, N>,
) -> Result<Option<String>, anyhow::Error> { ) -> Result<Option<String>, anyhow::Error> {