diff --git a/Cargo.lock b/Cargo.lock index a36da1424e28a8641303c940af0f665ddaf0b34d..1dea7a6d50c5421632d57d200e752c9e8f720dd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2003,19 +2003,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "mavlink-bindgen" -version = "0.14.0" -dependencies = [ - "crc-any", - "lazy_static", - "proc-macro2", - "quick-xml 0.36.2", - "quote", - "serde", - "thiserror 1.0.69", -] - [[package]] name = "mavlink-bindgen" version = "0.14.0" @@ -2987,7 +2974,7 @@ dependencies = [ "egui_plot", "egui_tiles", "enum_dispatch", - "mavlink-bindgen 0.14.0", + "mavlink-bindgen", "profiling", "rand 0.9.0", "ring-channel", @@ -3162,9 +3149,10 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "skyward_mavlink" version = "0.1.1" +source = "git+https://git.skywarder.eu/avn/swd/mavlink/mavlink-skyward-lib.git?branch=rust-strum#8f0700acc0def0cdb2d2ae490e0703fd6c820643" dependencies = [ "bitflags 2.9.0", - "mavlink-bindgen 0.14.0 (git+https://git.skywarder.eu/avn/swd/mavlink/rust-mavlink.git?rev=b7446436b3c96ca4c40d28b54eeed346e7bf021e)", + "mavlink-bindgen", "mavlink-core", "num-derive", "num-traits", diff --git a/Cargo.toml b/Cargo.toml index f6be7f44b8911bbc0326646437d784ddc6eb244a..d7507aa49ed77f86c2121a11b03fd0b0e2607599 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,20 +18,11 @@ egui_file = "0.22" # =========== Asynchronous =========== tokio = { version = "1.41", features = ["rt-multi-thread", "net", "sync"] } # =========== Mavlink =========== -# skyward_mavlink = { git = "https://git.skywarder.eu/avn/swd/mavlink/mavlink-skyward-lib.git", branch = "rust-strum", features = [ -# "reflection", -# "orion", -# "serde", -# ] } -skyward_mavlink = { path = "../mavlink-skyward-lib/mavlink_rust", features = [ +skyward_mavlink = { git = "https://git.skywarder.eu/avn/swd/mavlink/mavlink-skyward-lib.git", branch = "rust-strum", features = [ "reflection", "orion", "serde", ] } -# mavlink-bindgen = { version = "0.14", features = ["serde"] } -mavlink-bindgen = { path = "../rust-mavlink/mavlink-bindgen", features = [ - "serde", -] } serialport = "4.7.0" # ========= Persistency ========= serde = { version = "1.0", features = ["derive"] } @@ -51,5 +42,10 @@ anyhow = "1.0" ring-channel = "0.12.0" thiserror = "2.0.7" +[dependencies.mavlink-bindgen] +git = "https://git.skywarder.eu/avn/swd/mavlink/rust-mavlink.git" +rev = "b7446436b3c96ca4c40d28b54eeed346e7bf021e" +features = ["serde"] + [dev-dependencies] rand = "0.9.0" diff --git a/src/communication/serial.rs b/src/communication/serial.rs index 8f1c6fa73b6c4c924357f0050857d371f02d4762..b4d3897c8b563727e67dfb15e277cd9cae91dccd 100644 --- a/src/communication/serial.rs +++ b/src/communication/serial.rs @@ -51,6 +51,40 @@ pub fn find_first_stm32_port() -> Result<Option<SerialPortInfo>, serialport::Err Ok(None) } +pub mod cached { + use egui::Context; + + use crate::ui::cache::CacheCall; + + use super::*; + + /// Returns a cached list of all available USB ports. + /// + /// # Arguments + /// * `ctx` - The egui context used for caching. + /// + /// # Returns + /// * A Result containing a vector of `SerialPortInfo` or a `serialport::Error`. + pub fn cached_list_all_usb_ports( + ctx: &Context, + ) -> Result<Vec<SerialPortInfo>, serialport::Error> { + ctx.call_cached_short(&"list_usb_ports", list_all_usb_ports) + } + + /// Returns the first cached STM32 port found, if any. + /// + /// # Arguments + /// * `ctx` - The egui context used for caching. + /// + /// # Returns + /// * A Result containing an Option of `SerialPortInfo` or a `serialport::Error`. + pub fn cached_first_stm32_port( + ctx: &Context, + ) -> Result<Option<SerialPortInfo>, serialport::Error> { + ctx.call_cached_short(&"find_first_stm32_port", find_first_stm32_port) + } +} + /// Configuration for a serial connection. #[derive(Debug, Clone)] pub struct SerialConfiguration { diff --git a/src/mavlink/reflection.rs b/src/mavlink/reflection.rs index 68937c62c5b549a27abf81fa5bed5ae09f4540e8..c9f8a7fc585cee4d3fae97cdd3124ee9fc85a22f 100644 --- a/src/mavlink/reflection.rs +++ b/src/mavlink/reflection.rs @@ -128,10 +128,7 @@ impl IndexedField<'_> { } pub trait MessageLike { - fn to_mav_message<'a, 'b>( - &'a self, - ctx: &'b ReflectionContext, - ) -> Result<&'b MavMessage, String>; + fn to_mav_message<'b>(&self, ctx: &'b ReflectionContext) -> Result<&'b MavMessage, String>; } pub trait FieldLike<'a, 'b> { @@ -143,10 +140,7 @@ pub trait FieldLike<'a, 'b> { } impl MessageLike for u32 { - fn to_mav_message<'a, 'b>( - &'a self, - ctx: &'b ReflectionContext, - ) -> Result<&'b MavMessage, String> { + fn to_mav_message<'b>(&self, ctx: &'b ReflectionContext) -> Result<&'b MavMessage, String> { ctx.id_msg_map .get(self) .ok_or_else(|| format!("Message {} not found", self)) @@ -154,10 +148,7 @@ impl MessageLike for u32 { } impl MessageLike for &str { - fn to_mav_message<'a, 'b>( - &'a self, - ctx: &'b ReflectionContext, - ) -> Result<&'b MavMessage, String> { + fn to_mav_message<'b>(&self, ctx: &'b ReflectionContext) -> Result<&'b MavMessage, String> { ctx.mavlink_profile .messages .iter() @@ -203,6 +194,7 @@ impl<'b> FieldLike<'b, 'b> for IndexedField<'b> { }) } } + impl<'b> FieldLike<'_, 'b> for usize { fn to_mav_field( &self, @@ -221,6 +213,7 @@ impl<'b> FieldLike<'_, 'b> for usize { .ok_or_else(|| format!("Field {} not found in message {}", self, msg_id)) } } + impl<'b> FieldLike<'_, 'b> for &str { fn to_mav_field( &self, diff --git a/src/ui.rs b/src/ui.rs index 383fabd62708460d45dd65f105faf3feb5f75975..077abdba17c67d09579d71aa56bf547fbe52910f 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,5 +1,5 @@ mod app; -mod cache; +pub mod cache; mod panes; mod persistency; mod shortcuts; diff --git a/src/ui/cache.rs b/src/ui/cache.rs index 23d894d5b73859904f6767094245adcc0f44356a..9835924607803fe30d82dc326ae6d8541970abb2 100644 --- a/src/ui/cache.rs +++ b/src/ui/cache.rs @@ -13,6 +13,8 @@ use serialport::SerialPortInfo; use crate::{communication, error::ErrInstrument}; const SERIAL_PORT_REFRESH_INTERVAL: Duration = Duration::from_millis(500); +const SHORT_REFRESH_INTERVAL: Duration = Duration::from_millis(500); +const INDEF_REFRESH_INTERVAL: Duration = Duration::MAX; /// Internal helper function that caches the result of a given function call for a specified duration. /// @@ -42,7 +44,9 @@ where /// A trait to extend egui's Context with a caching function. pub trait CacheCall { - /// Calls the provided function and caches its result. + /// Calls the provided function and caches its result. Every time this + /// function is called, it will return the cached value if it is still + /// valid. /// /// # Arguments /// * `id` - A unique identifier for the cached value. @@ -52,6 +56,26 @@ pub trait CacheCall { where F: Fn() -> T, T: Clone + Send + Sync + 'static; + + fn call_cached_short<F, T, H>(&self, hashable: &H, fun: F) -> T + where + F: Fn() -> T, + T: Clone + Send + Sync + 'static, + H: Hash, + { + let id = egui::Id::new(hashable); + self.call_cached(id, fun, SHORT_REFRESH_INTERVAL) + } + + fn call_cached_indef<F, T, H>(&self, hashable: &H, fun: F) -> T + where + F: Fn() -> T, + T: Clone + Send + Sync + 'static, + H: Hash, + { + let id = egui::Id::new(hashable); + self.call_cached(id, fun, INDEF_REFRESH_INTERVAL) + } } impl CacheCall for egui::Context { @@ -65,36 +89,6 @@ impl CacheCall for egui::Context { } } -/// Returns a cached list of all available USB ports. -/// -/// # Arguments -/// * `ctx` - The egui context used for caching. -/// -/// # Returns -/// * A Result containing a vector of `SerialPortInfo` or a `serialport::Error`. -pub fn cached_list_all_usb_ports(ctx: &Context) -> Result<Vec<SerialPortInfo>, serialport::Error> { - ctx.call_cached( - egui::Id::new("list_usb_ports"), - communication::serial::list_all_usb_ports, - SERIAL_PORT_REFRESH_INTERVAL, - ) -} - -/// Returns the first cached STM32 port found, if any. -/// -/// # Arguments -/// * `ctx` - The egui context used for caching. -/// -/// # Returns -/// * A Result containing an Option of `SerialPortInfo` or a `serialport::Error`. -pub fn cached_first_stm32_port(ctx: &Context) -> Result<Option<SerialPortInfo>, serialport::Error> { - ctx.call_cached( - egui::Id::new("list_usb_ports"), - communication::serial::find_first_stm32_port, - SERIAL_PORT_REFRESH_INTERVAL, - ) -} - /// ChangeTracker manages the tracking of state changes using an integrity digest. /// /// The `integrity_digest` field holds a 64-bit unsigned integer that represents diff --git a/src/ui/panes/plot.rs b/src/ui/panes/plot.rs index 7c2e27d0ce9ed07888f0d8a41d9982874d3a05e0..9d9ad095dedb335b8a35c6ad7c3c6a7532c037bf 100644 --- a/src/ui/panes/plot.rs +++ b/src/ui/panes/plot.rs @@ -61,7 +61,7 @@ impl PaneBehavior for Plot2DPane { { plot_ui.line( Line::new(PlotPoints::from( - &points[points.len().saturating_sub(100)..], + &points[points.len().saturating_sub(100)..], // FIXME: don't show just the last 100 points )) .color(settings.color) .width(settings.width) diff --git a/src/ui/windows/connections.rs b/src/ui/windows/connections.rs index ebc34c32fcfd24d57cba0a17ff7f126d79b48e0b..30ffe5eae5606c493f4a37aae420f1b3d3254b2f 100644 --- a/src/ui/windows/connections.rs +++ b/src/ui/windows/connections.rs @@ -4,12 +4,15 @@ use tracing::{error, warn}; use crate::{ communication::{ - ConnectionError, EthernetConfiguration, SerialConfiguration, serial::DEFAULT_BAUD_RATE, + ConnectionError, EthernetConfiguration, SerialConfiguration, + serial::{ + DEFAULT_BAUD_RATE, + cached::{cached_first_stm32_port, cached_list_all_usb_ports}, + }, }, error::ErrInstrument, mavlink::DEFAULT_ETHERNET_PORT, message_broker::MessageBroker, - ui::cache::{cached_first_stm32_port, cached_list_all_usb_ports}, }; #[derive(Default)]