Own wifi #65

Merged
rhetenor merged 3 commits from own-wifi into main 2026-09-15 20:55:39 +02:00
5 changed files with 109 additions and 46 deletions
Showing only changes of commit 4f251de3d5 - Show all commits
+1 -1
View File
@@ -2,7 +2,7 @@
runner = "espflash flash --monitor --chip esp32s3" runner = "espflash flash --monitor --chip esp32s3"
[env] [env]
ESP_LOG = "debug" ESP_LOG = "info"
WM_CONN = '{"ssid": "Wokwi-GUEST", "psk": "", "data": {}}' WM_CONN = '{"ssid": "Wokwi-GUEST", "psk": "", "data": {}}'
[build] [build]
+6 -1
View File
@@ -52,7 +52,11 @@ binary_serde = "1.0.25"
static_assertions = { version = "1.1.0", default-features = false } static_assertions = { version = "1.1.0", default-features = false }
embedded-text = "0.7.3" embedded-text = "0.7.3"
esp-nvs = { version = "0.5.0", features = ["esp32s3"] } esp-nvs = { version = "0.5.0", features = ["esp32s3"] }
esp-backtrace = { version = "0.19.0", features = ["esp32s3", "panic-handler", "println"] } esp-backtrace = { version = "0.19.0", features = [
"esp32s3",
"panic-handler",
"println",
] }
esp-radio = { version = "0.18.0", features = ["esp32s3", "wifi"] } esp-radio = { version = "0.18.0", features = ["esp32s3", "wifi"] }
[build-dependencies] [build-dependencies]
@@ -82,6 +86,7 @@ opt-level = 's'
[features] [features]
default = [] default = []
wokwi = [] wokwi = []
nop_tertiary = []
[lints.clippy] [lints.clippy]
manual_async_fn = "allow" manual_async_fn = "allow"
+14 -6
View File
@@ -129,15 +129,24 @@ async fn main(spawner: Spawner) {
.expect("failed to create nvs"), .expect("failed to create nvs"),
)); ));
let wifi_store = WifiStore::new(nvs.clone()).await.expect("Could not initialize WiFi store"); let wifi_store = WifiStore::new(nvs.clone())
let init_credentials = Wifi::initialize_credentials(&wifi_store).await.expect("Could not get init WiFi credentials"); .await
let wifi = Wifi::new(esp_peripherals.WIFI, init_credentials).await.expect("Could not initialize WiFi"); .expect("Could not initialize WiFi store");
let mut wifi = Wifi::new(esp_peripherals.WIFI).expect("Could not initialize WiFi");
wifi.connect_with_stored_credentials(&wifi_store)
.await
.expect("could not connect initially");
let card_store = CardStore::new(nvs.clone()) let card_store = CardStore::new(nvs.clone())
.await .await
.expect("Could not initialize Card Store"); .expect("Could not initialize Card Store");
let store = Store { card_store, wifi_store }; let store = Store {
card_store,
wifi_store,
};
let rtc = Rtc::new(esp_peripherals.LPWR); let rtc = Rtc::new(esp_peripherals.LPWR);
let peripherals = Box::leak(Box::new(Peripherals { let peripherals = Box::leak(Box::new(Peripherals {
@@ -191,8 +200,7 @@ async fn main(spawner: Spawner) {
.expect("nfc scanner task failed"), .expect("nfc scanner task failed"),
); );
spawner.spawn( spawner.spawn(
wait_for_wifi_credentials(outputs, peripherals) wait_for_wifi_credentials(outputs, peripherals).expect("wifi credential task failed"),
.expect("wifi credential task failed"),
); );
core::future::pending::<()>().await core::future::pending::<()>().await
+41 -2
View File
@@ -14,6 +14,14 @@ pub struct TertiaryDisplayPinConfiguration<'a> {
pub i2c: I2cBus<'a>, pub i2c: I2cBus<'a>,
} }
#[cfg(feature = "nop_tertiary")]
impl<'a> TertiaryDisplayPinConfiguration<'a> {
pub fn build(self) -> Result<TertiaryDisplay<'a>, Self> {
Ok(TertiaryDisplay { phantom: &() })
}
}
#[cfg(not(feature = "nop_tertiary"))]
impl<'a> TertiaryDisplayPinConfiguration<'a> { impl<'a> TertiaryDisplayPinConfiguration<'a> {
pub fn build(self) -> Result<TertiaryDisplay<'a>, Self> { pub fn build(self) -> Result<TertiaryDisplay<'a>, Self> {
let device = AtomicDevice::new(self.i2c); let device = AtomicDevice::new(self.i2c);
@@ -61,19 +69,50 @@ impl<'a> core::fmt::Display for TertiaryDisplayWriteError<'a> {
} }
} }
#[cfg(not(feature = "nop_tertiary"))]
pub struct TertiaryDisplay<'a> { pub struct TertiaryDisplay<'a> {
display: TertiaryDisplayRaw<'a>, display: TertiaryDisplayRaw<'a>,
charset: CustomCharset, charset: CustomCharset,
} }
#[cfg(feature = "nop_tertiary")]
pub struct TertiaryDisplay<'a> {
phantom: &'a (),
}
#[cfg(feature = "nop_tertiary")]
impl<'a> TertiaryDisplay<'a> { impl<'a> TertiaryDisplay<'a> {
pub const WIDTH: usize = 16; pub const WIDTH: usize = 16;
pub const ROWS: usize = 2; pub const ROWS: usize = 2;
pub fn inner_mut(&mut self) -> &mut TertiaryDisplayRaw<'a> { pub fn load_charset(&mut self, charset: CustomCharset) -> Result<(), TertiaryDisplayError<'a>> {
&mut self.display log::info!("nop tertiary");
Ok(())
} }
pub fn clear(&mut self) -> Result<(), TertiaryDisplayError<'a>> {
log::info!("nop tertiary");
Ok(())
}
/// Writes text to the LCD. Normal strings wrap by default but this can be controlled
/// via explicit [`Lines::checked`].
pub fn write<'b, L: Into<Lines<'b>>>(
&mut self,
text: L,
) -> Result<(), TertiaryDisplayWriteError<'a>> {
log::info!("nop tertiary");
log::info!("{:?}", text.into());
Ok(())
}
}
#[cfg(not(feature = "nop_tertiary"))]
impl<'a> TertiaryDisplay<'a> {
pub const WIDTH: usize = 16;
pub const ROWS: usize = 2;
pub fn load_charset(&mut self, charset: CustomCharset) -> Result<(), TertiaryDisplayError<'a>> { pub fn load_charset(&mut self, charset: CustomCharset) -> Result<(), TertiaryDisplayError<'a>> {
self.charset = charset; self.charset = charset;
for (index, charmap) in self for (index, charmap) in self
+46 -35
View File
@@ -1,8 +1,6 @@
use crate::Mutex; use crate::Mutex;
use esp_radio::wifi::sta::StationConfig;
use esp_radio::wifi::Config;
use crate::alloc::string::ToString;
use crate::Signal; use crate::Signal;
use crate::alloc::string::ToString;
use crate::navigation::outputs::Outputs; use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
#[cfg(not(feature = "wokwi"))] #[cfg(not(feature = "wokwi"))]
@@ -11,7 +9,9 @@ use crate::peripherals::storage::wifistore::WifiStoreError;
use alloc::string::String; use alloc::string::String;
use core::error::Error; use core::error::Error;
use core::fmt::Display; use core::fmt::Display;
use esp_radio::wifi::Config;
use esp_radio::wifi::WifiController; use esp_radio::wifi::WifiController;
use esp_radio::wifi::sta::StationConfig;
use esp_radio::*; use esp_radio::*;
#[derive(Debug)] #[derive(Debug)]
@@ -22,7 +22,6 @@ pub struct WifiCredentials {
pub static WIFI_CREDENTIALS: Signal<WifiCredentials> = Signal::new(); pub static WIFI_CREDENTIALS: Signal<WifiCredentials> = Signal::new();
#[derive(Debug)] #[derive(Debug)]
pub struct Wifi { pub struct Wifi {
controller: WifiController<'static>, controller: WifiController<'static>,
@@ -61,49 +60,49 @@ impl From<esp_radio::wifi::WifiError> for WifiError {
} }
impl Wifi { impl Wifi {
pub async fn new( pub fn new(wifi: esp_hal::peripherals::WIFI<'static>) -> Result<Self, WifiError> {
wifi: esp_hal::peripherals::WIFI<'static>, log::info!("creating new wifi");
credentials: Option<WifiCredentials>
) -> Result<Self, WifiError> {
let wifi = wifi::new(wifi, Default::default())?; let wifi = wifi::new(wifi, Default::default())?;
let mut instance = Self { Ok(Self {
controller: wifi.0, controller: wifi.0,
interfaces: wifi.1 interfaces: wifi.1,
}; })
if let Some(creds) = credentials {
instance.set_station(creds).await?;
}
Ok(instance)
} }
// get wifi credentials from env WIFI_SSID; WIFI_PASS (priority) or storage // get wifi credentials from env WIFI_SSID; WIFI_PASS (priority) or storage
pub async fn initialize_credentials( pub async fn connect_with_stored_credentials(
&mut self,
wifi_store: &WifiStore, wifi_store: &WifiStore,
) -> Result<Option<WifiCredentials>, WifiError> { ) -> Result<(), WifiError> {
let option_stored_credentials = wifi_store.load_credentials().await?; let option_stored_credentials = wifi_store.load_credentials().await?;
let env_ssid = option_env!("WIFI_SSID"); let env_ssid = option_env!("WIFI_SSID");
let env_pass = option_env!("WIFI_PASS"); let env_pass = option_env!("WIFI_PASS");
if env_ssid.is_none() && option_stored_credentials.is_none() { if env_ssid.is_none() && option_stored_credentials.is_none() {
log::info!("no initial wifi credentials"); log::info!("no initial wifi credentials. do not connect");
return Ok(None); return Ok(());
} }
let stored_credentials = option_stored_credentials.expect("checked value before"); let stored_credentials = option_stored_credentials.unwrap_or(WifiCredentials {
pass: "".to_string(),
ssid: "".to_string(),
});
let ssid = env_ssid.map_or(stored_credentials.ssid, |v| v.to_string()); let ssid = env_ssid.map_or(stored_credentials.ssid, |v| v.to_string());
let pass = env_pass.map_or(stored_credentials.pass, |v| v.to_string()); let pass = env_pass.map_or(stored_credentials.pass, |v| v.to_string());
log::info!("initial wifi credentials:\nssid:{ssid}, pass:{pass}"); log::info!("initial wifi credentials:\nssid:{ssid}, pass:{pass}");
Ok(Some(WifiCredentials {ssid, pass})) let credentials = WifiCredentials { ssid, pass };
self.set_station(credentials).await?;
self.connect().await?;
Ok(())
} }
pub async fn connect(&mut self) -> Result<(), WifiError>{ pub async fn connect(&mut self) -> Result<(), WifiError> {
log::info!("connecting wifi..."); log::info!("connecting wifi...");
let stationinfo = self.controller.connect_async().await?; let stationinfo = self.controller.connect_async().await?;
@@ -114,12 +113,14 @@ impl Wifi {
} }
pub async fn set_station(&mut self, credentials: WifiCredentials) -> Result<(), WifiError> { pub async fn set_station(&mut self, credentials: WifiCredentials) -> Result<(), WifiError> {
let station_config = StationConfig::default().with_ssid(credentials.ssid).with_password(credentials.pass); let station_config = StationConfig::default()
self.controller.set_config(&Config::Station(station_config))?; .with_ssid(credentials.ssid)
.with_password(credentials.pass);
self.controller
.set_config(&Config::Station(station_config))?;
Ok(()) Ok(())
} }
#[cfg(feature = "wokwi")] #[cfg(feature = "wokwi")]
pub async fn setup( pub async fn setup(
wifi: esp_hal::peripherals::WIFI<'static>, wifi: esp_hal::peripherals::WIFI<'static>,
@@ -159,16 +160,28 @@ impl Wifi {
} }
} }
#[embassy_executor::task] #[embassy_executor::task]
pub async fn wait_for_wifi_credentials(_outputs: &'static Mutex<Outputs>, peripherals: &'static Peripherals) { pub async fn wait_for_wifi_credentials(
_outputs: &'static Mutex<Outputs>,
peripherals: &'static Peripherals,
) {
loop { loop {
log::info!("Waiting for new WiFi credentials"); log::info!("Waiting for new WiFi credentials");
let credentials = WIFI_CREDENTIALS.wait().await; let credentials = WIFI_CREDENTIALS.wait().await;
log::info!("Received new WiFi credentials:\nssid: {}, pass: {}", credentials.ssid, credentials.pass); log::info!(
if let Err(err) = peripherals.store.lock().await.wifi_store.save_credentials(&credentials).await { "Received new WiFi credentials:\nssid: {}, pass: {}",
credentials.ssid,
credentials.pass
);
if let Err(err) = peripherals
.store
.lock()
.await
.wifi_store
.save_credentials(&credentials)
.await
{
log::error!("Error storing credentials: {err}"); log::error!("Error storing credentials: {err}");
continue; continue;
} }
@@ -188,5 +201,3 @@ pub async fn wait_for_wifi_credentials(_outputs: &'static Mutex<Outputs>, periph
} }
} }
} }