events: rewrite the eventing system to reduce mutex usage to just the measurement bus
This commit is contained in:
@@ -12,7 +12,6 @@ pub mod demo;
|
||||
pub mod oled_render;
|
||||
|
||||
// Prediction engines
|
||||
pub mod predict;
|
||||
pub mod motion;
|
||||
|
||||
// Graphics stack
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use embassy_sync::{channel::{DynamicReceiver, DynamicSender}, pubsub::DynPublisher};
|
||||
use embassy_sync::{channel::DynamicReceiver, pubsub::DynPublisher};
|
||||
use log::*;
|
||||
|
||||
use crate::{ego::engine::BikeStates, events::{Measurement, Notification, Prediction, SensorSource, SensorState}};
|
||||
use crate::{ego::engine::BikeStates, events::{Measurement, Prediction}};
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn motion_task(src: DynamicReceiver<'static, Measurement>, prediction_sink: DynamicSender<'static, Prediction>) {
|
||||
pub async fn motion_task(src: DynamicReceiver<'static, Measurement>, prediction_sink: DynPublisher<'static, Prediction>) {
|
||||
let mut states = BikeStates::default();
|
||||
|
||||
loop {
|
||||
@@ -26,7 +26,7 @@ pub async fn motion_task(src: DynamicReceiver<'static, Measurement>, prediction_
|
||||
// FIXME: This needs harmonized with the automatic data timeout from above, somehow?
|
||||
Measurement::SensorHardwareStatus(source, state) => {
|
||||
warn!("Sensor {source:?} reports {state:?}!");
|
||||
prediction_sink.send(Prediction::SensorStatus(source, state)).await;
|
||||
prediction_sink.publish(Prediction::SensorStatus(source, state)).await;
|
||||
},
|
||||
Measurement::SimulationProgress(source, duration, _pct) => debug!("{source:?} simulation time: {}", duration.as_secs()),
|
||||
Measurement::Annotation => ()
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use alloc::sync::Arc;
|
||||
use display_interface::DisplayError;
|
||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, pubsub::DynSubscriber};
|
||||
use embassy_time::{Duration, Instant, Timer};
|
||||
use embedded_graphics::{pixelcolor::BinaryColor, prelude::DrawTarget};
|
||||
use figments::{mappings::embedded_graphics::Matrix2DSpace, prelude::{Coordinates, Rectangle}, render::{RenderSource, Shader}, surface::{BufferedSurfacePool, NullSurface, NullBufferPool, Surface, SurfaceBuilder, Surfaces}};
|
||||
use figments_render::output::{Brightness, OutputAsync};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embedded_graphics::pixelcolor::BinaryColor;
|
||||
use figments::{mappings::embedded_graphics::Matrix2DSpace, prelude::{Coordinates, Rectangle}, render::Shader, surface::{BufferedSurfacePool, NullBufferPool, Surface, SurfaceBuilder, Surfaces}};
|
||||
use figments_render::output::Brightness;
|
||||
use log::*;
|
||||
|
||||
use crate::{animation::Animation, backoff::Backoff, events::{Notification, Prediction, SensorSource, SensorState, Telemetry}, graphics::{display::DisplayControls, oled_ui::{OledUniforms, Screen}}};
|
||||
use crate::{animation::Animation, events::{Personality, Prediction}, graphics::{display::DisplayControls, oled_ui::{OledUniforms, Screen}}};
|
||||
|
||||
#[cfg(feature="oled")]
|
||||
pub type OledUiSurfacePool = BufferedSurfacePool<OledUniforms, Matrix2DSpace, BinaryColor>;
|
||||
@@ -22,7 +21,7 @@ pub type LockedUniforms = Arc<Mutex<CriticalSectionRawMutex, OledUniforms>>;
|
||||
pub struct OledUI<S: Surface + core::fmt::Debug> {
|
||||
overlay: S,
|
||||
controls: DisplayControls,
|
||||
uniforms: Arc<Mutex<CriticalSectionRawMutex, OledUniforms>>
|
||||
uniforms: LockedUniforms
|
||||
}
|
||||
|
||||
struct OverlayShader {}
|
||||
@@ -57,35 +56,32 @@ impl<S: core::fmt::Debug + Surface<CoordinateSpace = Matrix2DSpace, Pixel = Bina
|
||||
FADE_OUT.apply(&mut self.overlay).await;
|
||||
}
|
||||
|
||||
pub async fn on_event(&mut self, event: Telemetry) {
|
||||
pub async fn on_event(&mut self, event: Prediction) {
|
||||
match event {
|
||||
// Waking and sleeping
|
||||
Telemetry::Notification(Notification::Sleep) => {
|
||||
warn!("Putting OLED display to sleep");
|
||||
self.screen_transition(Screen::Sleeping).await;
|
||||
Timer::after_secs(1).await;
|
||||
self.screen_transition(Screen::Blank).await;
|
||||
self.controls.set_on(false);
|
||||
//ui_state.sleep = true
|
||||
Prediction::SetPersonality(personality) => {
|
||||
match personality {
|
||||
Personality::Waking => {
|
||||
warn!("Waking up OLED display");
|
||||
self.controls.set_on(true);
|
||||
self.screen_transition(Screen::Waking).await;
|
||||
Timer::after_secs(1).await;
|
||||
self.screen_transition(Screen::Home).await;
|
||||
},
|
||||
Personality::Sleeping => {
|
||||
warn!("Putting OLED display to sleep");
|
||||
self.screen_transition(Screen::Sleeping).await;
|
||||
Timer::after_secs(1).await;
|
||||
self.screen_transition(Screen::Blank).await;
|
||||
self.controls.set_on(false);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
self.with_uniforms(|state| { state.ui.personality = personality }).await;
|
||||
},
|
||||
Telemetry::Notification(Notification::WakeUp) => {
|
||||
warn!("Waking up OLED display");
|
||||
self.controls.set_on(true);
|
||||
self.screen_transition(Screen::Waking).await;
|
||||
Timer::after_secs(1).await;
|
||||
self.screen_transition(Screen::Home).await;
|
||||
//ui_state.sleep = false
|
||||
},
|
||||
|
||||
// State updates
|
||||
Telemetry::Prediction(Prediction::Velocity(v)) => self.with_uniforms(|state| {state.ui.velocity = v;}).await,
|
||||
Telemetry::Prediction(Prediction::Location(loc)) => self.with_uniforms(|state| {state.ui.location = loc}).await,
|
||||
Telemetry::Prediction(Prediction::Motion(motion)) => self.with_uniforms(|state| {state.ui.motion = motion}).await,
|
||||
Telemetry::Notification(Notification::SceneChange(scene)) => self.with_uniforms(|state| {state.ui.scene = scene}).await,
|
||||
Telemetry::Notification(Notification::SetBrakelight(b)) => self.with_uniforms(|state| {state.ui.brakelight = b}).await,
|
||||
Telemetry::Notification(Notification::SetHeadlight(b)) => self.with_uniforms(|state| {state.ui.headlight = b}).await,
|
||||
Telemetry::Notification(Notification::SensorStatus(src, sensor_state)) => self.with_uniforms(|state| {state.ui.sensor_states[src] = sensor_state}).await,
|
||||
_ => ()
|
||||
Prediction::Velocity(v) => self.with_uniforms(|state| {state.ui.velocity = v;}).await,
|
||||
Prediction::Location(loc) => self.with_uniforms(|state| {state.ui.location = loc}).await,
|
||||
Prediction::Motion{ prev: _, next: motion } => self.with_uniforms(|state| {state.ui.motion = motion}).await,
|
||||
Prediction::SensorStatus(src, sensor_state, ) => self.with_uniforms(|state| {state.ui.sensor_states[src] = sensor_state}).await,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +93,7 @@ impl<S: core::fmt::Debug + Surface<CoordinateSpace = Matrix2DSpace, Pixel = Bina
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn oled_ui(mut events: DynSubscriber<'static, Telemetry>, mut ui: OledUI<OledSurface>) {
|
||||
pub async fn oled_ui(mut events: DynSubscriber<'static, Prediction>, mut ui: OledUI<OledSurface>) {
|
||||
|
||||
ui.screen_transition(Screen::Bootsplash).await;
|
||||
Timer::after_secs(3).await;
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
|
||||
use embassy_sync::{channel::DynamicReceiver, pubsub::DynPublisher};
|
||||
use embassy_time::Duration;
|
||||
use log::*;
|
||||
|
||||
use crate::{ego::engine::{gps_to_local_meters_haversine, MotionState}, events::{Notification, Prediction, Scene, Telemetry}, idle::IdleClock};
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn prediction_task(prediction_src: DynamicReceiver<'static, Prediction>, notify: DynPublisher<'static, Notification>, telemetery: DynPublisher<'static, Telemetry>) {
|
||||
let mut last_velocity = 0.0;
|
||||
let mut first_position = None;
|
||||
let mut last_position = Default::default();
|
||||
let mut parking_timer = IdleClock::new(Duration::from_secs(10));
|
||||
let mut sleep_timer = IdleClock::new(Duration::from_secs(30));
|
||||
let mut stationary = true;
|
||||
loop {
|
||||
let d = first_position.map(|x| {
|
||||
gps_to_local_meters_haversine(&x, &last_position).norm()
|
||||
});
|
||||
if let Ok(next_evt) = embassy_time::with_timeout(Duration::from_secs(1), prediction_src.receive()).await {
|
||||
telemetery.publish(Telemetry::Prediction(next_evt)).await;
|
||||
match next_evt {
|
||||
Prediction::WakeRequested => {
|
||||
if sleep_timer.wake() {
|
||||
warn!("Wake requested during sleep");
|
||||
notify.publish(Notification::WakeUp).await;
|
||||
notify.publish(Notification::SetHeadlight(true)).await;
|
||||
notify.publish(Notification::SetBrakelight(true)).await;
|
||||
|
||||
// Also reset the parking timer
|
||||
parking_timer.wake();
|
||||
} else if parking_timer.wake() {
|
||||
info!("Wake requested while parked");
|
||||
// If we weren't asleep but we were parked, then switch back to the Ready state and turn on the lights
|
||||
notify.publish(Notification::SetHeadlight(true)).await;
|
||||
notify.publish(Notification::SetBrakelight(true)).await;
|
||||
notify.publish(Notification::SceneChange(Scene::Ready)).await;
|
||||
}
|
||||
}
|
||||
Prediction::Velocity(v) => {
|
||||
last_velocity = v;
|
||||
// TODO: Probably makes sense to only print this based on an IdleTimer, so that a long period of slightly variable movement doesn't get lost, but we can still report values to the UI / telemetry outputs
|
||||
//info!("Velocity predict: velocity={v}\tpos={last_position:?}\tdistance={d:?}");
|
||||
},
|
||||
Prediction::Location(loc) => {
|
||||
if first_position.is_none() {
|
||||
info!("Got location={loc:?}");
|
||||
first_position = Some(loc);
|
||||
}
|
||||
last_position = loc;
|
||||
}
|
||||
Prediction::Motion(motion) => {
|
||||
info!("Motion predict:\t{motion:?}\tvelocity={last_velocity}\tpos={last_position:?}\tdistance={d:?}");
|
||||
if sleep_timer.wake() {
|
||||
notify.publish(Notification::WakeUp).await;
|
||||
notify.publish(Notification::SetHeadlight(true)).await;
|
||||
notify.publish(Notification::SetBrakelight(true)).await
|
||||
}
|
||||
|
||||
if parking_timer.wake() {
|
||||
notify.publish(Notification::SetHeadlight(true)).await;
|
||||
notify.publish(Notification::SetBrakelight(true)).await
|
||||
}
|
||||
match motion {
|
||||
MotionState::Accelerating => {
|
||||
if stationary {
|
||||
// If we are going from standing still to immediately accelerating, first transition to the 'ready' scene
|
||||
notify.publish(Notification::SceneChange(Scene::Ready)).await;
|
||||
}
|
||||
notify.publish(Notification::SceneChange(Scene::Accelerating)).await;
|
||||
stationary = false;
|
||||
},
|
||||
MotionState::Decelerating => {
|
||||
if stationary {
|
||||
// If we are going from standing still to immediately accelerating, first transition to the 'ready' scene
|
||||
notify.publish(Notification::SceneChange(Scene::Ready)).await;
|
||||
}
|
||||
notify.publish(Notification::SceneChange(Scene::Decelerating)).await;
|
||||
stationary = false;
|
||||
},
|
||||
MotionState::Steady => {
|
||||
notify.publish(Notification::SceneChange(Scene::Ready)).await;
|
||||
stationary = false;
|
||||
},
|
||||
MotionState::Stationary => {
|
||||
notify.publish(Notification::SceneChange(Scene::Ready)).await;
|
||||
stationary = true
|
||||
}
|
||||
}
|
||||
},
|
||||
Prediction::SensorStatus(src, status) => {
|
||||
notify.publish(Notification::SensorStatus(src, status)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Need a way to detect if sensors are dead for some reason. Probably should be done in the motion engine, since it would be a prediction?
|
||||
|
||||
if stationary {
|
||||
if parking_timer.check() {
|
||||
warn!("Engaging parking brake");
|
||||
notify.publish(Notification::SceneChange(Scene::Idle)).await;
|
||||
notify.publish(Notification::SetHeadlight(false)).await;
|
||||
notify.publish(Notification::SetBrakelight(false)).await
|
||||
}
|
||||
|
||||
if sleep_timer.check() {
|
||||
warn!("Sleeping!");
|
||||
notify.publish(Notification::Sleep).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use embassy_sync::pubsub::DynSubscriber;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::Duration;
|
||||
use figments::prelude::*;
|
||||
use figments_render::output::Brightness;
|
||||
use rgb::Rgba;
|
||||
@@ -7,7 +7,7 @@ use core::fmt::Debug;
|
||||
use futures::join;
|
||||
use log::*;
|
||||
|
||||
use crate::{animation::{AnimDisplay, AnimatedSurface, Animation}, events::{Notification, Prediction}, graphics::{display::{DisplayControls, SegmentSpace, Uniforms}, shaders::*}, tasks::ui::UiSurfacePool};
|
||||
use crate::{animation::{AnimDisplay, AnimatedSurface, Animation}, events::{Personality, Prediction}, graphics::{display::{DisplayControls, SegmentSpace, Uniforms}, shaders::*}, tasks::ui::UiSurfacePool};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SafetyUi<S: Surface> {
|
||||
@@ -92,43 +92,35 @@ impl<S: Debug + Surface<Uniforms = Uniforms, CoordinateSpace = SegmentSpace, Pix
|
||||
info!("Fade out overlay");
|
||||
TURN_OFF.apply(&mut self.overlay).await;
|
||||
self.overlay.set_visible(false);
|
||||
Timer::after_secs(3).await;
|
||||
warn!("Turning off safety lights");
|
||||
join!(
|
||||
TURN_OFF.apply(&mut self.headlight),
|
||||
TURN_OFF.apply(&mut self.brakelight)
|
||||
);
|
||||
info!("Wakeup complete!");
|
||||
}
|
||||
|
||||
pub async fn on_event(&mut self, event: Notification) {
|
||||
match event {
|
||||
Notification::SceneChange(_) => (), // We already log this inside apply_scene()
|
||||
evt => info!("SafetyUI event: {evt:?}")
|
||||
}
|
||||
|
||||
match event {
|
||||
// Toggling head and brake lights
|
||||
// FIXME: These should be a Off/Low/High enum, so the stopping brake looks different from the dayrunning brake.
|
||||
Notification::SetBrakelight(is_on) => {
|
||||
if is_on {
|
||||
TURN_ON.apply(&mut self.brakelight).await;
|
||||
} else {
|
||||
TURN_OFF.apply(&mut self.brakelight).await;
|
||||
}
|
||||
pub async fn on_event(&mut self, event: Prediction) {
|
||||
if let Prediction::SetPersonality(personality) = event { match personality {
|
||||
Personality::Active => {
|
||||
// FIXME: These should be a Off/Low/High enum, so the stopping brake looks different from the dayrunning brake.
|
||||
warn!("Active personality: Turning on safety lights");
|
||||
join!(
|
||||
TURN_ON.apply(&mut self.brakelight),
|
||||
TURN_ON.apply(&mut self.headlight)
|
||||
);
|
||||
},
|
||||
Notification::SetHeadlight(is_on) => {
|
||||
if is_on {
|
||||
TURN_ON.apply(&mut self.headlight).await;
|
||||
} else {
|
||||
TURN_OFF.apply(&mut self.headlight).await;
|
||||
}
|
||||
Personality::Parked => {
|
||||
warn!("Idle personality: Turning off safety lights");
|
||||
join!(
|
||||
TURN_OFF.apply(&mut self.brakelight),
|
||||
TURN_OFF.apply(&mut self.headlight)
|
||||
);
|
||||
},
|
||||
|
||||
Notification::Sleep => self.sleep().await,
|
||||
Notification::WakeUp => self.wake().await,
|
||||
_ => ()
|
||||
}
|
||||
Personality::Sleeping => {
|
||||
warn!("Sleeping personality: Safety UI is going to sleep");
|
||||
self.sleep().await;
|
||||
},
|
||||
Personality::Waking => {
|
||||
warn!("Waking personality: Waking up safety UI");
|
||||
self.wake().await;
|
||||
},
|
||||
} }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +128,7 @@ const TURN_ON: Animation = Animation::new().duration(Duration::from_secs(1)).fro
|
||||
const TURN_OFF: Animation = Animation::new().duration(Duration::from_secs(1)).from(255).to(0);
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn safety_ui_main(mut events: DynSubscriber<'static, Notification>, mut ui: SafetyUi<<UiSurfacePool as Surfaces<SegmentSpace>>::Surface>) {
|
||||
pub async fn safety_ui_main(mut events: DynSubscriber<'static, Prediction>, mut ui: SafetyUi<<UiSurfacePool as Surfaces<SegmentSpace>>::Surface>) {
|
||||
// Wait for the renderer to start running
|
||||
//ui.display.render_is_running.wait().await;
|
||||
trace!("spooling until render starts ui={ui:?}");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use embassy_sync::pubsub::{DynPublisher, DynSubscriber};
|
||||
use embassy_sync::pubsub::DynSubscriber;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use figments::prelude::*;
|
||||
use rgb::{Rgb, Rgba};
|
||||
@@ -6,7 +6,7 @@ use core::fmt::Debug;
|
||||
use futures::join;
|
||||
use log::*;
|
||||
|
||||
use crate::{animation::{AnimatedSurface, Animation}, events::{Notification, Scene, SensorSource, SensorState, Telemetry}, graphics::{display::{SegmentSpace, Uniforms}, shaders::*}};
|
||||
use crate::{animation::{AnimatedSurface, Animation}, ego::engine::MotionState, events::{Personality, Prediction, Scene, SensorSource, SensorState}, graphics::{display::{SegmentSpace, Uniforms}, shaders::*}};
|
||||
|
||||
pub struct Ui<S: Surface> {
|
||||
// Background layer provides an always-running background for everything to draw on
|
||||
@@ -132,33 +132,32 @@ impl<S: Debug + Surface<Uniforms = Uniforms, CoordinateSpace = SegmentSpace, Pix
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn on_event(&mut self, event: Notification) {
|
||||
pub async fn on_event(&mut self, event: Prediction) {
|
||||
match event {
|
||||
Notification::SceneChange(_) => (), // We already log this inside apply_scene()
|
||||
evt => info!("UI event: {evt:?}")
|
||||
}
|
||||
match event {
|
||||
// TODO: We probably also want some events to indicate when the ESP has no calibration data or otherwise needs re-calibrated and is waiting for the bike to stand still
|
||||
Notification::SensorStatus(SensorSource::IMU, SensorState::Online) => self.flash_notification_color(Rgb::new(0, 255, 0)).await,
|
||||
Notification::SensorStatus(SensorSource::Location, SensorState::Degraded) => self.flash_notification_color(Rgb::new(255, 0, 0)).await,
|
||||
Notification::SensorStatus(SensorSource::GPS, SensorState::Online) => self.flash_notification_color(Rgb::new(0, 255, 255)).await,
|
||||
|
||||
// Scene change
|
||||
Notification::SceneChange(scene) => self.apply_scene(scene).await,
|
||||
|
||||
Notification::WakeUp => self.show().await,
|
||||
Prediction::SetPersonality(personality) => match personality {
|
||||
Personality::Active => self.apply_scene(Scene::Ready).await,
|
||||
Personality::Parked => self.apply_scene(Scene::Idle).await,
|
||||
Personality::Waking => self.show().await,
|
||||
_ => ()
|
||||
},
|
||||
Prediction::Motion { prev: _, next: MotionState::Accelerating } => self.apply_scene(Scene::Accelerating).await,
|
||||
Prediction::Motion { prev: _, next: MotionState::Decelerating } => self.apply_scene(Scene::Decelerating).await,
|
||||
Prediction::Motion { prev: _, next: MotionState::Steady } => self.apply_scene(Scene::Ready).await,
|
||||
Prediction::Motion { prev: _, next: MotionState::Stationary } => self.apply_scene(Scene::Ready).await,
|
||||
Prediction::SensorStatus(SensorSource::IMU, SensorState::Online) => self.flash_notification_color(Rgb::new(0, 255, 0)).await,
|
||||
Prediction::SensorStatus(SensorSource::Location, SensorState::Degraded) => self.flash_notification_color(Rgb::new(255, 0, 0)).await,
|
||||
Prediction::SensorStatus(SensorSource::GPS, SensorState::Online) => self.flash_notification_color(Rgb::new(0, 255, 255)).await,
|
||||
_ => ()
|
||||
|
||||
// Other event ideas:
|
||||
// - Bike has crashed, or is laid down
|
||||
// - Unstable physics right before crashing?
|
||||
// - Turning left/right
|
||||
// - BPM sync with phone app
|
||||
// - GPS data is being synchronized with nextcloud/whatever
|
||||
// - A periodic flash when re-initializing MPU and GPS, to indicate there might be a problem?
|
||||
// - Bluetooth/BLE connect/disconnect events
|
||||
// - Bike is waking up from stationary?
|
||||
}
|
||||
// Other event ideas:
|
||||
// - Bike has crashed, or is laid down
|
||||
// - Unstable physics right before crashing?
|
||||
// - Turning left/right
|
||||
// - BPM sync with phone app
|
||||
// - GPS data is being synchronized with nextcloud/whatever
|
||||
// - A periodic flash when re-initializing MPU and GPS, to indicate there might be a problem?
|
||||
// - Bluetooth/BLE connect/disconnect events
|
||||
// - Bike is waking up from stationary?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +199,7 @@ pub type UiSurfacePool = NullBufferPool<Uniforms, SegmentSpace, Rgba<u8>>;
|
||||
pub type UiSurfacePool = BufferedSurfacePool<Uniforms, SegmentSpace, Rgba<u8>>;
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn ui_main(mut events: DynSubscriber<'static, Notification>, telemetery: DynPublisher<'static, Telemetry>, mut ui: Ui<<UiSurfacePool as Surfaces<SegmentSpace>>::Surface>) {
|
||||
pub async fn ui_main(mut events: DynSubscriber<'static, Prediction>, mut ui: Ui<<UiSurfacePool as Surfaces<SegmentSpace>>::Surface>) {
|
||||
// FIXME: This should instead wait on some kind of flag set by the safety UI, or else we risk painting before we even have a display up and running
|
||||
Timer::after_secs(3).await;
|
||||
ui.show().await;
|
||||
@@ -212,6 +211,5 @@ pub async fn ui_main(mut events: DynSubscriber<'static, Notification>, telemeter
|
||||
loop {
|
||||
let evt = events.next_message_pure().await;
|
||||
ui.on_event(evt).await;
|
||||
telemetery.publish(Telemetry::Notification(evt)).await;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ use nalgebra::Vector2;
|
||||
use reqwless::client::{HttpClient, TlsConfig};
|
||||
use static_cell::StaticCell;
|
||||
|
||||
use crate::{backoff::Backoff, events::{Prediction, Telemetry}};
|
||||
use crate::{backoff::Backoff, events::{Prediction}};
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn net_task(mut runner: embassy_net::Runner<'static, WifiDevice<'static>>) {
|
||||
@@ -25,7 +25,7 @@ static RESOURCES: StaticCell<StackResources<5>> = StaticCell::new();
|
||||
|
||||
// TODO: Wifi task needs to know when there is data to upload, so it only connects when needed.
|
||||
#[embassy_executor::task]
|
||||
pub async fn wireless_task(mut telemetry: DynSubscriber<'static, Telemetry>, wifi_init: &'static mut Controller<'static>, wifi_device: esp_hal::peripherals::WIFI<'static>) {
|
||||
pub async fn wireless_task(mut predictions: DynSubscriber<'static, Prediction>, wifi_init: &'static mut Controller<'static>, wifi_device: esp_hal::peripherals::WIFI<'static>) {
|
||||
let (mut wifi, interfaces) = esp_radio::wifi::new(wifi_init, wifi_device, esp_radio::wifi::Config::default())
|
||||
.expect("Failed to initialize WIFI!");
|
||||
wifi.set_config(&esp_radio::wifi::ModeConfig::Client(
|
||||
@@ -81,7 +81,7 @@ pub async fn wireless_task(mut telemetry: DynSubscriber<'static, Telemetry>, wif
|
||||
let mut client = HttpClient::new_with_tls(&tcp, &dns, tls);
|
||||
|
||||
loop {
|
||||
if let Telemetry::Prediction(Prediction::Location(coords)) = telemetry.next_message_pure().await {
|
||||
if let Prediction::Location(coords) = predictions.next_message_pure().await {
|
||||
if let Err(e) = push_location(&mut client, coords).await {
|
||||
error!("HTTP error in publishing location: {e:?}");
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user