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; } } }