feat(config): use embassy-sync RpcService for the config service
This commit is contained in:
+86
-38
@@ -1,26 +1,64 @@
|
||||
use embassy_embedded_hal::adapter::BlockingAsync;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embedded_rpc::RpcService;
|
||||
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, SerializationError},
|
||||
map::{Key, MapConfig, MapStorage},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
pub enum ConfigCommand {
|
||||
SetStationCreds(),
|
||||
}
|
||||
|
||||
impl ConfigCommand {
|
||||
pub async fn set_station_creds() {}
|
||||
}
|
||||
|
||||
pub static CONFIG_SERVICE: RpcService<CriticalSectionRawMutex, ConfigCommand, ()> =
|
||||
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)),
|
||||
@@ -28,29 +66,17 @@ pub async fn start_config(spawner: Spawner, flash: FLASH<'static>) {
|
||||
Cache::new_uncached(),
|
||||
);
|
||||
|
||||
spawner.spawn(config_handler(storage).unwrap());
|
||||
let service = ConfigService {
|
||||
storage: storage,
|
||||
data_buffer: [0u8; 256],
|
||||
};
|
||||
|
||||
spawner.spawn(handler(service).unwrap());
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn config_handler(mut storage: MapStorage<ConfigKey, BlockingAsync<FlashStorage<'static>>, Cache<Uncached, Uncached, Uncached, ConfigKey>>) {
|
||||
let mut data_buffer = [0u8; 256];
|
||||
|
||||
loop {
|
||||
let (req, served) = CONFIG_SERVICE.serve().await;
|
||||
|
||||
match req {
|
||||
ConfigCommand::SetStationCreds() => {
|
||||
todo!()
|
||||
// if storage
|
||||
// .store_item(&mut data_buffer, &ConfigKey::Wifi, )
|
||||
// .await
|
||||
// .is_ok()
|
||||
// {
|
||||
// served.respond(());
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn handler(mut service: ConfigService) -> ! {
|
||||
CONFIG_SERVICE.run(&mut service).await
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntEnum)]
|
||||
@@ -60,18 +86,40 @@ enum ConfigKey {
|
||||
}
|
||||
|
||||
impl Key for ConfigKey {
|
||||
fn get_len(_: &[u8]) -> Result<usize, SerializationError> {
|
||||
fn get_len(_: &[u8]) -> Result<usize, sequential_storage::map::SerializationError> {
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
fn serialize_into(&self, buffer: &mut [u8]) -> Result<usize, SerializationError> {
|
||||
let val = buffer.get_mut(0).ok_or(SerializationError::BufferTooSmall)?;
|
||||
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), SerializationError> {
|
||||
let val = *buffer.get(0).ok_or(SerializationError::BufferTooSmall)?;
|
||||
Ok((val.try_into().map_err(|_| {SerializationError::InvalidData})?, 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>),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user