feat(config): use embassy-sync RpcService for the config service

This commit is contained in:
2026-08-27 23:15:42 -05:00
parent 15fad17fab
commit 51a450dad4
3 changed files with 141 additions and 39 deletions
Generated
+52
View File
@@ -26,6 +26,15 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c583acf993cf4245c4acb0a2cc2ab1f9cc097de73411bb6d3647ff6af2b1013d" checksum = "c583acf993cf4245c4acb0a2cc2ab1f9cc097de73411bb6d3647ff6af2b1013d"
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.1" version = "1.5.1"
@@ -203,6 +212,7 @@ dependencies = [
"esp-radio", "esp-radio",
"esp-rtos", "esp-rtos",
"esp-storage", "esp-storage",
"heapless 0.9.3",
"int-enum", "int-enum",
"picoserve", "picoserve",
"portable-atomic", "portable-atomic",
@@ -213,6 +223,7 @@ dependencies = [
"sntpc-net-embassy", "sntpc-net-embassy",
"sntpc-time-embassy", "sntpc-time-embassy",
"static_cell", "static_cell",
"thiserror",
] ]
[[package]] [[package]]
@@ -1362,6 +1373,20 @@ version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32 0.2.1",
"rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]] [[package]]
name = "heapless" name = "heapless"
version = "0.8.0" version = "0.8.0"
@@ -1382,6 +1407,7 @@ checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4"
dependencies = [ dependencies = [
"defmt 1.1.1", "defmt 1.1.1",
"hash32 0.3.1", "hash32 0.3.1",
"serde_core",
"stable_deref_trait", "stable_deref_trait",
] ]
@@ -1735,6 +1761,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
dependencies = [ dependencies = [
"cobs", "cobs",
"defmt 1.1.1",
"heapless 0.7.17",
"serde", "serde",
] ]
@@ -1884,6 +1912,15 @@ dependencies = [
"rustversion", "rustversion",
] ]
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.23" version = "1.0.23"
@@ -1908,6 +1945,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]] [[package]]
name = "sequential-storage" name = "sequential-storage"
version = "8.0.1" version = "8.0.1"
@@ -2051,6 +2094,15 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0f368519fc6c85fc1afdb769fb5a51123f6158013e143656e25a3485a0d401c" checksum = "a0f368519fc6c85fc1afdb769fb5a51123f6158013e143656e25a3485a0d401c"
[[package]]
name = "spin"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
dependencies = [
"lock_api",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.2.1" version = "1.2.1"
+3 -1
View File
@@ -63,9 +63,11 @@ picoserve = { version = "0.19", features = ["defmt", "embassy", "json"] }
sequential-storage = "8.0" sequential-storage = "8.0"
esp-storage = { version = "0.9", features = ["defmt", "esp32c6"] } esp-storage = { version = "0.9", features = ["defmt", "esp32c6"] }
postcard = { version = "1.1", default-features = false } postcard = { version = "1.1", default-features = false, features = ["defmt", "heapless"] }
serde = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", default-features = false, features = ["derive"] }
int-enum = "1.2.0" int-enum = "1.2.0"
heapless = { version = "0.9.3", features = ["defmt", "serde"] }
thiserror = { version = "2.0.20", default-features = false }
# For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html # For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html
+86 -38
View File
@@ -1,26 +1,64 @@
use embassy_embedded_hal::adapter::BlockingAsync; use embassy_embedded_hal::adapter::BlockingAsync;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, rpc_service::RpcService};
use embedded_rpc::RpcService;
use esp_hal::peripherals::FLASH; use esp_hal::peripherals::FLASH;
use esp_radio::wifi::sta::StationConfig;
use esp_storage::FlashStorage; use esp_storage::FlashStorage;
use heapless::String;
use int_enum::IntEnum; use int_enum::IntEnum;
use postcard::to_slice;
use sequential_storage::{ use sequential_storage::{
cache::{Cache, Uncached}, cache::{Cache, Uncached},
map::{Key, MapConfig, MapStorage, SerializationError}, map::{Key, MapConfig, MapStorage},
}; };
use serde::{Deserialize, Serialize};
use thiserror::Error;
pub enum ConfigCommand { pub static CONFIG_SERVICE: RpcService<CriticalSectionRawMutex, ConfigService, 64> =
SetStationCreds(),
}
impl ConfigCommand {
pub async fn set_station_creds() {}
}
pub static CONFIG_SERVICE: RpcService<CriticalSectionRawMutex, ConfigCommand, ()> =
RpcService::new(); 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>) { pub async fn start_config(spawner: Spawner, flash: FLASH<'static>) {
let storage = MapStorage::<ConfigKey, _, _>::new( let storage = MapStorage::<ConfigKey, _, _>::new(
BlockingAsync::new(FlashStorage::new(flash)), BlockingAsync::new(FlashStorage::new(flash)),
@@ -28,29 +66,17 @@ pub async fn start_config(spawner: Spawner, flash: FLASH<'static>) {
Cache::new_uncached(), 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] #[embassy_executor::task]
async fn config_handler(mut storage: MapStorage<ConfigKey, BlockingAsync<FlashStorage<'static>>, Cache<Uncached, Uncached, Uncached, ConfigKey>>) { async fn handler(mut service: ConfigService) -> ! {
let mut data_buffer = [0u8; 256]; CONFIG_SERVICE.run(&mut service).await
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(());
// }
}
}
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntEnum)] #[derive(Debug, Clone, Copy, PartialEq, Eq, IntEnum)]
@@ -60,18 +86,40 @@ enum ConfigKey {
} }
impl Key for ConfigKey { impl Key for ConfigKey {
fn get_len(_: &[u8]) -> Result<usize, SerializationError> { fn get_len(_: &[u8]) -> Result<usize, sequential_storage::map::SerializationError> {
Ok(1) Ok(1)
} }
fn serialize_into(&self, buffer: &mut [u8]) -> Result<usize, SerializationError> { fn serialize_into(
let val = buffer.get_mut(0).ok_or(SerializationError::BufferTooSmall)?; &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(); *val = self.clone().into();
Ok(1) Ok(1)
} }
fn deserialize_from(buffer: &[u8]) -> Result<(Self, usize), SerializationError> { fn deserialize_from(
let val = *buffer.get(0).ok_or(SerializationError::BufferTooSmall)?; buffer: &[u8],
Ok((val.try_into().map_err(|_| {SerializationError::InvalidData})?, 1)) ) -> 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>),
}