Hi Khalaf,
Thanks for the sharp question - you found a real gap, not a configuration mistake. There was no Docker path for the DMR bridge; everything assumed bare metal with systemd. So I built one, and it is now in the repository ready for you to try.
First, the architecture, because it explains why the systemd instructions did not apply. The bridge is not part of the CAD container, and it is really two programs that must run together:
The bridge itself is hbp_client.py. It speaks HomeBrew Protocol over UDP to your HBLink3 master and serves a small HTTP control surface on port 18091 that the CAD talks to.
The vocoder is md380-emu. This is the piece that surprises people: the actual AMBE voice codec is not something we wrote or ship. It is MD-380 radio firmware in emulation, listening on UDP 2470, and the bridge hands it each 20 ms of audio. Without it you get a bridge that connects perfectly and passes silence.
Those two run in a single container, because the bridge reaches the vocoder at
127.0.0.1:2470 - they have to share a network namespace. And to answer your original question directly: docker-config-gen.php is not involved at all; it only turns environment variables into the CAD's config.php.
To install it, from a git clone of the repository:
cd services/dvswitch/docker
cp .env.example .env
docker compose up -d --build
Fill in .env with your DMR ID 4300098, callsign A61KT, your Frankfurt master and port 54000, your passphrase, and the bearer token the CAD generated for the channel. You do not need to hand-write an MMDVM_Bridge.ini - the container generates it from those variables at startup. If you would rather supply your own, mount it at /etc/ticketscad/MMDVM_Bridge.ini and it takes precedence.
Then in the CAD, edit that DMR channel and set the bridge host to wherever the bridge is reachable from the CAD container, the bridge port to 18091, and the same bearer token. If you want browser push-to-talk as well, start the CAD's voice profile with: docker compose --profile voice up -d
Verify it in this order, because it isolates problems quickly.
Step 1 - Test the vocoder on its own. No radio or network needed:
docker run --rm ticketscad-dmr-bridge:local selftest
You want to see "md380-emu is answering on UDP 2470" and "codec round-trip succeeds." Do not be alarmed by the small peak amplitude number it prints - 40 to 60 is normal and my production bridge measures 55.
Step 2 - Watch it log in to your master:
docker compose logs -f dmr-bridge
You should see the config load, "bound local UDP 62032", and "sent RPTL" followed by a successful login. If it says "login stalled in state 1, retrying" then the master is not answering - check the address and port, the passphrase, and that your HBLink3 config authorises DMR ID 4300098.
Step 3 - Confirm the CAD can reach it. The channel should show connected in Settings, Communications, DMR. From the bridge host you can also run:
curl -H "Authorization: Bearer YOUR_TOKEN"
http://127.0.0.1:18091/healthThe full guide is docs/RADIO-DMR-DOCKER.md in the repository, with a troubleshooting table.
Now the honest part about what is and is not proven. On a real Docker host I verified that the image builds, that the vocoder answers and the AMBE round-trip passes, that the ini renders correctly from the environment variables, and that the bridge loads its config, binds its UDP socket and sends the HBP login. What I could not test is the part that needs a real master: the login completing, the HTTP control surface coming up (it starts listening after login succeeds), and actual audio on the air. You have the one thing I do not - a working HBLink3 master - so you are effectively the first real-world test of this path. If it works, you will be the reason it exists for everyone after you. If it does not, send me the output of "docker compose logs dmr-bridge" and I will fix it quickly.
Two things I found while building this that may save you time. The vocoder has to come from the DVSwitch project's package repository - building it from the upstream md380tools source produces a version without the UDP server mode the bridge needs, so it starts and then refuses. The container handles that for you. And a self-test in our own code was reporting failure on hardware that was actually working fine; that is fixed, so pull the latest before you build.
73, and thanks again - this is exactly the kind of report that makes the software better.
Eric