From fc8e63bdf7afa428314ae8bc9e5c78f2a7bb58a4 Mon Sep 17 00:00:00 2001 From: Pablo Revilla Date: Wed, 6 Aug 2025 16:16:28 -0700 Subject: [PATCH] add API code for /api/packets --- meshview/templates/firehose.html | 31 ++++++++++++++++--------------- meshview/web.py | 29 +++++++++++------------------ 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/meshview/templates/firehose.html b/meshview/templates/firehose.html index 81c3c7d..72c8120 100644 --- a/meshview/templates/firehose.html +++ b/meshview/templates/firehose.html @@ -6,6 +6,8 @@ margin: 0 auto; } + /* Removed .packet-fade-in animation CSS */ + /* .packet-fade-in { animation: fadeIn 0.5s ease forwards; opacity: 0; @@ -16,6 +18,7 @@ opacity: 1; } } + */ #pause-button { white-space: nowrap; @@ -66,18 +69,12 @@ function fetchUpdates() { .then(res => res.json()) .then(data => { if (data.packets && data.packets.length > 0) { - lastTime = data.latest_import_time; + lastTime = data.last_time; const list = document.getElementById("packet_list"); for (const html of data.packets.reverse()) { list.insertAdjacentHTML("afterbegin", html); - const firstChild = list.firstElementChild; - if (firstChild) { - firstChild.classList.add("packet-fade-in"); - firstChild.addEventListener("animationend", () => { - firstChild.classList.remove("packet-fade-in"); - }, { once: true }); - } + // No animation here anymore } } }) @@ -89,12 +86,16 @@ function fetchUpdates() { document.addEventListener("DOMContentLoaded", () => { const pauseBtn = document.getElementById("pause-button"); - document.querySelector('select[name="portnum"]').addEventListener("change", (e) => { - const selected = e.target.value; - const url = new URL(window.location.href); - url.searchParams.set("portnum", selected); - window.location.href = url; - }); + // Assuming you have a portnum selector somewhere (not shown in your snippet) + const portnumSelector = document.querySelector('select[name="portnum"]'); + if (portnumSelector) { + portnumSelector.addEventListener("change", (e) => { + const selected = e.target.value; + const url = new URL(window.location.href); + url.searchParams.set("portnum", selected); + window.location.href = url; + }); + } pauseBtn.addEventListener("click", () => { updatesPaused = !updatesPaused; @@ -103,7 +104,7 @@ document.addEventListener("DOMContentLoaded", () => { // Start fetching updates fetchUpdates(); - setInterval(fetchUpdates, 3000); + setInterval(fetchUpdates, 1000); }); diff --git a/meshview/web.py b/meshview/web.py index 3d77c74..e8ba381 100644 --- a/meshview/web.py +++ b/meshview/web.py @@ -399,39 +399,32 @@ async def packet_details(request): @routes.get("/firehose/updates") async def firehose_updates(request): try: - # Parse `last_time` from query - last_time_str = request.query.get("last_time", None) + # Get `last_time` from query string + last_time_str = request.query.get("last_time") + last_time = None if last_time_str: try: last_time = datetime.datetime.fromisoformat(last_time_str) - if last_time.tzinfo is None: - last_time = last_time.replace(tzinfo=datetime.timezone.utc) except Exception as e: print(f"Failed to parse last_time '{last_time_str}': {e}") last_time = None - else: - last_time = None + + # Query packets after last_time (microsecond precision) + packets = await store.get_packets(after=last_time, limit=10) - # Query packets using `after=last_time` - packets = await store.get_packets( - after=last_time, - limit=10, - ) + # Convert to UI model ui_packets = [Packet.from_model(p) for p in packets] - # Render HTML using Jinja2 + # Render HTML using Jinja2 template template = env.get_template("packet.html") rendered_packets = [template.render(packet=p) for p in ui_packets] - # Prepare response - response = { - "packets": rendered_packets, - } - + # Build response + response = {"packets": rendered_packets} if ui_packets: latest_import_time = max(p.import_time for p in ui_packets) - response["latest_import_time"] = latest_import_time.isoformat(timespec="seconds") + response["last_time"] = latest_import_time.isoformat() return web.json_response(response)