not working wip of station mode
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
@@ -381,11 +381,14 @@ impl PlantHal {
|
||||
lfs2Filesystem::mount(alloc, lfs2filesystem).expect("Could not mount lfs2 filesystem"),
|
||||
));
|
||||
|
||||
let ap = interfaces.ap;
|
||||
let sta = interfaces.sta;
|
||||
let mut esp = Esp {
|
||||
fs,
|
||||
rng,
|
||||
controller: Arc::new(Mutex::new(controller)),
|
||||
interfaces: Some(interfaces),
|
||||
interface_sta : Some(sta),
|
||||
interface_ap : Some(ap),
|
||||
boot_button,
|
||||
mqtt_client: None,
|
||||
ota,
|
||||
|
@@ -234,7 +234,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
{
|
||||
info!("No wifi configured, starting initial config mode");
|
||||
|
||||
let stack = board.board_hal.get_esp().wifi_ap().await?;
|
||||
let stack = board.board_hal.get_esp().wifi_ap(false).await?;
|
||||
|
||||
let reboot_now = Arc::new(AtomicBool::new(false));
|
||||
println!("starting webserver");
|
||||
@@ -243,8 +243,6 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
wait_infinity(board, WaitType::MissingConfig, reboot_now.clone()).await;
|
||||
}
|
||||
|
||||
info!("attempting to connect wifi ");
|
||||
|
||||
let mut stack = Option::None;
|
||||
let network_mode = if board.board_hal.get_config().network.ssid.is_some() {
|
||||
try_connect_wifi_sntp_mqtt(&mut board, *&mut stack).await
|
||||
@@ -261,7 +259,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
|
||||
let res = {
|
||||
let esp = board.board_hal.get_esp();
|
||||
esp.wifi_ap().await
|
||||
esp.wifi_ap(true).await
|
||||
|
||||
};
|
||||
match res {
|
||||
@@ -898,10 +896,16 @@ async fn publish_firmware_info(
|
||||
let _ = esp.mqtt_publish("/state", "online".as_bytes()).await;
|
||||
}
|
||||
|
||||
async fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<'static, CriticalSectionRawMutex, HAL<'static>>, stack_store:Option<Stack<'_>>) -> NetworkMode {
|
||||
async fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<'static, CriticalSectionRawMutex, HAL<'static>>, mut stack_store:Option<Stack<'_>>) -> NetworkMode {
|
||||
let nw_conf = &board.board_hal.get_config().network.clone();
|
||||
match board.board_hal.get_esp().wifi(nw_conf).await {
|
||||
Ok(ip_info) => {
|
||||
Ok(stack) => {
|
||||
stack_store = Some(stack);
|
||||
|
||||
loop {
|
||||
println!("wifi stuff");
|
||||
Timer::after_millis(1000).await;
|
||||
}
|
||||
let sntp_mode: SntpMode = match board.board_hal.get_esp().sntp(1000 * 10).await {
|
||||
Ok(new_time) => {
|
||||
info!("Using time from sntp");
|
||||
@@ -932,7 +936,7 @@ async fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<'static, CriticalSect
|
||||
NetworkMode::WIFI {
|
||||
sntp: sntp_mode,
|
||||
mqtt: mqtt_connected,
|
||||
ip_address: ip_info.ip.to_string(),
|
||||
ip_address: stack.hardware_address().to_string(),
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
|
Reference in New Issue
Block a user