The shipped unit files carry the author's user and paths (User=cort, /home/cort/hblink4), so copying them verbatim produces two services that fail to start. The docs said so only in a Customization section below the copy instructions, and told people to edit the repo copies -- which then conflict on the next git pull. The installer prompts for the service user and group (defaulting to the invoking sudo user and their primary group), substitutes them and the detected installation path into both units, installs to /etc/systemd/system/, reloads systemd, and optionally enables and starts the services. It backs up existing units, refuses unknown users/groups, checks the venv exists, warns when the service user cannot write the installation directory, and verifies the substitution landed before leaving anything in place. DESTDIR previews the output without touching the live system. The manual instructions now say to copy first and edit the installed copy, and note that daemon-reload is required after any unit change. Both unit files carry a header saying the same. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
HBlink4 Scripts
install_services.sh
Installs the systemd unit files with your user, group and paths filled in — the
shipped units carry the author's (User=cort, /home/cort/hblink4) and will not
work unmodified.
sudo ./scripts/install_services.sh
Prompts for the service user and group (defaulting to whoever ran sudo and
that user's primary group), rewrites both units, installs them to
/etc/systemd/system/, runs systemctl daemon-reload, and optionally enables
and starts the services. Any existing units are backed up as
<unit>.bak-<timestamp> first.
Preview the result without touching the live system:
sudo DESTDIR=/tmp/preview ./scripts/install_services.sh
See SYSTEMD.md for manual installation and service management.
filter_user_csv.py
Filters the DMR user database to only include US and Canada entries, reducing file size and memory usage.
Note
: The dashboard now refreshes
user.csvautomatically on a daily schedule via dashboard/user_db.py, applying configurable country/callsign/ID filters without a restart. This script remains available for manual / one-off filtering when the automated pipeline isn't in use.
Usage
Download latest user database:
# Download from radioid.net or other DMR database source
wget -O user_full.csv https://example.com/user.csv
Filter for US/Canada only:
# Process and save to user.csv
python3 scripts/filter_user_csv.py user_full.csv user.csv
# Or overwrite the original file:
python3 scripts/filter_user_csv.py user.csv
Output:
Processing user_full.csv...
✅ Filtering complete!
Kept: 132,999 entries (45.6%)
- Canada: 7,047
- United States: 125,952
Skipped: 158,969 entries (54.4%)
📊 File sizes:
Input: 14.79 MB
Output: 7.21 MB
Saved: 7.57 MB (51.2%)
✨ Filtered CSV written to: user.csv
Why Filter?
- Memory efficiency: 54% fewer entries to load
- Disk space: 51% smaller file size
- Target audience: Primary users are US/Canada
- Performance: Faster startup time for dashboard
Adding More Countries
To include additional countries, edit filter_user_csv.py line 52:
if country in ('United States', 'Canada', 'United Kingdom'): # Add more here
Automation
To automatically update and filter the user database:
#!/bin/bash
# update_user_database.sh
echo "Downloading latest user database..."
wget -O user_full.csv https://example.com/user.csv
echo "Filtering for US/Canada..."
python3 scripts/filter_user_csv.py user_full.csv user.csv
echo "Cleaning up..."
rm user_full.csv
echo "Done! Restart dashboard to load new database."