diff --git a/firmware/build.rs b/firmware/build.rs index fc1dc21..fce9fd6 100644 --- a/firmware/build.rs +++ b/firmware/build.rs @@ -7,6 +7,7 @@ macro_rules! set_env { } fn main() { + println!("cargo:rerun-if-changed=.env"); dotenvy::dotenv().ok(); set_env!("SSID"); diff --git a/firmware/src/communication.rs b/firmware/src/communication.rs index ec6fc09..8bfab9f 100644 --- a/firmware/src/communication.rs +++ b/firmware/src/communication.rs @@ -8,7 +8,7 @@ use packets::Packet; use crate::clock::CLOCK; use crate::tcp::PacketSocket; -use crate::{AppReceiver, AppSender, StateEvent}; +use crate::{AppReceiver, AppSender, Component, ComponentState, ComponentStateEvent, StateEvent}; pub type RegisterEvent = (); @@ -16,18 +16,29 @@ pub type RegisterEvent = (); pub async fn listen_register_events( stack: Stack<'static>, receiver: AppReceiver, + component_state_sender: AppSender, event_sender: AppSender, ) { loop { receiver.receive().await; info!("Register event received"); + component_state_sender + .send((Component::Registration, ComponentState::Initializing)) + .await; loop { let succesfull = register_at_server(stack, event_sender).await; if succesfull { + component_state_sender + .send((Component::Registration, ComponentState::Ok)) + .await; break; } + component_state_sender + .send((Component::Registration, ComponentState::Error)) + .await; + Timer::after(Duration::from_millis(10_000)).await; info!("Retrying registration..."); } diff --git a/firmware/src/main.rs b/firmware/src/main.rs index e59c391..6bdc070 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -9,11 +9,11 @@ use embassy_futures::select::{Either, select}; use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::{Channel, Receiver, Sender}; -use esp_hal::gpio::AnyPin; +use esp_hal::gpio::{AnyPin, Output, OutputConfig}; use esp_hal::mcpwm::operator::PwmPinConfig; use esp_hal::mcpwm::timer::PwmWorkingMode; use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; -use esp_hal::peripherals::{MCPWM0, MCPWM1}; +use esp_hal::peripherals::{GPIO2, MCPWM0, MCPWM1}; use esp_hal::time::Rate; use esp_hal::timer::timg::TimerGroup; use esp_hal::{clock::CpuClock, peripherals::Peripherals}; @@ -73,10 +73,16 @@ async fn main(spawner: Spawner) { static REGISTER_CHANNEL: StaticCell> = StaticCell::new(); let register_event_channel = REGISTER_CHANNEL.init(Channel::new()); + static COMPONENT_STATE_CHANNEL: StaticCell> = StaticCell::new(); + let component_state_channel = COMPONENT_STATE_CHANNEL.init(Channel::new()); + + spawner + .spawn(handle_components(component_state_channel.receiver(), peripherals.GPIO2).unwrap()); + let stack = wifi::init_wifi( peripherals.WIFI, &spawner, - peripherals.GPIO2, + component_state_channel.sender(), register_event_channel.sender(), ) .await; @@ -97,6 +103,7 @@ async fn main(spawner: Spawner) { listen_register_events( stack, register_event_channel.receiver(), + component_state_channel.sender(), event_channel.sender(), ) .unwrap(), @@ -189,10 +196,58 @@ pub async fn handle_sun( update_color(brightness).await; } Either::Second(_) => { - if !enabled { + update_color(brightness).await; + } + } + } +} + +pub enum Component { + WifiConnection = 0, + Registration = 1, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ComponentState { + Ok, + Initializing, + Error, +} + +type ComponentStateEvent = (Component, ComponentState); + +#[embassy_executor::task] +pub async fn handle_components( + event_receiver: AppReceiver, + led_pin: GPIO2<'static>, +) { + let mut pin = Output::new(led_pin, esp_hal::gpio::Level::Low, OutputConfig::default()); + + let mut is_blinking = false; + let mut states = [ComponentState::Ok; 2]; + + loop { + let result = select(event_receiver.receive(), maybe_timer(is_blinking, 1)).await; + + match result { + Either::First((component, state)) => { + is_blinking = false; + states[component as usize] = state; + + if states.iter().any(|s| *s == ComponentState::Error) { + is_blinking = true; continue; } - update_color(brightness).await; + + if states.iter().any(|s| *s == ComponentState::Initializing) { + pin.set_high(); + continue; + } + + pin.set_low(); + } + Either::Second(_) => { + pin.toggle(); } } } diff --git a/firmware/src/wifi.rs b/firmware/src/wifi.rs index befddf4..d4ebbac 100644 --- a/firmware/src/wifi.rs +++ b/firmware/src/wifi.rs @@ -1,21 +1,19 @@ use embassy_executor::Spawner; use embassy_net::{DhcpConfig, Runner, Stack, StackResources}; use embassy_time::{Duration, Timer}; -use esp_hal::{ - gpio::{Output, OutputConfig}, - peripherals::GPIO2, - rng::Rng, -}; +use esp_hal::rng::Rng; use esp_radio::wifi::{Config, ControllerConfig, Interface, WifiController, sta::StationConfig}; use log::info; use static_cell::StaticCell; -use crate::{AppSender, communication::RegisterEvent}; +use crate::{ + AppSender, Component, ComponentState, ComponentStateEvent, communication::RegisterEvent, +}; pub async fn init_wifi( wifi: esp_hal::peripherals::WIFI<'static>, spawner: &Spawner, - led_pin: GPIO2<'static>, + component_state_sender: AppSender, register_event_sender: AppSender, ) -> Stack<'static> { let station_config = Config::Station( @@ -46,7 +44,14 @@ pub async fn init_wifi( seed, ); - spawner.spawn(connection(wifi_controller, led_pin, register_event_sender).unwrap()); + spawner.spawn( + connection( + wifi_controller, + component_state_sender, + register_event_sender, + ) + .unwrap(), + ); spawner.spawn(net_task(runner).unwrap()); stack @@ -55,29 +60,36 @@ pub async fn init_wifi( #[embassy_executor::task] async fn connection( mut controller: WifiController<'static>, - led_pin: GPIO2<'static>, + component_state_sender: AppSender, register_event_sender: AppSender, ) { + component_state_sender + .send((Component::WifiConnection, ComponentState::Initializing)) + .await; info!("start connection task"); - let mut pin = Output::new(led_pin, esp_hal::gpio::Level::Low, OutputConfig::default()); - loop { match controller.connect_async().await { Ok(info) => { info!("Wifi connected to {:?}", info); - pin.set_high(); + component_state_sender + .send((Component::WifiConnection, ComponentState::Ok)) + .await; register_event_sender.send(()).await; // wait until we're no longer connected let info = controller.wait_for_disconnect_async().await.ok(); info!("Disconnected: {:?}", info); - pin.set_low(); + component_state_sender + .send((Component::WifiConnection, ComponentState::Error)) + .await; } Err(e) => { info!("Failed to connect to wifi: {e:?}"); - pin.set_low(); + component_state_sender + .send((Component::WifiConnection, ComponentState::Error)) + .await; } }