// --- WSPR Decoder Plugin (server-side decode) ---
const wsprStatus = document.getElementById("wspr-status");
const wsprMessagesEl = document.getElementById("wspr-messages");
const WSPR_MAX_MESSAGES = 200;
function fmtWsprTime(tsMs) {
if (!tsMs) return "--:--:--";
return new Date(tsMs).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
}
function renderWsprRow(msg) {
const row = document.createElement("div");
row.className = "ft8-row";
const snr = Number.isFinite(msg.snr_db) ? msg.snr_db.toFixed(1) : "--";
const dt = Number.isFinite(msg.dt_s) ? msg.dt_s.toFixed(2) : "--";
const baseHz = Number.isFinite(window.ft8BaseHz) ? window.ft8BaseHz : null;
const rfHz = Number.isFinite(msg.freq_hz) && Number.isFinite(baseHz) ? (baseHz + msg.freq_hz) : null;
const freq = Number.isFinite(rfHz) ? rfHz.toFixed(0) : "--";
const message = (msg.message || "").toString();
row.innerHTML = `${fmtWsprTime(msg.ts_ms)}${snr}${dt}${freq}${escapeWsprHtml(message)}`;
return row;
}
function addWsprMessage(msg) {
wsprMessagesEl.prepend(renderWsprRow(msg));
while (wsprMessagesEl.children.length > WSPR_MAX_MESSAGES) {
wsprMessagesEl.removeChild(wsprMessagesEl.lastChild);
}
}
function escapeWsprHtml(input) {
return input
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll("\"", """);
}
document.getElementById("wspr-decode-toggle-btn").addEventListener("click", async () => {
try { await postPath("/toggle_wspr_decode"); } catch (e) { console.error("WSPR toggle failed", e); }
});
document.getElementById("wspr-clear-btn").addEventListener("click", async () => {
wsprMessagesEl.innerHTML = "";
try { await postPath("/clear_wspr_decode"); } catch (e) { console.error("WSPR clear failed", e); }
});
window.onServerWspr = function(msg) {
wsprStatus.textContent = "Receiving";
addWsprMessage({
ts_ms: msg.ts_ms,
snr_db: msg.snr_db,
dt_s: msg.dt_s,
freq_hz: msg.freq_hz,
message: msg.message,
});
};