Automatic codeplug generation for the Baofeng DM-32UV DMR radio.
Pulls repeater data from RadioID, BrandMeister, and a bundled database of 16,000+ repeaters built from RepeaterBook KML data and regional directory PDFs. Produces 4 CSV files ready to import into the DM-32UV CPS programming software.
Available as a web UI and a command-line tool.
No Python, no terminal, no setup. Just download and run.
-
Go to the Releases page and download the file for your platform:
Platform File to download Windows CODEPLUGGER-windows.zipmacOS CODEPLUGGER-macos.tar.gzLinux CODEPLUGGER-linux.tar.gz -
Extract the downloaded file anywhere you like (e.g. your Desktop or Documents folder)
-
Windows: Open the extracted
CODEPLUGGERfolder and double-clickCODEPLUGGER.exemacOS / Linux: Open a terminal in the extracted folder and run./CODEPLUGGER -
A black window will appear briefly while the server starts — your browser will open automatically to the app at
http://localhost:8000 -
Leave the black window open while you use the app. Closing it shuts down the server.
Note: Windows may show a "Windows protected your PC" warning the first time. Click "More info" then "Run anyway" — this appears because the app isn't code-signed yet.
If there's no package available for your platform yet, or you prefer to run from source. About 30 minutes the first time.
- A Windows 10 or 11 computer
- An internet connection
- About 200 MB of free disk space
- The Baofeng DM-32UV CPS programming software (already installed for use with your radio)
That's it. No accounts, no API keys required.
CODEPLUGGER is written in Python, so you need to install Python first. Python is free.
- Open your web browser and go to https://www.python.org/downloads/
- Click the big yellow "Download Python 3.x" button (any version 3.10 or newer works — at the time of writing that's 3.14)
- Open the file you just downloaded (it's in your Downloads folder)
- VERY IMPORTANT: at the bottom of the installer window, check the box that says "Add python.exe to PATH" — if you skip this, nothing else will work
- Click "Install Now"
- When it says "Setup was successful", click "Close"
To check it worked: Press the Windows key, type cmd, press Enter. A black window opens. Type:
python --version
Press Enter. You should see Python 3.something (e.g. Python 3.14.0). If you see "not recognized as a command," you missed the PATH checkbox in step 4 — uninstall Python and start over.
Close that window when you're done.
- Go to https://github.com/jimdawdy-hub/codeplugger
- Click the green "Code" button (top right of the file list)
- Click "Download ZIP" at the bottom of the menu that pops down
- Find the downloaded file
codeplugger-main.zip(in your Downloads folder) - Right-click it → "Extract All..." → choose a place you'll remember (your Documents folder is a good choice) → click "Extract"
You now have a folder like Documents\codeplugger-main\ with the app inside it.
- Open File Explorer and navigate into the
codeplugger-mainfolder you just extracted - Click on the address bar at the top of File Explorer (where it shows the folder path)
- Type
cmdand press Enter — a black Command Prompt window opens, already pointing at the right folder - In that window, type exactly:
and press Enter
pip install -r requirements.txt - Wait 1–2 minutes. You'll see a lot of lines scrolling by saying "Collecting..." and "Installing..." — that's normal. When the prompt (
C:\...>) comes back by itself, it's done.
In the same Command Prompt window from Step 3, type:
python -m uvicorn web.app:app --port 8000
and press Enter.
You should see something like this:
INFO: Started server process [12345]
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000
Leave this window open! Closing it shuts down the app. You can minimize it, just don't close it.
- Open your web browser (Chrome, Edge, Firefox, whatever you normally use)
- In the address bar, type:
http://localhost:8000and press Enter - The CODEPLUGGER page loads — fill in the form, generate your codeplug, download the ZIP
- Unzip the downloaded codeplug and import the 4 CSV files into the DM-32UV CPS software in this exact order:
- Talk Groups
- RX Group Lists
- Channels
- Zones
A README.txt is included in the ZIP that explains the import order again.
Click the Command Prompt window, then hold Ctrl and press C once. The server stops. You can close the window.
You only have to do Steps 1–3 once. To use the app again on another day:
- Open File Explorer, go to
Documents\codeplugger-main\ - Click the address bar, type
cmd, press Enter - Type
python -m uvicorn web.app:app --port 8000and press Enter - Open your browser to
http://localhost:8000
| Problem | Fix |
|---|---|
'pip' is not recognized |
You missed the "Add Python to PATH" checkbox in Step 1. Uninstall Python from Settings → Apps, then redo Step 1 with the box checked. |
'python' is not recognized |
Same as above. |
Port 8000 is already in use |
Another program is using port 8000. Use --port 8001 instead, then visit http://localhost:8001 |
| Browser says "This site can't be reached" | The Command Prompt window is closed. Restart it (Step 4). |
| "Permission denied" during pip install | Right-click Command Prompt and choose "Run as administrator", then redo Step 3. |
| Need help | Open an issue at https://github.com/jimdawdy-hub/codeplugger/issues |
- Enter your DMR ID — your callsign and name are filled in automatically
- Pick one or more states to search
- Choose which networks you care about (BrandMeister, DMR-MARC, Tristate)
- The app searches RadioID and shows you every DMR repeater in those states — check/uncheck to include or exclude. A green ✓BM badge means the repeater is verified on the BrandMeister network.
- Click Search Analog Repeaters to add FM repeaters from the bundled database (16,000+ across all 50 states). They'll be grouped into zones by state and band — for example "IL 2m Analog", "IN 70cm Analog".
- Pick hotspot talkgroups from the catalog (1,700+ TGs grouped by Wide Area, US States, Countries, Language, Activity, etc.) — each category has a "Select All" checkbox
- Set TX power and hotspot frequency
- Agree to the disclaimer, type your initials, click Generate & Download — you get a ZIP containing the 4 CSV files plus a README
If you have a BrandMeister account, you can add an API key to get a green ✓BM verification badge on repeaters that are confirmed on the BM network. This is completely optional — the app works fine without it.
- Log in at https://brandmeister.network and go to your profile → API keys
- Generate a new API key
- Create a file at
C:\Users\YourName\.config\dmr-codeplug.jsonwith this content (replace the X's with your actual key):{"brandmeister_api_key": "XXXXXXXXXXXXXXXXX"} - Restart the app
python main.py \
--dmr-id 3179879 \
--city Chicago --state Illinois \
--networks BrandMeister DMR-MARC Tristate \
--max 40 \
--hotspot --hs-tgs 91 93 3117 3118 9 310 312 \
--out ./my_codeplugOther useful flags:
--dry-run— show what would be generated without writing files--list-hs-tgs— list available hotspot talkgroups--refresh-bm— force re-download of BrandMeister cache
The bundled data/repeaters.db is built from a Google Drive ZIP of RepeaterBook KML files plus regional PDF directories. To refresh it:
python import_data.pyThe KML ZIP can be downloaded from https://drive.google.com/drive/folders/10Lvzkdtox8vG7iNkpQHSOIUfn8yUNV5b — drop it in the project root and run the import.
Four CSV files for import into the DM-32UV CPS — in this order:
| # | File | Contents |
|---|---|---|
| 1 | talk_groups.csv |
Talkgroup list (TX Contact references these by name) |
| 2 | rx_group_lists.csv |
Receive group lists |
| 3 | channels.csv |
One channel per talkgroup per repeater, plus hotspot zones and analog channels |
| 4 | zones.csv |
Per-repeater zones, per-category hotspot zones, per-state/band analog zones |
- Bundled repeater database — 16,000+ analog repeaters from all 50 states, no API keys required
- State-only search — pick states, get all repeaters, choose what you want
- Per-category hotspot zones — Wide Area, US States, Countries, Language, Activity, Emcomm, Link — each capped at 64 channels with overflow paging
- Mandatory disconnect — every hotspot zone ends with TG 4000 disconnect; users can't accidentally omit it
- Per-state/band analog zones — separate "IL 2m Analog", "IL 70cm Analog", "IN 2m Analog" zones rather than one giant Analog zone
- BrandMeister verification (optional, with key) — cross-references RadioID data against BM device registry
- Official TG names from CSV — bundled BM talkgroup catalog (1,700+ entries)
- Parrot Private Call — TG 9990 and 310997 correctly configured as Private Call (required for echo test)
- 12-char name limit — clean LCD display on the radio
codeplug/
├── models.py — Dataclasses: Repeater, Channel, Zone, Codeplug, etc.
├── radioid.py — RadioID.net API client
├── brandmeister.py — BrandMeister API client + caching
├── bm_talkgroups.py — BM talkgroup catalog loader (CSV)
├── repeater_db.py — Local SQLite repeater database
├── kml_import.py — RepeaterBook KML/KMZ importer
├── pdf_import.py — Regional repeater directory PDF parsers
├── hearham_import.py — HearHam.com DMR talkgroup scraper
├── defaults.py — TG abbreviations, network prefixes
├── builder.py — CodeplugBuilder: assembles codeplug from repeater data
└── csv_export.py — Writes the 4 DM-32UV CSV files
web/
├── app.py — FastAPI backend
└── static/index.html — Single-page dark-themed UI
main.py — CLI entry point
import_data.py — Repeater database build tool
- Tested with the Baofeng DM-32UV and its CPS software
GroupCall Match = Offis recommended for ham use — the radio hears all traffic on matching frequency/color code/timeslot regardless of talkgroup- See
LESSONS_LEARNED.mdfor DMR domain knowledge and CPS quirks - See
ONBOARDING.mdfor full architecture and development history
MIT License — © 2026 James Dawdy, KQ9I. See LICENSE for full text.
CODEPLUGGER would not exist without the work of the amateur radio community:
-
RepeaterBook — The bundled repeater database (
data/repeaters.db) was built from RepeaterBook's publicly shared Google Earth KML export. RepeaterBook is a community-maintained repeater directory. Their data is used here for personal, non-commercial amateur radio purposes in the spirit in which it was shared. -
RadioID.net — Live DMR repeater and user data via their free public API. RadioID is the global registry for DMR IDs.
-
BrandMeister — Live repeater verification and talkgroup catalog via their public API. The bundled
Talkgroups BrandMeister.csvcontains community-maintained talkgroup data from the BrandMeister network. -
HearHam — DMR talkgroup data source for the optional
import_data.py --hearhamimport.
Software dependencies (all MIT or BSD licensed): FastAPI · uvicorn · httpx · pdfplumber · pydantic
Not affiliated with Baofeng, BrandMeister, RadioID.net, or RepeaterBook.
