not working wip of station mode

This commit is contained in:
2025-09-25 22:32:10 +02:00
parent e20b474dfd
commit 336961f0a0
3 changed files with 150 additions and 118 deletions

View File

@@ -1,6 +1,6 @@
use crate::bail;
use crate::config::{NetworkConfig, PlantControllerConfig};
use crate::hal::PLANT_COUNT;
use crate::hal::{PLANT_COUNT, TIME_ACCESS};
use crate::log::{LogMessage, LOG_ACCESS};
use chrono::{DateTime, Utc};
use serde::Serialize;
@@ -14,8 +14,11 @@ use alloc::borrow::ToOwned;
use core::marker::PhantomData;
use core::net::{IpAddr, Ipv4Addr};
use core::str::FromStr;
use core::sync::atomic::Ordering;
use core::sync::atomic::Ordering::Relaxed;
use edge_dhcp::io::server::run;
use embassy_executor::Spawner;
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
use embassy_net::{DhcpConfig, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::Mutex;
use embassy_time::{Duration, Timer};
@@ -28,13 +31,11 @@ use esp_hal::rtc_cntl::sleep::RtcSleepConfig;
use esp_hal::system::software_reset;
use esp_println::println;
use esp_storage::FlashStorage;
use esp_wifi::wifi::{
AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
ScanTypeConfig, WifiController, WifiDevice,
};
use esp_wifi::wifi::{AccessPointConfiguration, AccessPointInfo, AuthMethod, ClientConfiguration, Configuration, Interfaces, ScanConfig, ScanTypeConfig, WifiController, WifiDevice, WifiState};
use littlefs2::fs::Filesystem;
use littlefs2_core::{FileType, PathBuf, SeekFrom};
use log::info;
use portable_atomic::AtomicBool;
#[esp_hal::ram(rtc_fast, persistent)]
static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT];
@@ -75,7 +76,8 @@ pub struct Esp<'a> {
pub fs: Arc<Mutex<CriticalSectionRawMutex, Filesystem<'static, LittleFs2Filesystem>>>,
pub rng: Rng,
//first starter (ap or sta will take these)
pub interfaces: Option<Interfaces<'static>>,
pub interface_sta: Option<WifiDevice<'static>>,
pub interface_ap: Option<WifiDevice<'static>>,
pub controller: Arc<Mutex<CriticalSectionRawMutex, WifiController<'static>>>,
//only filled, if a useable mqtt client with working roundtrip could be established
@@ -288,7 +290,7 @@ impl Esp<'_> {
}
}
pub(crate) async fn wifi_ap(&mut self) -> FatResult<Stack<'static>> {
pub(crate) async fn wifi_ap(&mut self, fallback: bool) -> FatResult<Stack<'static>> {
let ssid = match self.load_config().await {
Ok(config) => config.network.ap_ssid.as_str().to_string(),
Err(_) => "PlantCtrl Emergency Mode".to_string(),
@@ -296,7 +298,7 @@ impl Esp<'_> {
let spawner = Spawner::for_current_executor().await;
let device = self.interfaces.take().unwrap().ap;
let device = self.interface_ap.take().unwrap();
let gw_ip_addr_str = "192.168.71.1";
let gw_ip_addr = Ipv4Addr::from_str(gw_ip_addr_str).expect("failed to parse gateway ip");
@@ -308,6 +310,86 @@ impl Esp<'_> {
let seed = (self.rng.random() as u64) << 32 | self.rng.random() as u64;
println!("init secondary stack");
// Init network stack
let (stack, runner) = embassy_net::new(
device,
config,
mk_static!(StackResources<4>, StackResources::<4>::new()),
seed,
);
let stack = mk_static!(Stack, stack);
let client_config = Configuration::AccessPoint(AccessPointConfiguration {
ssid: ssid.clone(),
..Default::default()
});
println!("stop old");
self.controller.lock().await.stop()?;
self.controller
.lock()
.await
.set_configuration(&client_config)?;
println!("start new");
self.controller.lock().await.start()?;
println!("start net task");
spawner.spawn(net_task(runner)).ok();
println!("run dhcp");
spawner.spawn(run_dhcp(stack.clone(), gw_ip_addr_str)).ok();
loop {
println!("waiting for wifi ap link up");
if stack.is_link_up() {
break;
}
Timer::after(Duration::from_millis(500)).await;
}
while !stack.is_config_up() {
println!("waiting for wifi ap config up");
Timer::after(Duration::from_millis(100)).await
}
println!(
"Connect to the AP `${ssid}` and point your browser to http://{gw_ip_addr_str}/"
);
stack
.config_v4()
.inspect(|c| println!("ipv4 config: {c:?}"));
Ok(stack.clone())
}
pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> FatResult<Stack<'static>> {
esp_wifi::wifi_set_log_verbose();
let ssid = network_config.ssid.clone();
match &ssid {
Some(ssid) => {
if ssid.is_empty() {
bail!("Wifi ssid was empty")
}
}
None => {
bail!("Wifi ssid was empty")
}
}
let ssid = ssid.unwrap().to_string();
info!("attempting to connect wifi {ssid}");
let password = match network_config.password {
Some(ref password) => password.to_string(),
None => "".to_string(),
};
let max_wait = network_config.max_wait;
let spawner = Spawner::for_current_executor().await;
let device = self.interface_sta.take().unwrap();
let config = embassy_net::Config::dhcpv4(DhcpConfig::default());
let seed = (self.rng.random() as u64) << 32 | self.rng.random() as u64;
// Init network stack
let (stack, runner) = embassy_net::new(
device,
@@ -317,28 +399,58 @@ impl Esp<'_> {
);
let stack = mk_static!(Stack, stack);
spawner
.spawn(connection(self.controller.clone(), ssid.to_owned()))
.ok();
let client_config = Configuration::Client(ClientConfiguration {
ssid,
bssid: None,
auth_method: AuthMethod::None,
password,
channel: None,
});
self.controller
.lock()
.await
.set_configuration(&client_config)?;
spawner.spawn(net_task(runner)).ok();
spawner.spawn(run_dhcp(stack.clone(), gw_ip_addr_str)).ok();
self.controller.lock().await.start_async().await?;
let timeout = TIME_ACCESS.get().await.current_time_us() + max_wait as u64 * 1000;
loop {
if stack.is_link_up() {
break;
let state = esp_wifi::wifi::ap_state();
println!("waiting wifi sta ready {:?}", state);
match state{
WifiState::StaStarted => {
self.controller.lock().await.connect()?;
break;
}
WifiState::StaConnected => {}
WifiState::StaDisconnected => {}
WifiState::StaStopped => {}
WifiState::ApStarted => {}
WifiState::ApStopped => {}
WifiState::Invalid => {}
}
if TIME_ACCESS.get().await.current_time_us() > timeout {
bail!("Timeout waiting for wifi link up")
}
}
while !stack.is_link_up() {
if TIME_ACCESS.get().await.current_time_us() > timeout {
bail!("Timeout waiting for wifi link up")
}
println!("waiting for wifi link up");
Timer::after(Duration::from_millis(500)).await;
}
while !stack.is_config_up() {
if TIME_ACCESS.get().await.current_time_us() > timeout {
bail!("Timeout waiting for wifi config up")
}
println!("waiting for wifi config up");
Timer::after(Duration::from_millis(100)).await
}
println!(
"Connect to the AP `${ssid}` and point your browser to http://{gw_ip_addr_str}/"
);
stack
.config_v4()
.inspect(|c| println!("ipv4 config: {c:?}"));
Ok(stack.clone())
}
@@ -370,76 +482,6 @@ impl Esp<'_> {
//};
}
pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> FatResult<IpInfo> {
let _ssid = network_config.ssid.clone();
match &_ssid {
Some(ssid) => {
if ssid.is_empty() {
bail!("Wifi ssid was empty")
}
}
None => {
bail!("Wifi ssid was empty")
}
}
let _ssid = _ssid.unwrap();
let _password = network_config.password.clone();
let _max_wait = network_config.max_wait;
bail!("todo")
// match password {
// Some(pw) => {
// //TODO expect error due to invalid pw or similar! //call this during configuration and check if works, revert to config mode if not
// self.wifi_driver.set_configuration(&Configuration::Client(
// ClientConfiguration {
// ssid,
// password: pw,
// ..Default::default()
// },
// ))?;
// }
// None => {
// self.wifi_driver.set_configuration(&Configuration::Client(
// ClientConfiguration {
// ssid,
// auth_method: AuthMethod::None,
// ..Default::default()
// },
// ))?;
// }
// }
//
// self.wifi_driver.start()?;
// self.wifi_driver.connect()?;
//
// let delay = Delay::new_default();
// let mut counter = 0_u32;
// while !self.wifi_driver.is_connected()? {
// delay.delay_ms(250);
// counter += 250;
// if counter > max_wait {
// //ignore these errors, Wi-Fi will not be used this
// self.wifi_driver.disconnect().unwrap_or(());
// self.wifi_driver.stop().unwrap_or(());
// bail!("Did not manage wifi connection within timeout");
// }
// }
// log::info!("Should be connected now, waiting for link to be up");
//
// while !self.wifi_driver.is_up()? {
// delay.delay_ms(250);
// counter += 250;
// if counter > max_wait {
// //ignore these errors, Wi-Fi will not be used this
// self.wifi_driver.disconnect().unwrap_or(());
// self.wifi_driver.stop().unwrap_or(());
// bail!("Did not manage wifi connection within timeout");
// }
// }
// //update freertos registers ;)
// let address = self.wifi_driver.sta_netif().get_ip_info()?;
// log(LogMessage::WifiInfo, 0, 0, "", &format!("{address:?}"));
// anyhow::Ok(address)
}
pub(crate) async fn load_config(&mut self) -> FatResult<PlantControllerConfig> {
let cfg = PathBuf::try_from(CONFIG_FILE).unwrap();
let data = self.fs.lock().await.read::<4096>(&cfg)?;
@@ -796,25 +838,8 @@ async fn run_dhcp(stack: Stack<'static>, gw_ip_addr: &'static str) {
}
}
#[embassy_executor::task]
async fn connection(
controller: Arc<Mutex<CriticalSectionRawMutex, WifiController<'static>>>,
ssid: String,
) {
let client_config = Configuration::AccessPoint(AccessPointConfiguration {
ssid: ssid.clone(),
..Default::default()
});
controller
.lock()
.await
.set_configuration(&client_config)
.unwrap();
controller.lock().await.start_async().await.unwrap();
println!("Wifi started!");
}
#[embassy_executor::task]
#[embassy_executor::task(pool_size = 2)]
async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) {
runner.run().await
}