From a1d56dc1d0aa47f3ad27c5b5f34c95a7a5c5e322 Mon Sep 17 00:00:00 2001 From: Stanislaw Grams Date: Fri, 13 Feb 2026 00:05:54 +0100 Subject: [PATCH] [fix](trx-server): make PSK Reporter activation diagnosable Require a receiver locator source when PSK Reporter is enabled, show inactive reason in status text, and add periodic uplink runtime counters (received/sent/skipped/errors). This makes missing-spot issues visible instead of silently dropping all decode events. Co-authored-by: Codex Signed-off-by: Stanislaw Grams --- src/trx-server/src/config.rs | 25 +++++++++++++++++++++++++ src/trx-server/src/main.rs | 17 +++++++++++++---- src/trx-server/src/pskreporter.rs | 21 ++++++++++++++++++++- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/trx-server/src/config.rs b/src/trx-server/src/config.rs index bb393d2..2bf9bd3 100644 --- a/src/trx-server/src/config.rs +++ b/src/trx-server/src/config.rs @@ -296,6 +296,15 @@ impl ServerConfig { if self.pskreporter.port == 0 { return Err("[pskreporter].port must be > 0".to_string()); } + if self.pskreporter.receiver_locator.is_none() + && (self.general.latitude.is_none() || self.general.longitude.is_none()) + { + return Err( + "[pskreporter] enabled requires either [pskreporter].receiver_locator \ + or [general].latitude and [general].longitude" + .to_string(), + ); + } } Ok(()) @@ -560,6 +569,22 @@ tokens = ["secret123"] assert!(config.validate().is_err()); } + #[test] + fn test_validate_pskreporter_requires_locator_source() { + let mut config = ServerConfig::default(); + config.rig.access.port = Some("/dev/ttyUSB0".to_string()); + config.rig.access.baud = Some(9600); + config.pskreporter.enabled = true; + config.pskreporter.receiver_locator = None; + config.general.latitude = None; + config.general.longitude = None; + assert!(config.validate().is_err()); + + config.general.latitude = Some(52.0); + config.general.longitude = Some(21.0); + assert!(config.validate().is_ok()); + } + #[test] fn test_default_search_paths_include_legacy_home_file() { let paths = ServerConfig::default_search_paths(); diff --git a/src/trx-server/src/main.rs b/src/trx-server/src/main.rs index 67f3418..59e1021 100644 --- a/src/trx-server/src/main.rs +++ b/src/trx-server/src/main.rs @@ -188,10 +188,19 @@ fn build_rig_task_config( registry: std::sync::Arc, ) -> rig_task::RigTaskConfig { let pskreporter_status = if cfg.pskreporter.enabled { - Some(format!( - "Enabled ({}:{})", - cfg.pskreporter.host, cfg.pskreporter.port - )) + let has_locator = cfg.pskreporter.receiver_locator.is_some() + || (resolved.latitude.is_some() && resolved.longitude.is_some()); + if has_locator { + Some(format!( + "Enabled ({}:{})", + cfg.pskreporter.host, cfg.pskreporter.port + )) + } else { + Some(format!( + "Enabled but inactive (missing locator source) ({}:{})", + cfg.pskreporter.host, cfg.pskreporter.port + )) + } } else { Some("Disabled".to_string()) }; diff --git a/src/trx-server/src/pskreporter.rs b/src/trx-server/src/pskreporter.rs index 060101f..391e912 100644 --- a/src/trx-server/src/pskreporter.rs +++ b/src/trx-server/src/pskreporter.rs @@ -6,6 +6,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use tokio::net::UdpSocket; use tokio::sync::{broadcast, watch}; +use tokio::time::{self, Duration}; use tracing::{info, warn}; use trx_core::decode::DecodedMessage; @@ -81,9 +82,20 @@ pub async fn run_pskreporter_uplink( ); let mut current_freq_hz = state_rx.borrow().status.freq.hz; + let mut stats_received: u64 = 0; + let mut stats_sent: u64 = 0; + let mut stats_skipped: u64 = 0; + let mut stats_send_err: u64 = 0; + let mut stats_tick = time::interval(Duration::from_secs(60)); loop { tokio::select! { + _ = stats_tick.tick() => { + info!( + "PSK Reporter stats: received={}, sent={}, skipped={}, send_errors={}", + stats_received, stats_sent, stats_skipped, stats_send_err + ); + } changed = state_rx.changed() => { if changed.is_err() { break; @@ -99,13 +111,20 @@ pub async fn run_pskreporter_uplink( } Err(broadcast::error::RecvError::Closed) => break, }; + stats_received += 1; let spot = match decoded_to_spot(decoded, current_freq_hz) { Some(spot) => spot, - None => continue, + None => { + stats_skipped += 1; + continue; + } }; if let Err(err) = client.send_spot(&spot).await { warn!("PSK Reporter send failed: {}", err); + stats_send_err += 1; + } else { + stats_sent += 1; } } }