From 7bae34061d45b073a18e81d3863be88b31ec6705 Mon Sep 17 00:00:00 2001 From: Carlos Guerra Date: Wed, 22 Apr 2026 00:09:37 +0200 Subject: [PATCH] fixes requested, gps timestamp corrected, more error managing, more border conditions covered --- daemon/src/gps.rs | 37 +++++++++++++++++++++++++++--- daemon/src/main.rs | 7 ++++-- daemon/src/server.rs | 10 +++++--- daemon/web/src/routes/+page.svelte | 6 ++--- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/daemon/src/gps.rs b/daemon/src/gps.rs index 3158fca..83ff70e 100644 --- a/daemon/src/gps.rs +++ b/daemon/src/gps.rs @@ -1,8 +1,7 @@ use axum::Json; use axum::extract::State; use axum::http::StatusCode; -use chrono::Utc; -use log::{error, warn}; +use log::{error, info, warn}; use serde::{Deserialize, Deserializer, Serialize}; use std::sync::Arc; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; @@ -10,6 +9,34 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use crate::config::GpsMode; use crate::server::ServerState; +fn deserialize_latitude<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + use serde::de; + let v = f64::deserialize(deserializer)?; + if !(-90.0..=90.0).contains(&v) { + return Err(de::Error::custom(format!( + "latitude {v} out of range [-90, 90]" + ))); + } + Ok(v) +} + +fn deserialize_longitude<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + use serde::de; + let v = f64::deserialize(deserializer)?; + if !(-180.0..=180.0).contains(&v) { + return Err(de::Error::custom(format!( + "longitude {v} out of range [-180, 180]" + ))); + } + Ok(v) +} + fn deserialize_unix_ts<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -34,7 +61,9 @@ where #[derive(Clone, Debug, Serialize, Deserialize)] pub struct GpsData { + #[serde(deserialize_with = "deserialize_latitude")] pub latitude: f64, + #[serde(deserialize_with = "deserialize_longitude")] pub longitude: f64, #[serde(deserialize_with = "deserialize_unix_ts")] pub timestamp: i64, @@ -88,7 +117,7 @@ pub async fn post_gps( match qmdl_store.open_entry_gps_for_append(entry_idx).await { Ok(Some(mut file)) => { let record = GpsRecord { - unix_ts: Utc::now().timestamp(), + unix_ts: gps_data.timestamp, lat: gps_data.latitude, lon: gps_data.longitude, }; @@ -117,6 +146,8 @@ pub async fn post_gps( )); } } + } else { + info!("GPS data received but no recording is active — position updated in memory only, not persisted to sidecar"); } Ok(StatusCode::OK) diff --git a/daemon/src/main.rs b/daemon/src/main.rs index ad79161..8610950 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -43,7 +43,7 @@ use diag::{ DiagDeviceCtrlMessage, delete_all_recordings, delete_recording, get_analysis_report, start_recording, stop_recording, }; -use log::{error, info}; +use log::{error, info, warn}; use qmdl_store::RecordingStoreError; use rayhunter::Device; use stats::get_log; @@ -315,7 +315,10 @@ async fn run_with_config( longitude: lon, timestamp: 0, }), - _ => None, + _ => { + warn!("gps_mode is Fixed but gps_fixed_latitude or gps_fixed_longitude is missing from config — no GPS coordinates will be recorded"); + None + } } } else { None diff --git a/daemon/src/server.rs b/daemon/src/server.rs index 6756baa..e1bb254 100644 --- a/daemon/src/server.rs +++ b/daemon/src/server.rs @@ -22,7 +22,7 @@ use tokio_util::io::ReaderStream; use tokio_util::sync::CancellationToken; use crate::analysis::{AnalysisCtrlMessage, AnalysisStatus}; -use crate::config::Config; +use crate::config::{Config, GpsMode}; use crate::diag::DiagDeviceCtrlMessage; use crate::display::DisplayState; use crate::gps::GpsData; @@ -162,8 +162,12 @@ pub async fn get_config( ))] pub async fn set_config( State(state): State>, - Json(config): Json, + Json(mut config): Json, ) -> Result<(StatusCode, String), (StatusCode, String)> { + if config.gps_mode != GpsMode::Fixed { + config.gps_fixed_latitude = None; + config.gps_fixed_longitude = None; + } let mut config_to_write = config.clone(); config_to_write.wifi_ssid = None; config_to_write.wifi_password = None; @@ -509,7 +513,7 @@ pub async fn debug_set_display_state( #[cfg(test)] mod tests { use super::*; - use crate::config::GpsMode; + use crate::config::GpsMode as _; use async_zip::base::read::mem::ZipFileReader; use axum::extract::{Path, State}; use tempfile::TempDir; diff --git a/daemon/web/src/routes/+page.svelte b/daemon/web/src/routes/+page.svelte index a11cf9d..a31cb75 100644 --- a/daemon/web/src/routes/+page.svelte +++ b/daemon/web/src/routes/+page.svelte @@ -25,10 +25,6 @@ let gps_data: GpsData | null = $state(null); let gps_mode: GpsMode = $state(GpsMode.Disabled); $effect(() => { - get_config().then((c) => { - gps_mode = c.gps_mode; - }); - const interval = setInterval(async () => { try { // Don't update UI if browser tab isn't visible @@ -46,6 +42,8 @@ current_entry = new_manifest.current_entry; system_stats = await get_system_stats(); + const config = await get_config(); + gps_mode = config.gps_mode; gps_data = await get_gps(); update_error = undefined; loaded = true;