From aed1e4166503690f1a3f3be223602812c48af51c Mon Sep 17 00:00:00 2001 From: Reed Krantz Date: Mon, 17 Aug 2026 17:25:09 -0500 Subject: [PATCH] feat: use the embedded-rpc library for the wifi service --- Cargo.lock | 10 ++++ Cargo.toml | 1 + src/wifi.rs | 134 ++++++++++++++++++++++++++++------------------------ 3 files changed, 83 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2961a0c..47b0df3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,6 +191,7 @@ dependencies = [ "embassy-net", "embassy-sync 0.8.0", "embassy-time", + "embedded-rpc", "esp-alloc", "esp-backtrace", "esp-bootloader-esp-idf", @@ -688,6 +689,15 @@ dependencies = [ "embedded-nal", ] +[[package]] +name = "embedded-rpc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "691855ab7f974e2aaa87433e0f6e5967a959f312c486f6f929ff1cda14c7f80d" +dependencies = [ + "embassy-sync 0.8.0", +] + [[package]] name = "embedded-storage" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 11044bd..716fd9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,6 +58,7 @@ portable-atomic = "1.15.0" picoserve = { version = "0.19", features = ["defmt", "embassy", "json"] } embassy-sync = { version = "0.8.0", features = ["defmt"] } embassy-futures = { version = "0.1.2", features = ["defmt"] } +embedded-rpc = "0.2.0" # For fine tuning these settings, please refer to https://doc.rust-lang.org/cargo/reference/profiles.html diff --git a/src/wifi.rs b/src/wifi.rs index 1d45add..b99d3b4 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -1,11 +1,10 @@ use defmt::{error, info}; use embassy_executor::Spawner; -use embassy_futures::select::Either::First; -use embassy_futures::select::select; +use embassy_futures::select::{Either, select}; use embassy_net::{Runner, Stack}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::{channel::Channel}; use embassy_time::{Duration, Timer}; +use embedded_rpc::{RequestDroppedError, RpcService}; use esp_hal::peripherals::WIFI; use esp_radio::wifi::sta::StationConfig; use esp_radio::wifi::{ControllerConfig, Interface, WifiController}; @@ -16,14 +15,16 @@ pub enum WifiCommand { } impl WifiCommand { - pub async fn set_station_config(config: esp_radio::wifi::Config) { - WIFI_CH - .send(WifiCommand::SetStationConfig(config)) - .await; + pub async fn set_station_config( + config: esp_radio::wifi::Config, + ) -> Result<(), RequestDroppedError> { + WIFI_SERVICE + .request(WifiCommand::SetStationConfig(config)) + .await } } -pub static WIFI_CH: Channel = Channel::new(); +pub static WIFI_SERVICE: RpcService = RpcService::new(); pub fn start_wifi(spawner: Spawner, wifi: WIFI<'static>) -> Stack<'static> { let wifi_config = esp_radio::wifi::Config::Station(StationConfig::default()); @@ -52,78 +53,87 @@ pub fn start_wifi(spawner: Spawner, wifi: WIFI<'static>) -> Stack<'static> { ); spawner.spawn(net_task(net_runner).unwrap()); - spawner.spawn(handler(wifi_controller, net_stack).unwrap()); + spawner.spawn(wifi_handler(wifi_controller).unwrap()); + spawner.spawn(ip_logger(net_stack).unwrap()); + spawner.spawn(handler(net_stack).unwrap()); net_stack } #[embassy_executor::task] -async fn handler(mut controller: WifiController<'static>, net_stack: Stack<'static>) { - let receiver = WIFI_CH.receiver(); +async fn handler(net_stack: Stack<'static>) { loop { - match select(receiver.receive(), connection(&mut controller, net_stack)).await { - First(WifiCommand::SetStationConfig(config)) => { - if controller.set_config(&config).is_err() { - error!("Set WiFi config failed: {:?}", config); - }; + let (req, served) = WIFI_SERVICE.serve().await; + + match req { + WifiCommand::SetStationConfig(config) => { + if WIFI_HANDLER_RPC.request(config).await.is_err() { + continue; + } } - First(WifiCommand::SetDhcpConfig(dhcp_config)) => { + WifiCommand::SetDhcpConfig(dhcp_config) => { net_stack.set_config_v4(embassy_net::ConfigV4::Dhcp(dhcp_config)); } - embassy_futures::select::Either::Second(_) => { - unreachable!("connection function should be infinite loop") + } + + served.respond(()); + } +} + +static WIFI_HANDLER_RPC: RpcService = + RpcService::new(); + +#[embassy_executor::task] +async fn wifi_handler(mut controller: WifiController<'static>) { + let connection = async |controller: &mut WifiController<'static>| { + info!("Connecting to WiFi..."); + + match controller.connect_async().await { + Ok(info) => { + info!("Wifi connected to {:?}", info); + + // wait until we're no longer connected + let info = controller.wait_for_disconnect_async().await.ok(); + info!("Disconnected: {:?}", info); + } + Err(e) => { + error!("Failed to connect to wifi: {:?}", e); + } + } + }; + + loop { + if let Either::First((req, served)) = + select(WIFI_HANDLER_RPC.serve(), connection(&mut controller)).await + { + if controller.set_config(&req).is_ok() { + served.respond(()); } } } } -async fn connection(controller: &mut WifiController<'static>, net_stack: Stack<'static>) { - info!("start connection task"); +#[embassy_executor::task] +async fn ip_logger(net_stack: Stack<'static>) { + loop { + info!("Getting IP address..."); + net_stack.wait_config_up().await; - select( - async { - loop { - info!("Connecting to WiFi..."); + match net_stack.config_v4() { + Some(info) => { + info!("Got IP: {:?}", info); - match controller.connect_async().await { - Ok(info) => { - info!("Wifi connected to {:?}", info); - - // wait until we're no longer connected - let info = controller.wait_for_disconnect_async().await.ok(); - info!("Disconnected: {:?}", info); - } - Err(e) => { - error!("Failed to connect to wifi: {:?}", e); - } - } - - Timer::after(Duration::from_millis(5000)).await + // wait until we're no longer connected + net_stack.wait_config_down().await; + info!("Address no longer configured"); } - }, - async { - loop { - info!("Getting IP address..."); - net_stack.wait_config_up().await; - - match net_stack.config_v4() { - Some(info) => { - info!("Got IP: {:?}", info); - - // wait until we're no longer connected - net_stack.wait_config_down().await; - info!("Address no longer configured"); - } - None => { - error!("Failed to configure an address"); - } - } - - Timer::after(Duration::from_millis(5000)).await + None => { + error!("Failed to configure an address"); } - }, - ) - .await; + } + + Timer::after(Duration::from_millis(5000)).await + } } #[embassy_executor::task]