[feat](trx-rs): add HF APRS decoder (300 baud, 1600/1800 Hz AFSK)

Adds a second APRS demodulator path tuned for the HF APRS standard
(300 baud Bell 103-style AFSK, mark=1600 Hz / space=1800 Hz), active
on RigMode::DIG.  Shares AX.25 framing, APRS parsing, APRS-IS uplink,
and frontend display with the existing VHF stack.

- trx-aprs: parameterise Demodulator::new(); add AprsDecoder::new_hf()
- trx-core: HfAprs variant in DecodedMessage; hf_aprs_decode_enabled /
  hf_aprs_decode_reset_seq in RigState/RigSnapshot; SetHfAprsDecodeEnabled
  and ResetHfAprsDecoder commands; handlers.rs fallback arm updated
- trx-protocol: client command variants + bidirectional mapping; test
  fixture updated
- trx-server: run_hf_aprs_decoder() task (activates on DIG mode);
  hf_aprs history in DecoderHistories; rig_task command dispatch;
  aprsfi uplink forwards HfAprs via OR-pattern
- trx-frontend: hf_aprs_history in FrontendRuntimeContext
- trx-frontend-http: prune/record/snapshot/clear helpers; SSE history
  replay; toggle_hf_aprs_decode + clear_hf_aprs_decode endpoints;
  /hf-aprs.js endpoint; HF APRS tab in web UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-08 20:17:37 +01:00
parent ee821a71b1
commit 19d6d2e50b
19 changed files with 740 additions and 11 deletions
+1
View File
@@ -425,6 +425,7 @@ mod tests {
server_longitude: None,
pskreporter_status: None,
aprs_decode_enabled: false,
hf_aprs_decode_enabled: false,
cw_decode_enabled: false,
ft8_decode_enabled: false,
wspr_decode_enabled: false,
+8
View File
@@ -34,6 +34,9 @@ pub fn client_command_to_rig(cmd: ClientCommand) -> RigCommand {
ClientCommand::SetAprsDecodeEnabled { enabled } => {
RigCommand::SetAprsDecodeEnabled(enabled)
}
ClientCommand::SetHfAprsDecodeEnabled { enabled } => {
RigCommand::SetHfAprsDecodeEnabled(enabled)
}
ClientCommand::SetCwDecodeEnabled { enabled } => RigCommand::SetCwDecodeEnabled(enabled),
ClientCommand::SetCwAuto { enabled } => RigCommand::SetCwAuto(enabled),
ClientCommand::SetCwWpm { wpm } => RigCommand::SetCwWpm(wpm),
@@ -43,6 +46,7 @@ pub fn client_command_to_rig(cmd: ClientCommand) -> RigCommand {
RigCommand::SetWsprDecodeEnabled(enabled)
}
ClientCommand::ResetAprsDecoder => RigCommand::ResetAprsDecoder,
ClientCommand::ResetHfAprsDecoder => RigCommand::ResetHfAprsDecoder,
ClientCommand::ResetCwDecoder => RigCommand::ResetCwDecoder,
ClientCommand::ResetFt8Decoder => RigCommand::ResetFt8Decoder,
ClientCommand::ResetWsprDecoder => RigCommand::ResetWsprDecoder,
@@ -88,6 +92,9 @@ pub fn rig_command_to_client(cmd: RigCommand) -> ClientCommand {
RigCommand::SetAprsDecodeEnabled(enabled) => {
ClientCommand::SetAprsDecodeEnabled { enabled }
}
RigCommand::SetHfAprsDecodeEnabled(enabled) => {
ClientCommand::SetHfAprsDecodeEnabled { enabled }
}
RigCommand::SetCwDecodeEnabled(enabled) => ClientCommand::SetCwDecodeEnabled { enabled },
RigCommand::SetCwAuto(enabled) => ClientCommand::SetCwAuto { enabled },
RigCommand::SetCwWpm(wpm) => ClientCommand::SetCwWpm { wpm },
@@ -97,6 +104,7 @@ pub fn rig_command_to_client(cmd: RigCommand) -> ClientCommand {
ClientCommand::SetWsprDecodeEnabled { enabled }
}
RigCommand::ResetAprsDecoder => ClientCommand::ResetAprsDecoder,
RigCommand::ResetHfAprsDecoder => ClientCommand::ResetHfAprsDecoder,
RigCommand::ResetCwDecoder => ClientCommand::ResetCwDecoder,
RigCommand::ResetFt8Decoder => ClientCommand::ResetFt8Decoder,
RigCommand::ResetWsprDecoder => ClientCommand::ResetWsprDecoder,
+2
View File
@@ -27,6 +27,7 @@ pub enum ClientCommand {
GetTxLimit,
SetTxLimit { limit: u8 },
SetAprsDecodeEnabled { enabled: bool },
SetHfAprsDecodeEnabled { enabled: bool },
SetCwDecodeEnabled { enabled: bool },
SetCwAuto { enabled: bool },
SetCwWpm { wpm: u32 },
@@ -34,6 +35,7 @@ pub enum ClientCommand {
SetFt8DecodeEnabled { enabled: bool },
SetWsprDecodeEnabled { enabled: bool },
ResetAprsDecoder,
ResetHfAprsDecoder,
ResetCwDecoder,
ResetFt8Decoder,
ResetWsprDecoder,