use alloc::string::String; use crate::network::wifi::WifiCredentials; use crate::Mutex; use crate::peripherals::storage::Nvs; use alloc::sync::Arc; use core::error::Error; use core::fmt::Display; use esp_nvs::Key; const NVS_NAMESPACE_WIFI: Key = Key::from_str("WIFI"); const NVS_WIFI_SSID_KEY: Key = Key::from_str("WIFI_SSID"); const NVS_WIFI_PASS_KEY: Key = Key::from_str("WIFI_PASS"); const NVS_WIFI_INITIALIZED_KEY: Key = Key::from_str("INITIALIZED"); #[derive(Debug)] pub enum WifiStoreError { Store(esp_nvs::error::Error), } impl Error for WifiStoreError {} impl Display for WifiStoreError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { WifiStoreError::Store(e) => e.fmt(f), } } } impl From for WifiStoreError { fn from(error: esp_nvs::error::Error) -> WifiStoreError { WifiStoreError::Store(error) } } pub struct WifiStore { nvs: Arc>, } impl WifiStore { pub async fn new(nvs: Arc>) -> Result { if !Self::is_initialized(&nvs).await? { log::info!("WifiStore has not been initialized"); Self::initialize(&nvs).await?; } log::info!("WifiStore has been initialized"); Ok(Self { nvs }) } async fn is_initialized(nvs: &Mutex) -> Result { log::info!("check initialization"); let mut nvs_lock = nvs.lock().await; match nvs_lock.get::(&NVS_NAMESPACE_WIFI, &NVS_WIFI_INITIALIZED_KEY) { Ok(initialized) => { log::debug!("initialization_check: initialized {initialized:?}"); return Ok(true); } Err(esp_nvs::error::Error::NamespaceNotFound) => { log::debug!("initialization_check: error: namespace not found"); return Ok(false); } Err(esp_nvs::error::Error::KeyNotFound) => { log::debug!("initialization_check: error: key not found"); return Ok(false); } Err(error) => return Err(error.into()), }; } async fn initialize(nvs: &Mutex) -> Result<(), WifiStoreError> { log::info!("initializing wifi store"); let mut nvs_lock = nvs.lock().await; log::debug!("initialization: write dummy ssid"); nvs_lock.set::<&str>( &NVS_NAMESPACE_WIFI, &NVS_WIFI_SSID_KEY, "" )?; log::debug!("initialization: write dummy pass"); nvs_lock.set::<&str>( &NVS_NAMESPACE_WIFI, &NVS_WIFI_PASS_KEY, "" )?; // set initialized log::debug!("initialization: write initialized"); nvs_lock.set::( &NVS_NAMESPACE_WIFI, &NVS_WIFI_INITIALIZED_KEY, true, )?; Ok(()) } pub async fn load_credentials(&self) -> Result { log::debug!("loading wifi credentials"); log::debug!("loading ssid"); let mut nvs_lock = self.nvs.lock().await; let ssid = nvs_lock.get::(&NVS_NAMESPACE_WIFI, &NVS_WIFI_SSID_KEY)?; log::debug!("ssid: {ssid}"); log::debug!("loading pass"); let pass = nvs_lock.get::(&NVS_NAMESPACE_WIFI, &NVS_WIFI_PASS_KEY)?; log::debug!("pass: {pass}"); Ok(WifiCredentials{ssid, pass}) } pub async fn save_credentials(&self, credentials: &WifiCredentials) -> Result<(), WifiStoreError> { log::debug!("writing wifi credentials"); log::debug!("writing ssid...\nssid: {}", credentials.ssid); self.nvs.lock().await.set::<&str>( &NVS_NAMESPACE_WIFI, &NVS_WIFI_SSID_KEY, &credentials.ssid, )?; log::debug!("writing pass...\npass: {}", credentials.pass); self.nvs.lock().await.set::<&str>( &NVS_NAMESPACE_WIFI, &NVS_WIFI_PASS_KEY, &credentials.pass, )?; Ok(()) } }