Repository navigation
Closed
Description
Context
#481 (the port of upstream 2208) added a rolling 1-hour airtime share per observer. GET /api/observers/metrics/summary already returns both tx_airtime_pct_1h and rx_airtime_pct_1h. The UI shows only TX 1h: in the observer list and on the RF Health tiles.
On meshview.dk, 2026-10-16, 58 of 59 observers had an RX 1h value, with a median of 3.7% and a maximum of 17.5%.
Meaning
- TX 1h is the share of the last hour the observer's own radio spent transmitting. It is regulated, and the EU g3 limit is 10%, so it keeps the existing duty-cycle warning.
- RX 1h is the share of the last hour the radio spent receiving packets. It measures how busy the channel is at that observer. It is not regulated, so it gets no warning colour. A high value shows a dense or congested area.
Work
- Observer list. Add a sortable numeric "RX 1h" column next to "TX 1h", using the same shared helper module (
public/observer-airtime.js). Do not add a warning style. A missing value shows—. - RF Health tiles. Show "RX 1h: x%" next to "TX 1h". The stats row must still wrap between items on narrow tiles, as Port upstream 2208: 1 h TX airtime + duty-cycle warning #481 fixed.
- Observer detail page (
public/observer-detail.js,#/observers/{id}). Show TX 1h (with the duty-cycle warning at or aboveduty_cycle_warn_pct, same style as the list) and RX 1h (neutral) in the stats area.- Reuse data the page already loads. If neither value is available there, do one summary request with the existing client TTL cache, or extend the existing per-observer detail response with a named Go struct field. Do not add per-item calls or new
map[string]interface{}. - Verify the actual response shapes first (AGENTS.md rule 4).
- Reuse data the page already loads. If neither value is available there, do one summary request with the existing client TTL cache, or extend the existing per-observer detail response with a named Go struct field. Do not add per-item calls or new
- Tooltips. TX: "Share of the last hour this observer transmitted; flagged at or above the duty-cycle limit." RX: "Share of the last hour this observer's radio was receiving packets — a measure of channel load at this location, not a limit." Keep them distinct from the existing per-sample
tx_airtime_pctin the RF Health charts.
Tests
- Unit tests for the helper: RX formatting, null and unknown values, and that RX never gets the warning class.
- Frontend tests for the list column (sorting,
—for null), the tile, and the detail page (TX warning at or above the threshold, RX neutral). - An E2E that serves a known summary through
page.route, astest-issue-661/Port upstream 2208: 1 h TX airtime + duty-cycle warning #481 does, and checks the column, sorting, tile and detail page. - Browser-check both themes at desktop width and 360×800.
Acceptance criteria
RX 1h is visible in the observer list, on the RF Health tiles and on the observer detail page. TX 1h is also on the detail page, with the existing warning semantics. No per-observer request loops.
Metadata
Metadata
Assignees
Labels
No labels
Activity
dborup commentedon Oct 16, 2026
Fixed by #498 (merged as
c8d60b0a56bb70261c5c7be6cd8779a0c06abe35).Fixed by #498: RX 1h (channel load, neutral) next to TX 1h in the observer list and RF Health, and TX/RX 1h cards on the observer detail page, filled without blocking the page render (APPROVE after round 2, CI green).