Major changes: - Comprehensive documentation audit completed - Config restructure: dashboard moved from global to top-level - Dual-stack IPv6: bind_ipv4/bind_ipv6 with port_ipv4/port_ipv6 - Dashboard transport: host_ipv4/host_ipv6 with disable_ipv6 flag - Fixed corrupted dashboard/server.py imports - Updated all documentation to match actual implementation - Removed duplication, established single source of truth Documentation updates: - docs/configuration.md: Complete overhaul with accurate field definitions - docs/dashboard_transport.md: Updated transport configuration guide - docs/integration.md: Dual-stack integration examples - dashboard/README.md: Clarified dashboard configuration requirements - DASHBOARD_INTEGRATION.md: Streamlined integration summary - All config examples now use correct field names Configuration changes: - dashboard section moved to top-level (not nested under global) - IPv6 settings: disable_ipv6 flag replaces ipv6 boolean - Separate bind addresses and ports for IPv4 and IPv6 - Dashboard uses host_ipv4/host_ipv6 instead of single host field Bug fixes: - Fixed syntax error in dashboard/server.py (corrupted imports) - All JSON configs validate successfully - All 39 tests passing See DOCUMENTATION_AUDIT.md for complete audit report.
14 KiB
HBlink4 Configuration Guide
HBlink4 uses a JSON configuration file to define server settings, repeater access control rules, and talkgroup definitions. This guide explains each configuration section and its options.
Configuration File Structure
The configuration file consists of five main sections:
- Global Settings - Server-wide settings
- Dashboard - Web dashboard and event communication
- Blacklist Rules - Access control for blocking repeaters
- Repeater Configurations - Per-repeater authentication and routing
- Talkgroup Definitions - Talkgroup names and bridging
Global Settings
The global section contains server-wide settings that control the basic operation of HBlink4.
{
"global": {
"max_missed": 3,
"timeout_duration": 30,
"disable_ipv6": false,
"bind_ipv4": "0.0.0.0",
"bind_ipv6": "::",
"port_ipv4": 62031,
"port_ipv6": 62031,
"logging": {
"file": "logs/hblink.log",
"console_level": "INFO",
"file_level": "DEBUG",
"retention_days": 30
},
"stream_timeout": 2.0,
"stream_hang_time": 10.0,
"user_cache": {
"timeout": 600
}
}
}
| Setting | Type | Description |
|---|---|---|
max_missed |
number | Maximum consecutive missed pings before disconnecting a repeater (default: 3) |
timeout_duration |
number | Seconds between expected pings from repeaters (default: 30) |
disable_ipv6 |
boolean | Disable IPv6 globally - use only if your network has broken IPv6 routing (default: false) |
bind_ipv4 |
string | IPv4 address to bind ("0.0.0.0" for all IPv4 interfaces) |
bind_ipv6 |
string | IPv6 address to bind ("::" for all IPv6 interfaces) |
port_ipv4 |
number | UDP port for IPv4 (default: 62031) |
port_ipv6 |
number | UDP port for IPv6 (default: 62031) |
logging.file |
string | Path to log file |
logging.console_level |
string | Logging level for console output ("DEBUG", "INFO", "WARNING", "ERROR") |
logging.file_level |
string | Logging level for file output ("DEBUG", "INFO", "WARNING", "ERROR") |
logging.retention_days |
number | Number of days to retain log files (default: 30) |
stream_timeout |
float | Fallback timeout when terminator frame is lost (default: 2.0 seconds) |
stream_hang_time |
float | Seconds to reserve slot for same source after stream ends (default: 10.0-20.0 seconds) |
user_cache.timeout |
number | Seconds before user cache entries expire (default: 600, minimum: 60) |
Note on IPv6: HBlink4 is dual-stack native and will bind to both IPv4 and IPv6 by default. If your network appears to support IPv6 but connections don't establish properly (a common issue with misconfigured IPv6), set disable_ipv6: true to force IPv4-only mode.
User Cache: The user cache tracks the last known repeater for each DMR ID to enable efficient private call routing. Entries are automatically cleaned up every 60 seconds. The timeout must be at least 60 seconds.
Dual-Stack IPv6 Support
HBlink4 is dual-stack native and can listen on both IPv4 and IPv6 simultaneously:
- Set
bind_ipv4to"0.0.0.0"to listen on all IPv4 interfaces - Set
bind_ipv6to"::"to listen on all IPv6 interfaces - Both can be active simultaneously for maximum compatibility
- Specific addresses can be used instead of wildcards (e.g.,
"192.168.1.10"or"2001:db8::1") - Use
disable_ipv6: trueto force IPv4-only mode if IPv6 is broken on your network
Example configurations:
// Dual-stack (both IPv4 and IPv6) - RECOMMENDED
"bind_ipv4": "0.0.0.0",
"bind_ipv6": "::",
"port_ipv4": 62031,
"port_ipv6": 62031,
// IPv4 only
"disable_ipv6": true,
"bind_ipv4": "0.0.0.0",
"port_ipv4": 62031,
// Specific addresses
"bind_ipv4": "192.168.1.10",
"bind_ipv6": "2001:db8::1",
"port_ipv4": 62031,
"port_ipv6": 62031
Dashboard Configuration
The dashboard section is a top-level configuration (not nested under global) and controls the real-time monitoring dashboard and event communication:
{
"dashboard": {
"enabled": true,
"disable_ipv6": false,
"transport": "unix",
"host_ipv4": "127.0.0.1",
"host_ipv6": "::1",
"port": 8765,
"unix_socket": "/tmp/hblink4.sock",
"buffer_size": 65536
}
}
| Setting | Type | Description |
|---|---|---|
enabled |
boolean | Enable/disable dashboard event emitting |
disable_ipv6 |
boolean | Disable IPv6 for dashboard (independent of global setting) |
transport |
string | Transport type: "unix" or "tcp" (see below) |
host_ipv4 |
string | IPv4 address for TCP transport (e.g., "127.0.0.1") |
host_ipv6 |
string | IPv6 address for TCP transport (e.g., "::1") |
port |
number | Port number for TCP transport (default: 8765) |
unix_socket |
string | Unix socket path for Unix transport (default: "/tmp/hblink4.sock") |
buffer_size |
number | Socket send buffer size (default: 65536) |
Transport Options
Unix Socket ("unix") - Recommended for local dashboard:
- ✅ Fastest performance (~0.5-1μs per event)
- ✅ Same-host only (most secure)
- ✅ Automatic cleanup on startup
- ✅ File permissions control access
- Use when: Dashboard runs on same server as HBlink4
- Configuration: Only
unix_socketpath is used (host and port fields ignored)
TCP ("tcp") - Required for remote dashboard:
- ✅ Remote dashboard capability
- ✅ Dual-stack IPv4/IPv6 support
- ⚠️ Network exposed (use firewall rules)
- Use when: Dashboard runs on different server
- Configuration: Uses
host_ipv4,host_ipv6, andport(unix_socket field ignored) - IPv6 detection: Automatic based on address format
Dashboard Configuration Examples
Local dashboard (Unix socket - recommended):
"dashboard": {
"enabled": true,
"transport": "unix",
"unix_socket": "/tmp/hblink4.sock"
}
Local dashboard (TCP - if Unix sockets unavailable):
"dashboard": {
"enabled": true,
"transport": "tcp",
"host_ipv4": "127.0.0.1",
"host_ipv6": "::1",
"port": 8765
}
Remote dashboard (TCP):
"dashboard": {
"enabled": true,
"transport": "tcp",
"host_ipv4": "192.168.1.100", // Dashboard server IP
"host_ipv6": "2001:db8::100", // Dashboard server IPv6 (optional)
"port": 8765
}
Disable IPv6 for dashboard only:
"dashboard": {
"enabled": true,
"disable_ipv6": true, // Use IPv4 only
"transport": "tcp",
"host_ipv4": "127.0.0.1",
"port": 8765
}
Important: Both HBlink4 config (config/config.json) and dashboard config (dashboard/config.json) must use the same transport type and connection details. See Dashboard Documentation for dashboard-side configuration.
Stream Management
The stream_timeout and stream_hang_time settings control two different aspects of DMR transmission management:
-
stream_timeout: Fallback cleanup timeout (default: 2.0 seconds). This is used only when a DMR terminator frame is lost or not received. Under normal operation, streams end immediately when a terminator frame is detected (~60ms). This timeout ensures slot cleanup even if the terminator packet is dropped. Recommended: 2.0 seconds to handle worst-case packet loss scenarios. -
stream_hang_time: Slot reservation period (default: 10.0-20.0 seconds). After a stream ends (either via terminator frame or timeout), the timeslot remains reserved for the same RF source for this duration, preventing other stations from hijacking the slot between transmissions in a conversation. Recommended: 10.0-20.0 seconds depending on operator speed and network usage patterns.
How It Works:
- DMR transmission begins → stream active
- DMR terminator frame received → stream ends immediately (~60ms), hang time begins
- If terminator lost → stream_timeout (2s) triggers cleanup, hang time begins
- During hang time → only original source can re-use the slot
- After hang time expires → slot available to all
DMR Timing Notes:
- DMR voice packets transmitted approximately every 60ms
- DMR terminator frame signals end of transmission (primary detection method)
- stream_timeout is a fallback safety mechanism only
- hang_time prevents slot hijacking during multi-transmission conversations
See Hang Time Documentation for detailed explanation of these features.
Blacklist Rules
The blacklist section defines patterns for blocking unwanted repeaters. Each pattern can match by ID, ID range, or callsign.
{
"blacklist": {
"patterns": [
{
"name": "Pattern Name",
"description": "Pattern Description",
"match": {
"ids": [123456, 123457]
// OR "id_ranges": [[100000, 199999]]
// OR "callsigns": ["BADACTOR*"]
},
"reason": "Reason for blocking"
}
]
}
}
Blacklist Pattern Options
| Field | Type | Description |
|---|---|---|
name |
string | Unique name for the blacklist pattern |
description |
string | Detailed description of the pattern |
match |
object | One of three match types (see below) |
reason |
string | Reason shown when blocking a repeater |
Match Types
Only ONE match type can be used per pattern:
-
Specific IDs:
"match": { "ids": [310666, 310667] } -
ID Ranges:
"match": { "id_ranges": [[315000, 315999]] } -
Callsign Patterns:
"match": { "callsigns": ["BADACTOR*", "SPAM*"] }Note: Callsign patterns support "*" as a wildcard.
Repeater Configurations
The repeater_configurations section defines patterns for matching repeaters and their configurations. It includes a default configuration and specific patterns.
{
"repeater_configurations": {
"patterns": [...],
"default": {
"enabled": true,
"timeout": 30,
"passphrase": "default-key",
"talkgroups": [3100],
"description": "Default Configuration"
}
}
}
Pattern Structure
Each pattern defines a match rule and associated configuration:
{
"name": "Pattern Name",
"description": "Optional description for documentation",
"match": {
"ids": [312100, 312101]
// OR "id_ranges": [[312000, 312099]]
// OR "callsigns": ["WA0EDA*"]
},
"config": {
"passphrase": "secret-key",
"slot1_talkgroups": [8, 9],
"slot2_talkgroups": [3100, 3101]
}
}
Note: The description field is optional and for human documentation only—it is not used by the program.
Match Types
Like blacklist patterns, repeater patterns support three match types (only ONE per pattern):
- Specific IDs:
"ids"- Array of DMR IDs - ID Ranges:
"id_ranges"- Array of [start, end] ranges (inclusive) - Callsign Patterns:
"callsigns"- Array of patterns with "*" wildcards
Configuration Options
| Option | Type | Description |
|---|---|---|
passphrase |
string | Authentication key for the repeater (required) |
slot1_talkgroups |
array | List of allowed talkgroup IDs for timeslot 1 (bidirectional) |
slot2_talkgroups |
array | List of allowed talkgroup IDs for timeslot 2 (bidirectional) |
Symmetric Routing: The same talkgroup lists control BOTH directions:
- FROM repeater (inbound): Only listed TGIDs are accepted from the repeater
- TO repeater (outbound): Only listed TGIDs are forwarded to the repeater
Special Case - Accept/Forward All Talkgroups:
- Empty list
[]: Accepts and forwards ALL talkgroups (no filtering) - This ensures symmetric routing—if a repeater can send any TG, it can receive any TG
Example:
"config": {
"passphrase": "my-secret-key",
"slot1_talkgroups": [], // Accept/forward ALL on TS1 (no filtering)
"slot2_talkgroups": [3120, 3121] // Accept/forward ONLY 3120 and 3121 on TS2
}
Pattern Matching Priority
When multiple patterns could match a repeater, they are evaluated in this order:
- Specific IDs (highest priority)
- ID Ranges
- Callsign patterns (lowest priority)
The first matching pattern is used.
Talkgroup Definitions
The talkgroups section defines available talkgroups and their properties.
{
"talkgroups": {
"3100": {
"name": "Local",
"bridge": true
}
}
}
Talkgroup Options
| Option | Type | Description |
|---|---|---|
name |
string | Human-readable name for the talkgroup |
bridge |
boolean | Whether to bridge this talkgroup between repeaters |
Configuration Tips
-
Security:
- Use strong passphrases for repeater authentication
- Restrict talkgroups appropriately for each repeater group
- Use blacklisting to prevent unauthorized access
-
Organization:
- Give patterns clear, descriptive names
- Document the purpose of each pattern in its description
- Group related repeaters under common patterns
-
Maintenance:
- Keep the default configuration restrictive
- Document blacklist reasons for future reference
- Use meaningful talkgroup names
-
Validation:
- Ensure no pattern has multiple match types
- Verify talkgroup IDs exist in the talkgroups section
- Check for overlapping ID ranges
Example Configuration
See the config/hblink.json file in the repository for a complete example configuration with multiple patterns and talkgroups.