[feat](trx-frontend-http): add RDS debug panel in Plugins tab
Add an RDS sub-tab to the Plugins panel showing PI code, PS name, PTY number and name, decoder status, and a raw JSON dump of the latest RDS data received via SSE. Also list the RDS decoder in the Overview tab. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -3103,14 +3103,44 @@ function clearSpectrumCanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateRdsPsOverlay(rds) {
|
function updateRdsPsOverlay(rds) {
|
||||||
if (!rdsPsOverlay) return;
|
// Overview strip overlay
|
||||||
const ps = rds?.program_service?.trim();
|
if (rdsPsOverlay) {
|
||||||
if (ps) {
|
const ps = rds?.program_service?.trim();
|
||||||
rdsPsOverlay.textContent = ps;
|
if (ps) {
|
||||||
rdsPsOverlay.style.display = "";
|
rdsPsOverlay.textContent = ps;
|
||||||
} else {
|
rdsPsOverlay.style.display = "";
|
||||||
rdsPsOverlay.style.display = "none";
|
} else {
|
||||||
|
rdsPsOverlay.style.display = "none";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RDS debug panel
|
||||||
|
const statusEl = document.getElementById("rds-status");
|
||||||
|
const piEl = document.getElementById("rds-pi");
|
||||||
|
const psEl = document.getElementById("rds-ps");
|
||||||
|
const ptyEl = document.getElementById("rds-pty");
|
||||||
|
const ptyNameEl = document.getElementById("rds-pty-name");
|
||||||
|
const rawEl = document.getElementById("rds-raw");
|
||||||
|
if (!statusEl) return;
|
||||||
|
|
||||||
|
if (!rds) {
|
||||||
|
statusEl.textContent = "No signal";
|
||||||
|
statusEl.className = "rds-value rds-no-signal";
|
||||||
|
piEl.textContent = "--";
|
||||||
|
psEl.textContent = "--";
|
||||||
|
ptyEl.textContent = "--";
|
||||||
|
ptyNameEl.textContent = "--";
|
||||||
|
rawEl.textContent = "--";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusEl.textContent = "Decoding";
|
||||||
|
statusEl.className = "rds-value rds-decoding";
|
||||||
|
piEl.textContent = rds.pi != null ? `0x${rds.pi.toString(16).toUpperCase().padStart(4, "0")}` : "--";
|
||||||
|
psEl.textContent = rds.program_service ?? "--";
|
||||||
|
ptyEl.textContent = rds.pty != null ? String(rds.pty) : "--";
|
||||||
|
ptyNameEl.textContent = rds.pty_name ?? "--";
|
||||||
|
rawEl.textContent = JSON.stringify(rds, null, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function scheduleSpectrumDraw() {
|
function scheduleSpectrumDraw() {
|
||||||
|
|||||||
@@ -236,6 +236,7 @@
|
|||||||
<button class="sub-tab" data-subtab="cw">CW</button>
|
<button class="sub-tab" data-subtab="cw">CW</button>
|
||||||
<button class="sub-tab" data-subtab="ft8">FT8</button>
|
<button class="sub-tab" data-subtab="ft8">FT8</button>
|
||||||
<button class="sub-tab" data-subtab="wspr">WSPR</button>
|
<button class="sub-tab" data-subtab="wspr">WSPR</button>
|
||||||
|
<button class="sub-tab" data-subtab="rds">RDS</button>
|
||||||
<button class="sub-tab" data-subtab="map">Map</button>
|
<button class="sub-tab" data-subtab="map">Map</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="subtab-overview" class="sub-tab-panel">
|
<div id="subtab-overview" class="sub-tab-panel">
|
||||||
@@ -263,6 +264,23 @@
|
|||||||
Decodes WSPR messages from RX audio (DIG/USB only, toggle required).
|
Decodes WSPR messages from RX audio (DIG/USB only, toggle required).
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="plugin-item">
|
||||||
|
<strong>RDS Decoder</strong>
|
||||||
|
<div style="color:var(--text-muted); font-size:0.85rem; margin-top:0.2rem;">
|
||||||
|
Decodes Radio Data System (RDS) metadata from WFM broadcasts (57 kHz subcarrier).
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="subtab-rds" class="sub-tab-panel" style="display:none;">
|
||||||
|
<div class="rds-grid">
|
||||||
|
<div class="rds-field"><span class="rds-label">Status</span><span id="rds-status" class="rds-value rds-no-signal">No signal</span></div>
|
||||||
|
<div class="rds-field"><span class="rds-label">PI</span><span id="rds-pi" class="rds-value">--</span></div>
|
||||||
|
<div class="rds-field"><span class="rds-label">PS</span><span id="rds-ps" class="rds-value rds-ps">--</span></div>
|
||||||
|
<div class="rds-field"><span class="rds-label">PTY</span><span id="rds-pty" class="rds-value">--</span></div>
|
||||||
|
<div class="rds-field"><span class="rds-label">PTY Name</span><span id="rds-pty-name" class="rds-value">--</span></div>
|
||||||
|
</div>
|
||||||
|
<div class="rds-raw-label">Raw JSON</div>
|
||||||
|
<pre id="rds-raw" class="rds-raw">--</pre>
|
||||||
</div>
|
</div>
|
||||||
<div id="subtab-map" class="sub-tab-panel" style="display:none;">
|
<div id="subtab-map" class="sub-tab-panel" style="display:none;">
|
||||||
<div class="map-controls">
|
<div class="map-controls">
|
||||||
|
|||||||
@@ -729,6 +729,16 @@ small { color: var(--text-muted); }
|
|||||||
}
|
}
|
||||||
.map-controls input[type="checkbox"] { margin-right: 0.3rem; }
|
.map-controls input[type="checkbox"] { margin-right: 0.3rem; }
|
||||||
|
|
||||||
|
.rds-grid { display: grid; grid-template-columns: auto 1fr; gap: 0.4rem 1rem; align-items: baseline; margin-bottom: 1rem; }
|
||||||
|
.rds-field { display: contents; }
|
||||||
|
.rds-label { color: var(--text-muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em; white-space: nowrap; }
|
||||||
|
.rds-value { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 0.95rem; color: var(--text); }
|
||||||
|
.rds-ps { font-size: 1.1rem; font-weight: 600; letter-spacing: 0.08em; color: var(--accent-green); }
|
||||||
|
.rds-no-signal { color: var(--text-muted); }
|
||||||
|
.rds-decoding { color: var(--accent-green); }
|
||||||
|
.rds-raw-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin-bottom: 0.3rem; }
|
||||||
|
.rds-raw { background: var(--input-bg); border: 1px solid var(--border-light); border-radius: 6px; padding: 0.5rem 0.6rem; font-size: 0.8rem; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; color: var(--text); white-space: pre; overflow-x: auto; margin: 0; }
|
||||||
|
|
||||||
.cw-controls { display: flex; gap: 0.6rem; align-items: center; margin-bottom: 0.75rem; }
|
.cw-controls { display: flex; gap: 0.6rem; align-items: center; margin-bottom: 0.75rem; }
|
||||||
.cw-config { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin-bottom: 0.75rem; }
|
.cw-config { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin-bottom: 0.75rem; }
|
||||||
.cw-config label { display: flex; flex-direction: column; gap: 0.2rem; color: var(--text-muted); font-size: 0.82rem; }
|
.cw-config label { display: flex; flex-direction: column; gap: 0.2rem; color: var(--text-muted); font-size: 0.82rem; }
|
||||||
|
|||||||
Reference in New Issue
Block a user