Files
cover-theif/src/config.rs
T

126 lines
3.5 KiB
Rust

use embassy_embedded_hal::adapter::BlockingAsync;
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, rpc_service::RpcService};
use esp_hal::peripherals::FLASH;
use esp_radio::wifi::sta::StationConfig;
use esp_storage::FlashStorage;
use heapless::String;
use int_enum::IntEnum;
use postcard::to_slice;
use sequential_storage::{
cache::{Cache, Uncached},
map::{Key, MapConfig, MapStorage},
};
use serde::{Deserialize, Serialize};
use thiserror::Error;
pub static CONFIG_SERVICE: RpcService<CriticalSectionRawMutex, ConfigService, 64> =
RpcService::new();
pub struct ConfigService {
storage: MapStorage<
ConfigKey,
BlockingAsync<FlashStorage<'static>>,
Cache<Uncached, Uncached, Uncached, ConfigKey>,
>,
data_buffer: [u8; 256],
}
impl ConfigService {
pub async fn set_wifi_creds(&mut self, value: WifiCredentials) -> Result<(), ConfigError> {
let mut buf = [0u8; 256];
to_slice(&value, &mut buf)?;
self.storage
.store_item(&mut self.data_buffer, &ConfigKey::Wifi, &buf)
.await
.map_err(|e| ConfigError::FlashError(e))?;
// TODO: send the change to the wifi service
// WIFI_SERVICE
// .call(|s| s.set_station_config(esp_radio::wifi::Config::Station(value.into())))
// .await;
Ok(())
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct WifiCredentials {
pub ssid: String<32>,
pub password: String<32>,
}
impl From<WifiCredentials> for StationConfig {
fn from(value: WifiCredentials) -> Self {
Self::default()
.with_ssid(value.ssid.as_str())
.with_password(value.password.as_str().into())
}
}
pub async fn start_config(spawner: Spawner, flash: FLASH<'static>) {
let storage = MapStorage::<ConfigKey, _, _>::new(
BlockingAsync::new(FlashStorage::new(flash)),
const { MapConfig::new(0x3F_0000..0x40_0000) },
Cache::new_uncached(),
);
let service = ConfigService {
storage: storage,
data_buffer: [0u8; 256],
};
spawner.spawn(handler(service).unwrap());
}
#[embassy_executor::task]
async fn handler(mut service: ConfigService) -> ! {
CONFIG_SERVICE.run(&mut service).await
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntEnum)]
#[repr(u8)]
enum ConfigKey {
Wifi,
}
impl Key for ConfigKey {
fn get_len(_: &[u8]) -> Result<usize, sequential_storage::map::SerializationError> {
Ok(1)
}
fn serialize_into(
&self,
buffer: &mut [u8],
) -> Result<usize, sequential_storage::map::SerializationError> {
let val = buffer
.get_mut(0)
.ok_or(sequential_storage::map::SerializationError::BufferTooSmall)?;
*val = self.clone().into();
Ok(1)
}
fn deserialize_from(
buffer: &[u8],
) -> Result<(Self, usize), sequential_storage::map::SerializationError> {
let val = *buffer
.get(0)
.ok_or(sequential_storage::map::SerializationError::BufferTooSmall)?;
Ok((
val.try_into()
.map_err(|_| sequential_storage::map::SerializationError::InvalidData)?,
1,
))
}
}
#[derive(Error, Debug)]
pub enum ConfigError {
#[error("Error serializing data: {0}")]
SerializationError(#[from] postcard::Error),
#[error("Error storing data on the flash: {0:?}")]
FlashError(sequential_storage::Error<esp_storage::FlashStorageError>),
}