From 72465d14b30097f7c4eca7a8dd03b29b18445923 Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sat, 21 Mar 2026 15:58:20 +0100 Subject: [PATCH] [fix](trx-frontend-http): reset decoder state and virtual channels on rig switch Broadcast virtual channel list for newly selected rig from select_rig so SSE clients receive correct channels immediately. Detect rig changes in render() and reset stale decoder state (RDS, spectrum, decoder status indicators) from the previous rig. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stan Grams --- .../trx-frontend-http/assets/web/app.js | 30 +++++++++++++++++++ .../trx-frontend/trx-frontend-http/src/api.rs | 8 +++++ 2 files changed, 38 insertions(+) diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js index 1ef0f52..261ffe1 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js @@ -1608,6 +1608,32 @@ function resetRdsDisplay() { updateRdsPsOverlay(primaryRds); } +function resetDecoderStateOnRigSwitch() { + // RDS + primaryRds = null; + vchanRdsById = new Map(); + resetRdsDisplay(); + resetWfmStereoIndicator(); + + // Spectrum — clear stale data from previous rig's SDR + lastSpectrumData = null; + window.lastSpectrumData = null; + lastSpectrumRenderData = null; + + // Decoder status indicators + const decoderIds = ["ais-status", "vdes-status", "aprs-status", "cw-status", "ft8-status", "wspr-status"]; + decoderIds.forEach((id) => { + const el = document.getElementById(id); + if (el) el.textContent = "--"; + }); + + // FT8/FT4/WSPR history tables + if (typeof window.ft8ClearHistory === "function") window.ft8ClearHistory(); + if (typeof window.ft4ClearHistory === "function") window.ft4ClearHistory(); + if (typeof window.ft2ClearHistory === "function") window.ft2ClearHistory(); + if (typeof window.wsprClearHistory === "function") window.wsprClearHistory(); +} + function resetWfmStereoIndicator() { if (!wfmStFlagEl) return; wfmStFlagEl.textContent = "MO"; @@ -2701,6 +2727,10 @@ function render(update) { `trx-server hosted by ${safeCallsign}`; } } + // Detect rig switch and reset stale decoder state from the previous rig. + if (typeof update.active_rig_id === "string" && update.active_rig_id.length > 0 && update.active_rig_id !== lastActiveRigId) { + resetDecoderStateOnRigSwitch(); + } updateRigSubtitle(update.active_rig_id); if (ownerSubtitle) { if (ownerCallsign) { diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs index 63b6e6a..3eb7651 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs +++ b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs @@ -1379,6 +1379,7 @@ pub struct SelectRigQuery { pub async fn select_rig( query: web::Query, context: web::Data>, + vchan_mgr: web::Data>, ) -> Result { let rig_id = query.rig_id.trim(); if rig_id.is_empty() { @@ -1403,6 +1404,13 @@ pub async fn select_rig( *active = Some(rig_id.to_string()); } + // Broadcast the channel list for the newly selected rig so all SSE + // clients receive the correct virtual channels immediately. + let chans = vchan_mgr.channels(rig_id); + if let Ok(json) = serde_json::to_string(&chans) { + let _ = vchan_mgr.change_tx.send(format!("{rig_id}:{json}")); + } + Ok(HttpResponse::Ok().json(build_rig_list_payload(context.get_ref().as_ref()))) }