Documentation cleanup pass across the tree, driven by the upcoming merge of the dmrd-translation branch to main. Deletions (obsolete / superseded): - docs/user_csv_automation_proposal.md — implemented as dashboard/user_db.py - docs/QUICK_TEST_REFERENCE.md — stale test counts, referenced a TEST_COVERAGE.md that no longer exists - user.old.csv — development backup artifact (also added user.old* and user.bak* to .gitignore) Release notes renumbered to the 4.x series (file kept 1.x-labelled from a prior numbering scheme that predated the 4.1.0 release): - docs/RELEASE_NOTES_v1.5.md -> docs/RELEASE_NOTES_v4.5.md - docs/RELEASE_NOTES_v1.6.1.md -> docs/RELEASE_NOTES_v4.6.1.md - Also fixed a stray "v1.5+" -> "v4.5+" in stream_tracking_diagrams.md Content fixes where docs contradicted code or were stale: - docs/dmrd_translation.md: replaced the "Payload blanking" section with "Link Control rewriting" describing VHEAD/VTERM full-LC and voice-burst EMB_LC re-encoding via dmr_utils3.bptc - docs/connecting_to_hblink4.md: cross-reference updated to match - docs/protocol.md: corrected call-type bit direction (0=Group, 1=Private/Unit — previously reversed), replaced "Bits 0-3: Reserved" with actual dtype_vseq semantics, updated translation-doc link - readme.md: "Built on Twisted" -> asyncio (Twisted was removed in the outbound-connection release); expanded docs index to include routing, DMRD translation, diagrams, TODO, and OpenBridge analysis; added DMRD translation to the features list - docs/stream_tracking.md: StreamState snippet now shows lc_base and lc_cache fields added for LC rewriting - scripts/README.md: noted that dashboard/user_db.py is the primary refresh path; script remains as manual fallback - dashboard/user_db.py: dropped the doctring reference to the deleted proposal file Note: dmrd-translation branch remains in active development but is fully functional as of this commit. Tests: 75/75 pass (pre-existing test_access_control.py failures are unrelated and predate this branch). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HBlink4 Web Dashboard
Real-time monitoring dashboard for HBlink4 DMR server with modern look and feel.
Features
- Real-time Updates: WebSocket-based live updates every second (no page refreshes required)
- Repeater Monitoring: See all connected repeaters with their configurations and connection health
- Active Streams: Monitor ongoing DMR transmissions in real-time with duration counters
- Last Heard Tracking: View the 10 most recent users with alias display
- 10-minute user cache with configurable timeout
- View full cache (up to 50 users) in modal dialog
- Shows radio ID, callsign/alias, repeater, slot, talkgroup, and time
- On-Air Event Log: Track stream starts and ends for user-focused activity monitoring
- Connection Monitoring: Visual warnings for repeaters with missed keepalives
- Statistics: View total streams, packets, and activity metrics
- Clean Design: Dark theme with responsive layout that works on desktop and mobile
- Configurable Branding: Customize server name and dashboard title
- Network Info Button: Optional button linking to network information page
Configuration
The dashboard uses two configuration files:
- HBlink4 config (
config/config.json) - Controls event sending - Dashboard config (
dashboard/config.json) - Controls dashboard behavior and event receiving
Both configs must use the same transport settings (Unix socket for local, TCP for remote).
For complete configuration details, see the Configuration Guide. "port": 8765
The config file is created automatically with defaults on first run. Edit `dashboard/config.json` and restart the dashboard to apply changes.
### Announcement Banner
Display an optional announcement banner at the top of the dashboard to communicate important messages to users:
```json
{
"announcement": {
"enabled": true,
"text": "Welcome to the network! Please review the talkgroup list before transmitting."
}
}
Configuration Options:
enabled: Set totrueto show the banner,falseto hide ittext: The message to display in the banner
The banner appears as an eye-catching orange gradient banner at the top of the page, perfect for:
- Welcome messages
- Network announcements
- Maintenance notices
- Operational reminders
- Important policy updates
The banner only displays when both enabled is true and text contains content.
Network Info Button
Add an optional "Network Info" button to the dashboard header that links users to your network's information page:
{
"network_info": {
"enabled": true,
"button_text": "Network Info",
"url": "https://your-network-site.com/info"
}
}
Configuration Options:
enabled: Set totrueto show the button,falseto hide itbutton_text: Custom text for the button (e.g., "Network Info", "TG List", "Help")url: Target URL that opens in a new tab when clicked
The button appears as the first item in the header status area with a light blue color to distinguish it from system status indicators. Perfect for linking to talkgroup lists, network rules, connection information, or help pages.
Usage
The dashboard is started automatically with ./run_all.sh or can be started separately with python3 run_dashboard.py. Access at http://localhost:8080 (or your server IP for remote access).
Dashboard Components
Statistics Cards
Top row displays key metrics:
- Connections: Total connections (inbound repeaters/hotspots/network + connected outbound)
- Active Streams: Number of streams currently in progress (RX and TX)
- Total Calls Today: Number of calls received from repeaters today (RX only)
- Retransmitted Calls Today: Number of calls forwarded to other repeaters today (TX)
- Total Traffic Today: Duration of received traffic today (RX only)
Last Heard Table
Shows the 10 most recent users:
- Radio ID
- Callsign/Alias (or "-" if not available)
- Repeater ID
- Slot (1 or 2)
- Talkgroup
- Time (e.g., "2 minutes ago")
Click "View Full Cache" to see up to 50 users with cache statistics.
Active Streams
Real-time view of ongoing transmissions:
- Stream ID
- Radio ID
- Repeater ID
- Slot and Talkgroup
- Duration counter (updates every second)
- Packet count
Connected Repeaters
Connections are automatically categorized by device type:
- 📶 Repeaters - Full duplex repeaters and club sites (generic MMDVM, MMDVM_Unknown)
- 📱 Hotspots - Personal hotspots (MMDVM_HS boards, Pi-Star, WPSD, DMO/simplex)
- 🔗 Network Inbound - Servers connecting to us (HBlink, FreeDMR)
- ❓ Other - Unrecognized connection types
Each category shows:
- Repeater ID and callsign
- IP address
- Connected duration
- Last keepalive time
- Configuration (mode, slots, colorcode)
- Warning indicator if keepalives are being missed
Click any connection card to view detailed information including:
- Software ID and Package ID (for troubleshooting detection)
- Connection Type (repeater, hotspot, network, unknown)
- Location, frequencies, and access control settings
Detection is based on the package_id field from MMDVM/Pi-Star/WPSD configuration, with fallback to software_id. Customize detection patterns in config/config.json under connection_type_detection. See the Configuration Guide for details.
Recent Events
User-focused activity log showing:
- Stream starts (user keyed up)
- Stream ends (user unkeyed)
- Excludes system events like keepalives and cache updates
API Endpoints
The dashboard provides REST API endpoints:
GET /api/config
Returns dashboard configuration
GET /api/repeaters
Returns list of all connected repeaters
GET /api/streams
Returns list of active and recently ended streams
GET /api/events?limit=50
Returns recent events (default limit: 100)
GET /api/stats
Returns aggregate statistics
WebSocket /ws
Real-time updates via WebSocket
Troubleshooting
Dashboard shows "Disconnected"
- Check if HBlink4 is running
- Verify WebSocket connection in browser console
No events appearing
- Verify HBlink4 is running and repeaters are connected
- Check browser console for errors
WebSocket connection fails
- Verify uvicorn is running with WebSocket support
- Try a different browser
License
Same as HBlink4: GNU GPLv3