[fix](trx-rs): limit aprs live bar to one hour

Attach replay timestamps to APRS history and filter the APRS live bar
so it only shows the last hour of valid entries.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-01 18:08:38 +01:00
parent 63fd35802e
commit 5899592b6c
5 changed files with 30 additions and 5 deletions
@@ -4,6 +4,7 @@ const aprsPacketsEl = document.getElementById("aprs-packets");
const aprsFilterInput = document.getElementById("aprs-filter");
const aprsBarOverlay = document.getElementById("aprs-bar-overlay");
const APRS_MAX_PACKETS = 100;
const APRS_BAR_WINDOW_MS = 60 * 60 * 1000;
let aprsFilterText = "";
let aprsPacketHistory = [];
@@ -105,7 +106,8 @@ function applyAprsFilterToAll() {
function updateAprsBar() {
if (!aprsBarOverlay) return;
const isPkt = (document.getElementById("mode")?.value || "").toUpperCase() === "PKT";
const okFrames = aprsPacketHistory.filter((p) => p.crcOk);
const cutoffMs = Date.now() - APRS_BAR_WINDOW_MS;
const okFrames = aprsPacketHistory.filter((p) => p.crcOk && p._tsMs >= cutoffMs);
if (!isPkt || okFrames.length === 0) {
aprsBarOverlay.style.display = "none";
return;
@@ -143,8 +145,9 @@ function addAprsPacket(pkt) {
console.log(tag, `${pkt.srcCall}>${pkt.destCall}${pkt.path ? "," + pkt.path : ""}: ${pkt.info}`, pkt);
// Stamp timestamp for persistence
pkt._ts = new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
pkt._tsMs = Date.now();
const tsMs = Number.isFinite(pkt.ts_ms) ? Number(pkt.ts_ms) : Date.now();
pkt._tsMs = tsMs;
pkt._ts = new Date(tsMs).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
aprsPacketHistory.unshift(pkt);
if (aprsPacketHistory.length > APRS_MAX_PACKETS) aprsPacketHistory.length = APRS_MAX_PACKETS;
@@ -12,7 +12,7 @@
use std::collections::VecDeque;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use actix_web::{get, web, Error, HttpRequest, HttpResponse};
use actix_ws::Message;
@@ -103,7 +103,14 @@ pub fn snapshot_aprs_history(context: &FrontendRuntimeContext) -> Vec<AprsPacket
.lock()
.expect("aprs history mutex poisoned");
prune_aprs_history(&mut history);
history.iter().map(|(_, pkt)| pkt.clone()).collect()
history
.iter()
.map(|(ts, pkt)| {
let mut pkt = pkt.clone();
pkt.ts_ms = Some(timestamp_ms_for_elapsed(ts.elapsed()));
pkt
})
.collect()
}
pub fn snapshot_cw_history(context: &FrontendRuntimeContext) -> Vec<CwEvent> {
@@ -141,6 +148,17 @@ pub fn clear_aprs_history(context: &FrontendRuntimeContext) {
history.clear();
}
fn timestamp_ms_for_elapsed(elapsed: Duration) -> i64 {
let wall_clock = SystemTime::now()
.checked_sub(elapsed)
.unwrap_or(UNIX_EPOCH);
let millis = wall_clock
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_millis();
i64::try_from(millis).unwrap_or(i64::MAX)
}
pub fn clear_cw_history(context: &FrontendRuntimeContext) {
let mut history = context
.cw_history