[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 <codex@openai.com> Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
@@ -296,6 +296,15 @@ impl ServerConfig {
|
|||||||
if self.pskreporter.port == 0 {
|
if self.pskreporter.port == 0 {
|
||||||
return Err("[pskreporter].port must be > 0".to_string());
|
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(())
|
Ok(())
|
||||||
@@ -560,6 +569,22 @@ tokens = ["secret123"]
|
|||||||
assert!(config.validate().is_err());
|
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]
|
#[test]
|
||||||
fn test_default_search_paths_include_legacy_home_file() {
|
fn test_default_search_paths_include_legacy_home_file() {
|
||||||
let paths = ServerConfig::default_search_paths();
|
let paths = ServerConfig::default_search_paths();
|
||||||
|
|||||||
@@ -188,10 +188,19 @@ fn build_rig_task_config(
|
|||||||
registry: std::sync::Arc<RegistrationContext>,
|
registry: std::sync::Arc<RegistrationContext>,
|
||||||
) -> rig_task::RigTaskConfig {
|
) -> rig_task::RigTaskConfig {
|
||||||
let pskreporter_status = if cfg.pskreporter.enabled {
|
let pskreporter_status = if cfg.pskreporter.enabled {
|
||||||
Some(format!(
|
let has_locator = cfg.pskreporter.receiver_locator.is_some()
|
||||||
"Enabled ({}:{})",
|
|| (resolved.latitude.is_some() && resolved.longitude.is_some());
|
||||||
cfg.pskreporter.host, cfg.pskreporter.port
|
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 {
|
} else {
|
||||||
Some("Disabled".to_string())
|
Some("Disabled".to_string())
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||||||
|
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
use tokio::sync::{broadcast, watch};
|
use tokio::sync::{broadcast, watch};
|
||||||
|
use tokio::time::{self, Duration};
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use trx_core::decode::DecodedMessage;
|
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 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 {
|
loop {
|
||||||
tokio::select! {
|
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() => {
|
changed = state_rx.changed() => {
|
||||||
if changed.is_err() {
|
if changed.is_err() {
|
||||||
break;
|
break;
|
||||||
@@ -99,13 +111,20 @@ pub async fn run_pskreporter_uplink(
|
|||||||
}
|
}
|
||||||
Err(broadcast::error::RecvError::Closed) => break,
|
Err(broadcast::error::RecvError::Closed) => break,
|
||||||
};
|
};
|
||||||
|
stats_received += 1;
|
||||||
|
|
||||||
let spot = match decoded_to_spot(decoded, current_freq_hz) {
|
let spot = match decoded_to_spot(decoded, current_freq_hz) {
|
||||||
Some(spot) => spot,
|
Some(spot) => spot,
|
||||||
None => continue,
|
None => {
|
||||||
|
stats_skipped += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if let Err(err) = client.send_spot(&spot).await {
|
if let Err(err) = client.send_spot(&spot).await {
|
||||||
warn!("PSK Reporter send failed: {}", err);
|
warn!("PSK Reporter send failed: {}", err);
|
||||||
|
stats_send_err += 1;
|
||||||
|
} else {
|
||||||
|
stats_sent += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user