SIP-DMR Radio Gateway

Un gateway bidirezionale scritto in Python che permette di collegare centralini VoIP SIP (come FreePBX) a reti radio DMR (tramite protocollo OpenBridge)[cite: 2].

Il sistema gestisce l'handshake SIP, la transcodifica audio in tempo reale tra PCM (G.711a) e AMBE, il controllo PTT tramite toni DTMF e il cambio dinamico del Talkgroup direttamente dal tastierino del telefono, simulando il comportamento di una vera radio[cite: 2].

🚀 Caratteristiche Principali

  • Integrazione Trasparente: Dialoga nativamente con FreePBX gestendo i ping OPTIONS (Trunk PJSIP)[cite: 2].
  • Cambio Canale al Volo: Digita il numero del Talkgroup sul telefono e il gateway ti sposterà di stanza senza far cadere la chiamata[cite: 2].
  • Sicurezza IP: Rifiuta nativamente le connessioni SIP da IP non autorizzati[cite: 2].
  • Aggiornamento Display: Usa il protocollo re-INVITE per mostrare Caller ID (DMR ID) e Talkgroup attivi sui telefoni hardware compatibili[cite: 2].
  • Transcoding 100% Software: Nessun hardware dedicato richiesto (es. DVStick). Il sistema usa l'emulatore nativo md380-emu elaborando l'audio crudo (RAW) direttamente tramite CPU.
  • Multi-Tenancy Dinamica: Gestisce chiamate simultanee multiple. Il motore alloca e dealloca dinamicamente le porte UDP instradando gli stream audio in tempo reale sui vocoder liberi.
  • Audio Bidirezionale G.711 / AMBE: Converte al volo i pacchetti SIP A-Law in PCM lineare 16-bit (tramite modulo audioop) per la rete DMR, e viceversa.

🛠️ 1. Prerequisiti di Sistema (Debian / Ubuntu)

Prima di installare il gateway, assicurati di avere gli strumenti di compilazione e l'ambiente Python installati sul server[cite: 2]:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git build-essential python3 python3-venv python3-pip

(Nota: su architetture a 64-bit potrebbe essere necessario installare libc6-dev-i386 per compilare correttamente l'emulatore AMBE)[cite: 2].


📻 2. Installazione Motore Audio Scalabile (md380-emu)

Il cuore della conversione audio è l'emulatore open-source md380-emu[cite: 2]. Va scaricato, compilato e configurato come "template" Systemd per supportare un pool di porte[cite: 2].

cd /opt
sudo git clone https://github.com/nostar/md380-emu.git
cd md380-emu
sudo make

Creazione del demone Systemd Template per le istanze multiple:

Crea il file /etc/systemd/system/md380-emu@.service:

[Unit]
Description=MD380 Emulator Vocoder (Port %i)
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/md380-emu
# Il %i verrà sostituito automaticamente con il numero di porta
ExecStart=/opt/md380-emu/emulator -p %i
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

Attivazione delle istanze (es. per 10 canali simultanei):

Ricarica i demoni e avvia il loop di porte (es. dalla 2470 alla 2479):

sudo systemctl daemon-reload
for port in {2470..2479}; do
    sudo systemctl enable --now md380-emu@$port.service
done

(Per aumentare la capacità futura, ti basterà avviare nuovi servizi systemctl ed espandere il range di porte generate in vocoder_engine.py).


💻 3. Installazione del Gateway Python

Clona questo repository e configura l'ambiente virtuale[cite: 2]:

cd /opt
git clone https://git.arifvg.it/iv3jdv/sip-dmr-gateway.git
cd sip-dmr-gateway

# Crea e attiva il Virtual Environment
python3 -m venv venv
source venv/bin/activate

# Installa le dipendenze
pip install -r requirements.txt

Copia i file di esempio per creare la tua configurazione reale[cite: 2]:

cp config.example.json config.json
cp utenti.example.json utenti.json

Modifica config.json: Inserisci le credenziali del tuo server HBlink/OpenBridge, le porte e, soprattutto, l'IP autorizzato del tuo server FreePBX per la sicurezza[cite: 2].


⚙️ 4. Configurazione FreePBX

Affinché il centralino dialoghi correttamente con il Gateway, crea un Trunk PJSIP con queste regole[cite: 2]:

  • Autenticazione: Nessuna (Identity via IP Match)[cite: 2]. L'IP match deve puntare all'IP del server dove gira questo script Python[cite: 2].
  • Qualify Frequency: Lascialo attivo (es. 60 secondi)[cite: 2]. Il gateway risponderà regolarmente con 200 OK[cite: 2].
  • Codecs: Disabilita tutto e lascia spuntato SOLO alaw (G.711a)[cite: 2].
  • Advanced -> DTMF Mode: Imposta su RFC4733[cite: 2].
  • Advanced -> Trust RPID/PAI: Imposta su Yes[cite: 2].
  • Advanced -> Send RPID/PAI: Imposta su Both[cite: 2].

Crea poi una Rotta in Uscita (Outbound Route) che intercetti un prefisso a tua scelta (es. 99) e che lo strippi (lo elimini), inviando al Trunk solo il numero del Talkgroup[cite: 2].


📞 5. Utilizzo e Comandi DTMF (Tastierino)

Chiama la rotta configurata su FreePBX seguita dal Talkgroup desiderato (es. componi 99 222 per entrare sul TG 222)[cite: 2]. Una volta in linea, usa il tastierino del telefono per pilotare la radio[cite: 2]:

  • Tasto * (Asterisco): Premi per abilitare il PTT e iniziare a trasmettere[cite: 2].
  • Tasto # (Cancelletto): Premi per disabilitare il PTT e tornare in ascolto[cite: 2].
  • Tasti 0-9 (Cambio Canale): Digita il numero di un nuovo Talkgroup (es. 9, 1) e rilascia i tasti[cite: 2]. Dopo circa 2,5 secondi il sistema ti sposterà automaticamente sul nuovo TG (verrai avvisato da un aggiornamento sul display del telefono, se supportato)[cite: 2].

🔄 6. Esecuzione come Servizio (Produzione)

Per far avviare il Gateway automaticamente al boot, crea il file /etc/systemd/system/sipdmr.service[cite: 2]:

[Unit]
Description=Gateway SIP-DMR Core
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/sip-dmr-gateway
ExecStart=/opt/sip-dmr-gateway/venv/bin/python3 /opt/sip-dmr-gateway/core.py
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=sipdmr

[Install]
WantedBy=multi-user.target

Abilita e avvia il gateway[cite: 2]:

sudo systemctl enable sipdmr --now

Per visualizzare i log in tempo reale e monitorare il traffico radio[cite: 2]:

journalctl -u sipdmr -f
S
Description
No description provided
Readme 3 MiB
Languages
Python 100%