diff --git a/common/src/lib.rs b/common/src/lib.rs index f09af96..13791c5 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; /// -1..1 pub type Speed = f32; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub enum ControlPacket { /// Forward, Clockwise Twist(Speed, Speed), diff --git a/interface/src/gui.rs b/interface/src/gui.rs index 4f74cc3..2d5596f 100644 --- a/interface/src/gui.rs +++ b/interface/src/gui.rs @@ -1,9 +1,13 @@ +use std::cell::OnceCell; + use common::{ControlPacket, TelemetryPacket}; -use eframe::egui::{self, Align2}; +use eframe::egui::{self, containers, Align2, Checkbox, Context, Label}; use tokio::sync::{mpsc, watch::Receiver}; use egui_toast::{Toast, Toasts}; +pub const GUI: OnceCell = OnceCell::new(); + pub fn gui(data: Receiver, toasts: mpsc::Receiver) -> eframe::Result { let options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]), @@ -43,8 +47,21 @@ impl GUI { impl eframe::App for GUI { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + let _ = GUI.set(ctx.clone()); egui::CentralPanel::default().show(ctx, |ui| { ui.heading("Cruise Control"); + + if let Some(ref command) = self.data.borrow().last_command { + ui.label(format!("sending {command:?}")); + } + if let Some(ref telem) = self.data.borrow().telemetry { + ui.label(format!("Left tof: {}", if let Some(tof) = telem.sensors.tof_l {format!("✅ {tof}mm")} else {"❌".into()})); + ui.label(format!("Right tof: {}", if let Some(tof) = telem.sensors.tof_r {format!("✅ {tof}mm")} else {"❌".into()})); + ui.label(format!("Side tof: {}", if let Some(tof) = telem.sensors.tof_s {format!("✅ {tof}mm")} else {"❌".into()})); + ui.label(format!("Gyro: {}", if telem.sensors.gyro.is_some() {"✅"} else {"❌"})); + } else { + ui.label("disconnected"); + } }); let mut toasts = Toasts::new() .anchor(Align2::RIGHT_BOTTOM, (-10.0, -10.0)) // 10 units from the bottom right corner diff --git a/interface/src/main.rs b/interface/src/main.rs index 3cf1423..dca7b64 100644 --- a/interface/src/main.rs +++ b/interface/src/main.rs @@ -6,7 +6,7 @@ use anyhow::{Context, Ok, Result}; use common::{ControlPacket, TelemetryPacket}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use egui_toast::{Toast, ToastKind}; -use gui::{gui, GUIData}; +use gui::{gui, GUIData, GUI}; use pitch_detection::{detector::{mcleod::McLeodDetector, PitchDetector}, utils}; use rust_music_theory::note::{Note, NoteLetter, Pitch, Tuning}; use tokio::{io::{AsyncReadExt, AsyncWriteExt, BufWriter, WriteHalf}, net::{tcp::{OwnedReadHalf, OwnedWriteHalf}, TcpStream}, spawn, sync::{self, mpsc, watch, RwLock}, time::timeout}; @@ -68,7 +68,7 @@ fn main() -> Result<()> { Ok(control) }).unwrap(); - executor.block_on(controller(notes, control)).unwrap() + executor.block_on(controller(notes, control, data_sender.clone())).unwrap() }); println!("launching gui"); @@ -92,10 +92,11 @@ async fn telemetry_handler(mut telem: OwnedReadHalf, gui: watch::Sender gui.send_modify(|gui| { gui.telemetry = Some(telem); }); + GUI.get().map(|c| c.request_repaint()); } } -async fn controller(mut notes: mpsc::Receiver<(Option>, f32)>, controller: OwnedWriteHalf) -> Result<()> { +async fn controller(mut notes: mpsc::Receiver<(Option>, f32)>, controller: OwnedWriteHalf, gui: watch::Sender) -> Result<()> { let mut controller = BufWriter::new(controller); //send_packet(&mut controller, ControlPacket::Arm(true)).await?; //println!("armed flipper"); @@ -123,10 +124,13 @@ async fn controller(mut notes: mpsc::Receiver<(Option