From fca376486ab14df48ebc52bf0fe6f57972657234 Mon Sep 17 00:00:00 2001 From: pablorevilla-meshtastic Date: Fri, 3 Apr 2026 11:49:42 -0700 Subject: [PATCH] Add filter to firehose --- meshview/lang/en.json | 1 + meshview/lang/es.json | 1 + meshview/templates/firehose.html | 68 ++++++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/meshview/lang/en.json b/meshview/lang/en.json index 9a3a7e8..ccfb0c9 100644 --- a/meshview/lang/en.json +++ b/meshview/lang/en.json @@ -181,6 +181,7 @@ "from": "From", "to": "To", "channel": "Channel", + "all_channels": "All Channels", "port": "Port", "links": "Links", "unknown_app": "UNKNOWN APP", diff --git a/meshview/lang/es.json b/meshview/lang/es.json index fd27d02..dfe32d4 100644 --- a/meshview/lang/es.json +++ b/meshview/lang/es.json @@ -180,6 +180,7 @@ "from": "De", "to": "A", "channel": "Canal", + "all_channels": "Todos los canales", "port": "Puerto", "direct_to_mqtt": "Directo a MQTT", "all_broadcast": "Todos" diff --git a/meshview/templates/firehose.html b/meshview/templates/firehose.html index d775bc9..bc5266a 100644 --- a/meshview/templates/firehose.html +++ b/meshview/templates/firehose.html @@ -11,6 +11,12 @@ font-size: 0.9rem; border-radius: 6px; } +.firehose-controls { + gap: 12px; +} +.firehose-filter { + min-width: 220px; +} .port-tag { display: inline-block; @@ -89,15 +95,22 @@ {% block body %}
-
+

📡 Live Feed

- +
+ + + + +
@@ -241,6 +254,7 @@ function logPacketTimes(packet) { let lastImportTimeUs = null; let updatesPaused = false; let updateInterval = 3000; +let selectedChannel = ""; async function configureFirehose() { try { @@ -250,6 +264,36 @@ async function configureFirehose() { } catch {} } +async function loadChannels() { + try { + const res = await fetch("/api/channels"); + if (!res.ok) return; + + const data = await res.json(); + const select = document.getElementById("channel-filter"); + const channels = data.channels || []; + + for (const channel of channels) { + const option = document.createElement("option"); + option.value = channel; + option.textContent = channel; + select.appendChild(option); + } + } catch (err) { + console.error("Failed loading channels:", err); + } +} + +function resetFirehose() { + lastImportTimeUs = null; + document.getElementById("packet_list").innerHTML = ""; +} + +function matchesSelectedChannel(packet) { + if (!selectedChannel) return true; + return (packet.channel || "").toLowerCase() === selectedChannel.toLowerCase(); +} + async function fetchUpdates() { if (updatesPaused) return; @@ -270,6 +314,8 @@ async function fetchUpdates() { const list = document.getElementById("packet_list"); for (const pkt of packets.reverse()) { + if (!matchesSelectedChannel(pkt)) continue; + logPacketTimes(pkt); /* FROM — includes translation */ @@ -373,6 +419,7 @@ async function fetchUpdates() { document.addEventListener("DOMContentLoaded", async () => { const pauseBtn = document.getElementById("pause-button"); + const channelFilter = document.getElementById("channel-filter"); pauseBtn.addEventListener("click", () => { updatesPaused = !updatesPaused; @@ -383,6 +430,12 @@ document.addEventListener("DOMContentLoaded", async () => { : (firehoseTranslations.pause || "Pause"); }); + channelFilter.addEventListener("change", async (e) => { + selectedChannel = e.target.value; + resetFirehose(); + await fetchUpdates(); + }); + document.addEventListener("click", e => { const btn = e.target.closest(".toggle-btn"); if (!btn) return; @@ -397,6 +450,7 @@ document.addEventListener("DOMContentLoaded", async () => { await loadTranslationsFirehose(); await configureFirehose(); await loadNodes(); + await loadChannels(); fetchUpdates(); setInterval(fetchUpdates, updateInterval);