Add live waterfall during pager and sensor decoding via IQ pipeline

Replace rtl_fm/rtl_433 with rtl_sdr for raw IQ capture when available,
enabling a Python IQ processor to compute FFT for the waterfall while
simultaneously feeding decoded data to multimon-ng (pager) or rtl_433
(sensor). Falls back to the legacy pipeline when rtl_sdr is unavailable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-02-07 23:18:43 +00:00
parent b312eb20aa
commit f04ba7f143
9 changed files with 1053 additions and 434 deletions

View File

@@ -3589,7 +3589,8 @@ async function startWaterfall(options = {}) {
lastWaterfallDraw = 0;
initWaterfallCanvas();
connectWaterfallSSE();
if (typeof reserveDevice === 'function') {
// Only reserve device if not decoder-driven (decoder already owns the device)
if (data.source !== 'decoder' && typeof reserveDevice === 'function') {
reserveDevice(parseInt(device), 'waterfall');
}
if (resume || resumeRfWaterfallAfterListening) {
@@ -3618,11 +3619,14 @@ async function stopWaterfall() {
}
try {
await fetch('/listening/waterfall/stop', { method: 'POST' });
const resp = await fetch('/listening/waterfall/stop', { method: 'POST' });
let stopData = {};
try { stopData = await resp.json(); } catch (e) {}
isWaterfallRunning = false;
if (waterfallEventSource) { waterfallEventSource.close(); waterfallEventSource = null; }
setWaterfallControlButtons(false);
if (typeof releaseDevice === 'function') {
// Only release device if it was a standalone waterfall (not decoder-driven)
if (stopData.source !== 'decoder' && typeof releaseDevice === 'function') {
releaseDevice('waterfall');
}
} catch (err) {