KS-DMR*.png are the operator's own branding (referenced by the gitignored dashboard/config.py LOGO_FILE), not project assets -- they were swept in by a `git add -A` in the previous commit. Untrack them and gitignore dashboard/*.png so they stay local. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
HBlink3 Dashboard
A real-time web dashboard for HBlink3, in the spirit of the old HBmonitor (same tables and information) but with a modern dark UI and a far more efficient data path. It is a separate program from the HBlink3 core.
It connects to HBlink3's reporting feed, keeps the display state, and pushes live JSON deltas to the browser over a WebSocket. The browser renders the tables and ticks the duration/uptime counters itself — no full-page or full-table refreshes, and no pickle on the wire.
What it shows
- Last Heard — the most-recent unique callers (user, call type, source repeater, timeslot, talkgroup, and when), derived live from the call log. The table is collapsible; its open/closed state is remembered in your browser.
- Server Systems — each server and its connected repeaters (ID, callsign, location, IP, uptime, frequency, colorcode, slots) with the live call on each timeslot (source → destination, color-coded by direction). Each server's connection list can be collapsed with the Show/Hide Connections button; when collapsed, system-level TS1/TS2 activity pills replace the table so you still see what's talking. State is remembered per-browser.
- Outbound Systems — outbound connections with health (connection state, pings sent/ackd/lost) and live per-timeslot calls.
- OpenBridge Systems — network ID, target, and active streams.
- Conference Bridges — each bridge's members: timeslot, talkgroup, connected/disconnected state, timeout countdown, and on/off trigger talkgroups.
- Call Log — a running log of call starts and ends.
For a field-by-field explanation of everything on the screen, see FIELDS.md.
Install
cd dashboard
python3 -m venv venv && source venv/bin/activate # or reuse the HBlink3 venv
pip install -r requirements.txt
cp config_sample.py config.py # then edit config.py
python server.py # or, from the repo root: python run_dashboard.py
Open http://<host>:8080.
Configuration (config.py)
HBLINK_IP/HBLINK_PORT— HBlink3's reporting feed (the[REPORTS]section ofhblink.cfg:REPORT_PORT, default 4321). Used whenHBLINK_TRANSPORTistcp.HBLINK_TRANSPORT/HBLINK_SOCKET— optional. SetHBLINK_TRANSPORT = 'unix'andHBLINK_SOCKETto the daemon'sREPORT_SOCKETpath to connect over a local Unix socket instead of TCP (same-box dashboard; immune to NIC flaps / conntrack eviction). Defaults totcp. Must match the daemon'sREPORT_TRANSPORT.WEB_HOST/WEB_PORT— where the dashboard listens.PATH/*_FILE— alias files mapping DMR IDs to callsigns/talkgroup names (the same files HBlink3 uses; pointPATHat HBlink3's directory to share them).REPORT_NAME,LOG_LINES— branding and call-log length.LAST_HEARD— default state of the Last Heard table:'open','closed', or'off'(omit it entirely). Users can still toggle it in their own browser.LAST_HEARD_COUNT— number of recent callers to list (default 10).SERVER_REPEATERS— default state of each server system's connection list:'open'or'closed'. Use'closed'for a compact view on many-repeater servers; per-system browser choices override it.
HBlink3 side
In hblink.cfg, under [REPORTS]:
REPORT: TrueREPORT_PORTmust match the dashboard'sHBLINK_PORTREPORT_CLIENTSmust include the dashboard host's IP (or*)REPORT_INTERVALsets how often the full systems/bridge snapshot is resent as a slow resync. Live calls and repeater connect/disconnect are pushed as they happen (granular events); the periodic snapshot is just a safety-net resync and also carries the per-repeater ping-quality figures, so a larger value like60is fine.
Notes
- This replaces the old HBmonitor. HBlink3's reporting feed is now newline-delimited JSON, which HBmonitor does not understand.
- The dashboard depends on FastAPI + Uvicorn; the HBlink3 core itself remains stdlib-only.
- Demo mode — append
?demoto the dashboard URL (e.g.http://localhost:8080/?demo) to load a static pre-populated scenario showing all visual elements: a SERVER with three repeaters, an OUTBOUND peer, an OpenBridge connection, active calls bridged coherently across systems, a slot in group-hangtime, and a populated call log. No HBlink3 connection is required. This is useful for understanding what the dashboard looks like under normal operating conditions before any traffic has been seen.