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

View File

@ -21,6 +21,7 @@ use crate::{
};
use alloc::boxed::Box;
use alloc::format;
use alloc::sync::Arc;
use anyhow::{Ok, Result};
use async_trait::async_trait;
use embassy_executor::Spawner;
@ -273,10 +274,15 @@ impl PlantHal {
};
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 {
rng,
controller: Some(controller),
controller: Arc::new(Mutex::new(controller)),
interfaces: Some(interfaces),
boot_button,
mqtt_client: None,

View File

@ -21,8 +21,8 @@ use log::info;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Debug)]
struct SSIDList<'a> {
ssids: Vec<&'a String>,
struct SSIDList {
ssids: Vec<String>,
}
#[derive(Serialize, Debug)]
@ -369,6 +369,7 @@ impl Handler for HttpHandler {
"/files" => Some(list_files(conn).await),
"/log_localization" => Some(get_log_localization_config(conn).await),
"/log" => Some(get_log(conn).await),
"/wifiscan" => Some(wifi_scan(conn).await),
_ => None,
};
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,
};
let code = match status {
@ -406,6 +417,33 @@ impl Handler for HttpHandler {
// reboot_now_for_reboot.store(true, std::sync::atomic::Ordering::Relaxed);
// 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>(
_request: &mut Connection<'_, T, N>,
) -> Result<Option<String>, anyhow::Error> {