15. März 2026
Mit einem alten Wählscheibentelefon gezielt EchoLink-Nodes weltweit anrufen – klingt unmöglich, funktioniert aber. Dieser Artikel beschreibt den langen Weg dorthin und was dabei über die Zusammenarbeit mit einer KI gelernt wurde.
Die Idee klingt absurd: Ein altes Wählscheibentelefon, das keine Raute-Taste kennt und nur Impulswahl beherrscht, soll sich mit beliebigen EchoLink-Nodes weltweit verbinden können. EchoLink ist ein System, das Amateurfunkstationen über das Internet miteinander verbindet und normalerweise eine moderne Software oder zumindest ein DTMF-fähiges Telefon voraussetzt. Das Ziel war also von Anfang an sportlich.

Was ist EchoLink: EchoLink ist ein System das Amateurfunkstationen weltweit über das Internet miteinander verbindet. Die Grundidee ist einfach: Wer eine Amateurfunklizenz besitzt, kann sich mit einem anderen Funkamateur irgendwo auf der Welt unterhalten, ohne dass die Funkwellen die Distanz tatsächlich überbrücken müssen. Stattdessen wird die Verbindung über das Internet hergestellt, entweder von Computer zu Computer, vom Mobiltelefon zu einer Funkstation oder von Relais zu Relais.
EchoLink gibt es seit 2002 und es ist kostenlos nutzbar, allerdings ausschließlich für lizenzierte Funkamateure. Die Zulassung wird über das offizielle Rufzeichen geprüft, das jeder Funkamateur von der zuständigen Behörde seines Landes erhält. Weltweit sind mehrere hunderttausend Stationen registriert, von denen zu jeder Tages- und Nachtzeit tausende gleichzeitig online sind.
Neben Einzelverbindungen zwischen zwei Stationen gibt es sogenannte Konferenzserver, auf denen sich beliebig viele Teilnehmer gleichzeitig treffen können, ähnlich wie in einem Chatroom, nur eben per Sprache. Bekannte deutsche Konferenzräume sind zum Beispiel GERMANY, auf denen sich Funkamateure aus dem deutschsprachigen Raum treffen. Jede Station und jeder Konferenzraum hat eine eindeutige Nodenummer, über die sie weltweit erreichbar ist.
Zunächst zur ehrlichen Einschätzung: Der praktische Nutzen dieses Projekts ist sehr begrenzt. Kaum jemand wird ein Wählscheibentelefon besitzen und gleichzeitig EchoLink nutzen wollen. Die Bedienung ist umständlicher als jede moderne Alternative, und der Aufwand für die Installation steht in keinem vernünftigen Verhältnis zum Ergebnis. Aber genau das ist der Charme der Sache. Ein Telefon aus den 1970er Jahren, das über Asterisk und SVXLink ins weltweite EchoLink-Netzwerk telefoniert – das hat eine ganz eigene Faszination, die sich rational kaum erklären lässt.
Über eine sprachgesteuerte Vermittlung sich mit dem Telefon in das Echolink-Netzwerk einwählen.
Die Hardware-Konstellation ist bewusst zweigeteilt. Ein Raspberry Pi 3B dient als Haupt-Asterisk-Instanz und ist die Schnittstelle zur Außenwelt – er verwaltet die SIP-Accounts der angeschlossenen Telefone und nimmt Anrufe aus dem Heimnetz entgegen. Im gleichen LAN ist er per IAX2-Protokoll mit einem zweiten Asterisk verbunden, der auf dem Hauptrechner läuft, einem Intel Esprimo Q520 mit 8 GB RAM und Ubuntu MATE. Diese Aufteilung hat zwei Vorteile: Der Raspberry wird entlastet, und die gesamte Entwicklungsarbeit an SVXLink und den Python-Scripts kann direkt auf dem Hauptrechner stattfinden, ohne ständig zwischen Geräten wechseln zu müssen. Auf dem Esprimo laufen also der zweite Asterisk mit PJSIP auf Port 5075, SVXLink mit der EchoLink-Anbindung und zusätzlich die sprachgesteuerte Vermittlung Fräulein vom Amt, die OpenAI Whisper zur Spracherkennung nutzt und bereits in einem früheren Artikel beschrieben wurde. All das auf einer Maschine mit bescheidener Hardware – der Esprimo ist kein Kraftpaket, bewältigt die Aufgabe aber problemlos.
Das Wählscheibentelefon ist über die analoge Telefonbuchse einer Fritz!Box angeschlossen, die als ATA fungiert und das alte Gerät in ein vollwertiges SIP-Telefon verwandelt. Die Fritz!Box versteht auch die Impulswahl älterer Telefone und leitet die gewählte Nummer als SIP-Anruf an Asterisk weiter. Die fehlende Raute-Taste ist dabei kein Problem mehr – das Python-AGI-Script echolink_connect.py übernimmt die gesamte Steuerung, die sonst manuell erledigt werden müsste. Nachdem Asterisk die Verbindung zu SVXLink aufgebaut hat, schreibt das Script mit gezielten Zeitverzögerungen eine Befehlssequenz in das Pseudo-Terminal von SVXLink: Zuerst werden mit zwei Hash-Zeichen eventuell noch laufende EchoLink-Verbindungen getrennt und das Modul deaktiviert, dann wird das EchoLink-Modul mit der Sequenz 2# neu aktiviert, und schließlich wird die gewählte Nodenummer gefolgt von einem Hash-Zeichen übergeben. Was früher bedeutet hätte, diese Tasten manuell auf einem DTMF-Telefon eintippen zu müssen, erledigt das Script vollautomatisch im Hintergrund.
Das technische Fundament bildet SVXLink, eine leistungsfähige Open-Source-Software zur Repeatersteuerung unter Linux, die unter anderem EchoLink unterstützt. Die entscheidende Erweiterung ist der pjSipLogic-Branch von Adi/DL1HRC, der SVXLink um eine SIP-Logik erweitert und damit die Verbindung zur Telefonwelt ermöglicht. Diese Erweiterung ist experimentell und muss aus dem Quellcode kompiliert werden, was bereits eine erste Hürde darstellt. Ohne das GitHub-Repository von DL1HRC wäre das Projekt nicht möglich gewesen.

Die eigentliche Intelligenz steckt in einem Python-AGI-Script namens echolink_connect.py, das von Asterisk aufgerufen wird sobald jemand die Vorwahl 73 gefolgt von einer EchoLink-Nodenummer wählt. Das Script übernimmt die komplette Steuerung: Es baut zunächst die SIP-Verbindung zu SVXLink auf, schreibt dann in einer bestimmten Reihenfolge Steuerbefehle in ein Pseudo-Terminal, das SVXLink überwacht. Dabei werden zunächst eventuell noch laufende EchoLink-Verbindungen getrennt, dann das EchoLink-Modul aktiviert und schließlich die gewünschte Nodenummer übergeben. Alles vollautomatisch, ohne dass der Anrufer eine einzige Taste drücken muss.
Die Konfiguration von SVXLink besteht im Wesentlichen aus drei Teilen. Die svxlink.conf definiert zwei Logiken – eine SimplexLogic mit dem EchoLink-Modul und eine SipLogic für die Telefonanbindung – die über einen sogenannten SipLink miteinander verbunden sind. Die SipLogic.conf enthält die SIP-Zugangsdaten für den lokalen Asterisk. Die ModuleEchoLink.conf konfiguriert EchoLink selbst mit Rufzeichen, Passwort und dem entscheidenden Parameter MUTE_LOGIC_LINKING=0, ohne den kein Audio vom EchoLink zurück zum Telefon fließt. Eine eigene TCL-Datei namens SipLogic.tcl im local-Verzeichnis der SVXLink-Events sorgt dafür, dass DTMF-Töne vom Telefon an die richtige Logik weitergeleitet werden.
Ein entscheidendes Dokument für das Gesamtverständnis war eine PDF-Anleitung von DL1HRC,
https://github.com/dl1hrc/documentation/blob/main/SvxLink-Contributions.pdf
die den genauen Aufbau der SipLogic beschreibt und insbesondere Abschnitt 3.1d zeigt, wie EchoLink über die SipLogic angewählt werden kann. Ohne dieses Dokument wäre die korrekte Verschaltung der beiden SVXLink-Logiken über das DTMF_CTRL_PTY-Pseudo-Terminal nicht klar gewesen.
Die entsprechenden Abschnitte habe ich herauskopiert und an Claude Sonnet übermittelt, das mir dann bei der Konfiguration und beim Kompilieren von svxlink Schritt für Schritt geholfen hat.
Kompilieren: In der PDF- Anleitung https://github.com/dl1hrc/documentation/blob/main/SvxLink-Contributions.pdf von DL1HRC findet sich die Installationsanleitung für die pjSipLogic-Erweiterung in Abschnitt 3.1 sowie die allgemeine Installationsanleitung ab Abschnitt 2.2. Dort sind die Schritte für die Entwicklungsumgebung, die Installation des pjSIP-Frameworks und das Kompilieren von SVXLink beschrieben. Bild 3 in der Anleitung zeigt die Schrittfolge als Übersicht.
Ein wichtiger Hinweis der in der Anleitung steht und den man unbedingt beachten muss: Das Kompilieren darf nicht als root durchgeführt werden. Das betrifft sowohl das Kompilieren von pjSIP als auch von SVXLink selbst. Der Grund ist dass beim Kompilieren unter root Dateien mit falschen Besitzverhältnissen angelegt werden können, was später beim Start des SVXLink-Dienstes als svxlink-User zu Berechtigungsfehlern führt. Außerdem warnt DL1HRC ausdrücklich davor dass Reste früherer SVXLink-Installationen zu Problemen führen können — eine bestehende Installation sollte daher vorher mit sudo apt remove --purge svxlink-server entfernt werden.
Wer das Kompilieren noch nie gemacht hat, dem empfiehlt sich folgendes Vorgehen: Man kopiert das entsprechende Kapitel aus dem PDF von DL1HRC heraus und übergibt es zusammen mit den tatsächlichen Fehlermeldungen aus dem Terminal direkt an Claude Sonnet. Die KI erklärt dann jeden Schritt, deutet Fehlermeldungen und schlägt Korrekturen vor. Genau so ist dieses Projekt entstanden — durch schrittweise Zusammenarbeit, bei der keine tiefe Programmiererfahrung vorausgesetzt wurde, sondern die KI als geduldiger und kenntnisreicher Begleiter durch den gesamten Prozess geführt hat.
Zusammenarbeit mit Claude Sonnet 4.6 : Was dieses Projekt aber wirklich bemerkenswert macht, ist nicht das technische Ergebnis selbst, sondern wie es zustande kam. Als Programmieranfänger wäre dieses Projekt ohne die Hilfe von Claude, dem KI-Assistenten von Anthropic, schlicht nicht realisierbar gewesen. Über zwei Tage hinweg wurden Schritt für Schritt Konfigurationsfehler analysiert, Logdateien ausgewertet und Lösungsansätze entwickelt. Was dabei auffiel: Die KI ging bei der Fehlersuche probabilistisch vor wie ein erfahrener Programmierer. Sie suchte proaktiv nach Alternativen, auf die man als Anfänger nie gekommen wäre – etwa der entscheidende Wechsel von der RepeaterLogic zur SimplexLogic auf Hinweis von DL1HRC, oder die Lösung des PTY-Berechtigungsproblems durch Hinzufügen des Asterisk-Users zur tty-Gruppe. Beim Python-AGI-Script wurden mehrere Ansätze durchprobiert und verworfen, bis die richtige Kombination aus direkter stdin/stdout-Kommunikation mit Asterisk und parallelem Schreiben ins SVXLink-PTY gefunden war.
Besonders beeindruckend war, dass sich die KI in die Zielsetzung hineinversetzen konnte, ohne dass jedes Detail neu erklärt werden musste. Sie verstand den Zusammenhang zwischen den einzelnen Komponenten, erinnerte sich an frühere Fehlermeldungen und zog daraus Schlüsse für neue Probleme. Das ist eine neue Qualität der Mensch-Maschine-Zusammenarbeit, die hier sehr deutlich spürbar wurde – nicht als Ersatz für menschliches Verständnis, sondern als geduldiger, kenntnisreicher Partner, der auch um Mitternacht noch neue Ideen hat.
Das Ergebnis übertrifft die ursprüngliche Erwartung sogar noch. Nicht nur lässt sich vom Wählscheibentelefon durch einfaches Wählen von 73 gefolgt von der Nodenummer jeder EchoLink-Node weltweit erreichen. Über die bereits vorhandene Sprachvermittlung Fräulein vom Amt, die Whisper zur Spracherkennung nutzt, kann man einfach den Namen der Konferenz sprechen und wird automatisch verbunden. Ein Telefon aus den 1970ern, das per Stimme EchoLink-Konferenzen weltweit anruft – das hätte sich wohl niemand träumen lassen.
Die Konfigurationsdateien für SVXLink:
# /etc/svxlink/svxlink.conf [GLOBAL] LOGIC_CORE_PATH=/usr/lib/x86_64-linux-gnu/svxlink LOGICS=SimplexLogic,SipLogic CFG_DIR=svxlink.d TIMESTAMP_FORMAT="%c" CARD_SAMPLE_RATE=48000 LINKS=SipLink [SipLink] CONNECT_LOGICS=SimplexLogic,SipLogic DEFAULT_ACTIVE=1 [SimplexLogic] TYPE=Simplex RX=Rx1 TX=Tx1 MODULES=ModuleEchoLink CALLSIGN=SM5ZBS-L SHORT_IDENT_INTERVAL=60 LONG_IDENT_INTERVAL=60 EVENT_HANDLER=/usr/share/svxlink/events.tcl DEFAULT_LANG=de_DE RGR_SOUND_DELAY=0 DTMF_CTRL_PTY=/var/spool/svxlink/dtmf_repeater [Rx1] TYPE=Dummy AUDIO_DEV=none [Tx1] TYPE=Dummy AUDIO_DEV=none
# /etc/svxlink/svxlink.d/ModuleEchoLink.conf [ModuleEchoLink] NAME=EchoLink ID=2 TIMEOUT=60 CALLSIGN=SM5ZBS-L PASSWORD=DeinEcholinkPasswort SYSOPNAME=Volker LOCATION=Finspang JO78tr SERVERS=servers.echolink.org MUTE_LOGIC_LINKING=0 DESCRIPTION="SM5ZBS-L EchoLink node"
# /etc/svxlink/svxlink.d/SipLogic.conf [SipLogic] TYPE=Sip DEFAULT_LANG=de_DE SIPSERVER=127.0.0.1:5075 SIPREGISTRAR=127.0.0.1:5075 SIPPORT=5060 CALLERNAME=SM5ZBS-L <svxlink> USERNAME=svxlink PASSWORD=passwort_fuer_sip SIPSCHEMA=Digest SIPEXTENSION=default AUTOANSWER=1 SIP_LOGLEVEL=0 CALL_TIMEOUT=45 SEMI_DUPLEX=0 VOX_FILTER_DEPTH=20 VOX_THRESH=1000 SQL_HANGTIME=1500 SIP_CTRL_PTY=/var/spool/svxlink/sip_pty DTMF_CTRL_PTY=/var/spool/svxlink/dtmf_repeater EVENT_HANDLER=/usr/share/svxlink/events.tcl SIP_PREAMP=3 SIP_LIMITER_THRESH=-1.0 IGNORE_REGISTRATION=1 # AUTOCONNECT=sip:88351864@127.0.0.1:5075 ACCEPT_INCOMING=^(.*)$
SVXLink Event-Handler: Ort: /usr/share/svxlink/events.d/local/SipLogic.tcl
namespace eval SipLogic {
variable stored_digits ""
proc dtmf_digit_received {digit caller} {
variable port
variable stored_digits
puts "Dtmf digit received $digit from $caller"
if {$digit == "#"} {
set port [open "/var/spool/svxlink/dtmf_repeater" w+]
puts $port $stored_digits
puts $port "#"
close $port
set stored_digits ""
} else {
set stored_digits "$stored_digits$digit"
}
return 0
}
proc callTerminated {reason} {
puts "SIP call terminated, disconnecting EchoLink"
catch {
set port [open "/var/spool/svxlink/dtmf_repeater" w+]
puts $port "#"
close $port
}
}
}
SVXLinks Sounds: /usr/share/svxlink/sounds/de_DE/ — installiert aus https://github.com/dl1hrc/svxlink-sounds-de_DE-petra . Es fehlt noch eine welcome.wav in /usr/share/svxlink/sounds/de_DE/SipLogic/welcome.wav, die man mit 16.000 Hz selbst sampeln muss ( welcome.wav.zip ). Das geht Audacity. Der Sprecher ist von ElevenLabs.
Konfigurations-Dateien für Asterisk: Sie befinden sich wie üblich in /etc/asterisk
;===============================================================================
; extensions.conf - Einfacher Dialplan für 3000-3999
;===============================================================================
[general]
static=yes
writeprotect=no
;-------------------------------------------------------------------------------
; Kontext: telefone
;-------------------------------------------------------------------------------
[telefone]
exten => _73.,1,NoOp(EchoLink Node Zielnummer ${EXTEN:2})
same => n,Noop(Echolink Anrufer: "${CALLERID(name)}" <${CALLERID(num)}>)
same => n,AGI(echolink_connect.py,${EXTEN:2})
same => n,Hangup()
; EchoLink via SVXLink (Vorwahl 77) Alternative Einwahl
exten => _77.,1,NoOp(EchoLink Node ${EXTEN:2})
same => n,Noop(Echolink: "${CALLERID(name)}" <${CALLERID(num)}>)
same => n,Dial(PJSIP/svxlink,60,rtT)
same => n,Hangup()
; Durchwahl 3000-3999
exten => _3XXX,1,Dial(PJSIP/${EXTEN},60,rtT)
same => n,Hangup()
exten => 501,1,Answer(2)
same => n,Playback(beep)
; Aufnahme: 3 Sek Stille stoppt, max 20 Sek, 's' für Stille-Erkennung
same => n,Set(AGC(RX)=on)
same => n,Set(VOLUME(RX)=2.5)
same => n,Record(/tmp/sprache.wav,3,20,s)
same => n,Playback(beep) ; Whisper braucht kurz zum Rechnen
same => n,AGI(whisper_test.py,/tmp/sprache.wav)
; Überprüfung: Wenn nichts erkannt wurde, zum Fehler-Teil springen
same => n,GotoIf($["${RECOGNIZED}" = "nichts"]?no_number,1)
same => n,GotoIf($["${RECOGNIZED}" = "error"]?no_number,1)
; Ansage der Nummer zur Kontrolle
same => n,Playback(beep)
same => n,SayDigits(${RECOGNIZED})
; JETZT WÄHLEN:
same => n,Dial(IAX2/outgoing-raspi111/${RECOGNIZED})
same => n,Hangup()
; Fehlerbehandlung
exten => no_number,1,Playback(beep)
same => n,Hangup()
; ECHOTEST (HALL, ZEITVERZOEGERUNG DEUTSCH)
exten => 222,1,NoOp(ECHOTEST)
same => n,Noop(ECHOTEST: "${CALLERID(name)}" <${CALLERID(num)}>)
same => n,Answer() ; Abheben
same => n,Set(CHANNEL(language)=de)
same => n,Wait(2) ; Warten
same => n,Playback(demo-echotest) ; Ansage
same => n,Echo ; Echotest
same => n,Playback(demo-echodone) ; Bestaetigung
same => n,Hangup() ; Auflegen
; Konferenzraum ohne PIN (z.B. Raum 600 - wähle 600, um beizutreten)
exten => 600,1,ConfBridge(600)
same => n,Hangup()
; IAX2-Verbindung zum Raspi11
exten => _8835X.,1,NoOp(IAX2 - Esprimo ruft Raspi an mit Vorwahl 8835)
same => n,Dial(IAX2/outgoing-raspi111/${EXTEN:4})
; ── Fräulein vom Amt ────────────────────────────────────────────────────────
; Nebenstelle 500 - Sprachvermittlung
; Dialog läuft komplett in whisper_vermittlung.py
; RECOGNIZED wird gesetzt auf: Nummer | "auflegen" | "error"
exten => 500,1,Noop(Sprachgesteuerte Vermittlung. Teilnehmer: "${CALLERID(name)}" <${CALLERID(num)}>)
same => n,Answer(1)
; same => n,Set(CHANNEL(language)=de)
; same => n,Set(AGC(RX)=off)
; same => n,Set(VOLUME(RX)=2)
; same => n,Set(VOLUME(TX)=1)
; Kompletter Dialog läuft im AGI
; whisper_vermittlung.py übernimmt:
; - Ansagen via gTTS
; - Aufnahme und Erkennung
; - Bestätigungsdialog
; - Setzt RECOGNIZED, RECOGNIZED_TYPE, RECOGNIZED_NAME
same => n,AGI(whisper_vermittlung.py)
; Auswertung
same => n,GotoIf($["${RECOGNIZED}" = "auflegen"]?hangup,1)
same => n,GotoIf($["${RECOGNIZED}" = "error"]?hangup,1)
same => n,GotoIf($["${RECOGNIZED}" = "nichts"]?hangup,1)
; Verbinden
same => n,NoOp(Verbinde: Typ=${RECOGNIZED_TYPE} Name=${RECOGNIZED_NAME} Nummer=${RECOGNIZED})
same => n,Dial(IAX2/outgoing-raspi111/${RECOGNIZED})
same => n,Hangup()
; ── Auflegen ─────────────────────────────────────────────────────────────────
exten => hangup,1,Hangup()
;-------------------------------------------------------------------------------
; Kontext: from-svxlink
; Eingehende Anrufe von SVXLink SipLogic
;-------------------------------------------------------------------------------
[from-svxlink]
exten => s,1,NoOp(Eingehender Anruf von SVXLink)
same => n,Noop(Echolink: "${CALLERID(name)}" <${CALLERID(num)}>)
same => n,Dial(IAX2/outgoing-raspi111/1864,30,rtT)
same => n,Hangup()
;=============================================================================== ; PJSIP Configuration für Asterisk 16+ ; Registrar: 192.168.1.235:5075 – nur LAN 192.168.1.0/24 ;=============================================================================== ;------------------------------------------------------------------------------- ; Transport Definition (Netzwerk-Bindung) ;------------------------------------------------------------------------------- [transport-udp] type=transport protocol=udp bind=0.0.0.0:5075 local_net=192.168.1.0/24 local_net=127.0.0.1/32 external_media_address=192.168.1.235 external_signaling_address=192.168.1.235 ;------------------------------------------------------------------------------- ; Globale Einstellungen ;------------------------------------------------------------------------------- [global] max_forwards=70 user_agent=Asterisk PBX ;------------------------------------------------------------------------------- ; ACL – nur LAN zugelassen ;------------------------------------------------------------------------------- [acl-lan] type=acl deny=0.0.0.0/0.0.0.0 permit=192.168.1.0/24 permit=127.0.0.1/32 ;------------------------------------------------------------------------------- ; Templates ;------------------------------------------------------------------------------- [teilnehmer-template](!) type=aor max_contacts=1 qualify_frequency=15 default_expiration=300 maximum_expiration=3600 [teilnehmer-auth](!) type=auth auth_type=userpass [teilnehmer-endpoint](!) type=endpoint context=telefone transport=transport-udp ; ACL – nur LAN deny=0.0.0.0/0.0.0.0 permit=192.168.1.0/24 permit=127.0.0.1/32 ; Codec-Einstellungen disallow=all allow=g722,alaw,ulaw,gsm,vp8 allow_overlap=no allow_transfer=no allow_subscribe=no ; NAT & Media direct_media=no rtp_symmetric=yes force_rport=yes rewrite_contact=yes ice_support=yes ; DTMF dtmf_mode=rfc4733 ; Session Timers timers=no timers_min_se=90 timers_sess_expires=1800 ; QoS/ToS tos_audio=ef tos_video=af41 cos_audio=5 cos_video=4 ; WebRTC webrtc=no ;------------------------------------------------------------------------------- ; SVXLink SipLogic ;------------------------------------------------------------------------------- [svxlink-aor](!) type=aor max_contacts=1 qualify_frequency=15 default_expiration=300 maximum_expiration=3600 [svxlink](teilnehmer-endpoint) auth=svxlink aors=svxlink callerid="EchoLink" <7373> context=telefone deny=0.0.0.0/0.0.0.0 permit=127.0.0.1/32 [svxlink](teilnehmer-auth) username=svxlink password=passwort_fuer_sip [svxlink](svxlink-aor) ;------------------------------------------------------------------------------- ; Teilnehmer 3001 - Kalle Anka ;------------------------------------------------------------------------------- [3001](teilnehmer-endpoint) auth=3001 aors=3001 callerid="Kalle Anka" <3001> [3001](teilnehmer-auth) username=3001 password=pass3001 [3001](teilnehmer-template) ;------------------------------------------------------------------------------- ; Teilnehmer 3002 - Donald Duck ;------------------------------------------------------------------------------- [3002](teilnehmer-endpoint) auth=3002 aors=3002 callerid="Donald Duck" <3002> [3002](teilnehmer-auth) username=3002 password=pass3002 [3002](teilnehmer-template) ;------------------------------------------------------------------------------- ; Teilnehmer 3003 - Dagobert Duck ;------------------------------------------------------------------------------- [3003](teilnehmer-endpoint) auth=3003 aors=3003 callerid="Dagobert Duck" <3003> [3003](teilnehmer-auth) username=3003 password=pass3003 [3003](teilnehmer-template) ;------------------------------------------------------------------------------- ; Teilnehmer 3004 - Max Mustermann ;------------------------------------------------------------------------------- [3004](teilnehmer-endpoint) auth=3004 aors=3004 callerid="Max Mustermann" <3004> [3004](teilnehmer-auth) username=3004 password=pass3004 [3004](teilnehmer-template) ;------------------------------------------------------------------------------- ; Teilnehmer 3005 - King Kong ;------------------------------------------------------------------------------- [3005](teilnehmer-endpoint) auth=3005 aors=3005 callerid="King Kong" <3005> [3005](teilnehmer-auth) username=3005 password=pass3005 [3005](teilnehmer-template) ;------------------------------------------------------------------------------- ; Teilnehmer 3006 - Adam Smith ;------------------------------------------------------------------------------- [3006](teilnehmer-endpoint) auth=3006 aors=3006 callerid="Adam Smith" <3006> [3006](teilnehmer-auth) username=3006 password=pass3006 [3006](teilnehmer-template)
; iax.conf sending-server ubuntu [general] disallow=all allow=g722 allow=alaw allow=ulaw ; allow=g722 jitterbuffer=yes forcejitterbuffer=yes maxjitterbuffer=400 ; ← höher als normal wegen WLAN resyncthreshold=2000 autokill=yes delayreject=yes requirecalltoken=yes authdebug=yes ; language=de qualify=yes ; **************************** ; Verbindung zum Raspberry 192.168.111 ; vom Esprimo 192.168.1.235 [outgoing-raspi111] description=Vorwahl 8891 zum Raspberry type=peer host=192.168.1.111 secret=xbodoxzack auth=md5 context=telefone trunk=no qualify=yes requirecalltoken=no calltokenoptional=yes authdebug=no username=incoming-esprimo235 iaxcompat=yes deny=0.0.0.0/0.0.0.0 permit=192.168.1.111 [incoming-raspi111] type=user host=192.168.1.111 secret=xbodoxzack auth=md5 context=telefone trunk=no qualify=yes requirecalltoken=no calltokenoptional=yes authdebug=no username=outgoing-esprimo235 iaxcompat=yes deny=0.0.0.0/0.0.0.0 permit=192.168.1.111
; rtp.conf [general] rtpstart=10501 rtpend=10700 jbenable=yes jbmaxsize=200 jbresyncthreshold=1000 jbimpl=adaptive
; features.conf [general] transferdigittimeout => 3 [featuremap] blindxfer => * [applicationmap]
Das Python-Skript für AGI: /usr/share/asterisk/agi-bin/echolink_connect.py
#!/usr/bin/env python3
import sys
import time
# AGI Variablen lesen
env = {}
while True:
line = sys.stdin.readline()
if not line or line == '\n':
break
line = line.strip()
if ': ' in line:
key, val = line.split(': ', 1)
env[key] = val
node_number = env.get('agi_arg_1', '9999')
# ANSWER
sys.stdout.write("ANSWER\n")
sys.stdout.flush()
sys.stdin.readline()
# PTY beschreiben
with open("/var/spool/svxlink/dtmf_repeater", "w") as f:
f.write("#\n")
time.sleep(3)
with open("/var/spool/svxlink/dtmf_repeater", "w") as f:
f.write("#\n")
time.sleep(3)
with open("/var/spool/svxlink/dtmf_repeater", "w") as f:
f.write("2#\n")
time.sleep(3)
with open("/var/spool/svxlink/dtmf_repeater", "w") as f:
f.write(node_number + "#\n")
time.sleep(1)
# Dial
sys.stdout.write("EXEC Dial PJSIP/svxlink,60,rtT\n")
sys.stdout.flush()
sys.stdin.readline()
Berechtigungen: Zwei Berechtigungsänderungen für das Python-Skript waren nötig.
1. Asterisk-User zur Gruppe tty — das Python-Script läuft unter dem Asterisk-User, aber das PTY `/dev/pts/1` gehört der Gruppe `tty`. Ohne diese Mitgliedschaft konnte das Script nicht ins PTY schreiben und brach stillschweigend ab:
sudo usermod -a -G tty asterisk
sudo systemctl restart asterisk
2. Verzeichnis /var/spool/svxlink/ — SVXLink muss dort die PTY-Symlinks anlegen. Das Verzeichnis gehört dem User svxlink:
sudo mkdir -p /var/spool/svxlink
sudo chown svxlink:svxlink /var/spool/svxlink
Das war der Grund warum das Script lange scheinbar funktionierte — es startete, las die AGI-Variablen, antwortete mit ANSWER — aber beim Öffnen des PTY warf Python eine Exception und beendete sich still, ohne den EXEC Dial zu senden.
Portforwarding: EchoLink benötigt zwei UDP-Ports die in der Fritz!Box weitergeleitet werden müssen:
UDP 5198 — EchoLink Audio
UDP 5199 — EchoLink Steuerung
Beide müssen auf die interne IP des Esprimo weitergeleitet werden, also auf 192.168.1.235, wo sich das Programm svxlink befindet. Ohne diese Portfreigaben verbindet sich EchoLink zwar zum Verzeichnisserver und erscheint als online, aber eingehende Verbindungen von anderen Nodes kommen nicht durch — und ausgehende Verbindungen zu manchen Nodes schlagen ebenfalls fehl.
Wichtige Befehle:
sudo tail -f /var/log/svxlink
Das ist der wichtigste Befehl — er zeigt live was SVXLink tut: eingehende Anrufe, DTMF-Digits, EchoLink-Verbindungsaufbau, Squelch-Ereignisse und Fehlermeldungen.
Wenn du mehr Details über den SIP-Teil sehen willst, erhöhe in der `SipLogic.conf` vorübergehend:
SIP_LOGLEVEL=4
Und für Asterisk parallel dazu:
sudo asterisk -rvvv
agi set debug on
Das zeigt den kompletten AGI-Dialog zwischen Asterisk und dem Python-Script sowie den Aufbau der PJSIP-Verbindung zu SVXLink.
SVXLink starten und stoppen:
sudo systemctl start svxlink
sudo systemctl stop svxlink
sudo systemctl restart svxlink
Und den aktuellen Status prüfen:
sudo systemctl status svxlink
Wichtig: wenn SVXLink als root manuell gestartet wurde, legt es die PTY-Symlinks als root an und der spätere Start als svxlink-User schlägt fehl. Dann vorher aufräumen:
sudo rm /var/spool/svxlink/dtmf_repeater
sudo rm /var/spool/svxlink/sip_pty
Ein klassischer Linux-Fallstrick mit den Sicherheitskopien von Linux: Wenn man in einem Dateimanager wie Nautilus oder Thunar eine Sicherheitskopie einer Konfigurationsdatei anlegt, entsteht automatisch eine Datei mit einem Namen wie `svxlink.conf (Kopie)` oder `svxlink (noch eine Kopie).conf` — direkt im selben Verzeichnis `/etc/svxlink/`.
SVXLink liest beim Start alle Dateien im Konfigurationsverzeichnis die auf `.conf` enden. Eine Datei namens `svxlink (Kopie).conf` endet auf `.conf` und wird deshalb ebenfalls gelesen. Enthält diese Kopie zum Beispiel noch den alten Eintrag `CALLSIGN=SM5ZBS` statt `CALLSIGN=SM5ZBS-L`, oder eine fehlerhafte DESCRIPTION mit Einrückungen, dann schlägt SVXLink beim Start mit einem kryptischen Syntaxfehler fehl — und man sucht den Fehler in der falschen Datei, weil die eigentliche `svxlink.conf` längst korrekt ist.
Genau das ist uns passiert: SVXLink meldete `Configuration file parse error. Illegal value line syntax on line 12` und startete mehrfach neu, obwohl die aktuelle Konfiguration einwandfrei aussah. Erst als die Kopien gefunden und gelöscht wurden, startete SVXLink sauber. Die Lehre daraus: Sicherheitskopien von SVXLink-Konfigurationsdateien niemals im selben Verzeichnis ablegen, sondern in einem separaten Backup-Ordner außerhalb von `/etc/svxlink/`.
Weiterführend:
|
|
Sprachgesteuerte Telefonvermittlung mit OpenAI Whisper und Asterisk – 5. März 2026: In vielen Museen stehen sie noch – alte Telefonvermittlungen, stumm und unberührt hinter Glas. Dieses Projekt erweckt eine solche Anlage zum Leben: Besucher heben den Hörer ab, nennen einen Namen oder eine Nummer, und die Vermittlung stellt durch. Was wie Magie klingt, steckt dahinter: das quelloffene Spracherkennungsmodell Whisper von OpenAI, kombiniert mit der Telefonanlage Asterisk auf einem Raspberry Pi. – weiter – |
|
|
Asterisk-Telefonserver auf einem Raspberry Pi – Installation, Konfiguration, Programmierung, SIP, IAX2, AGI-Skripte, Sicherheit und Tipps zum praktischen Betrieb – 2.11.2022: Diese Seite richtet sich an jene, welche einen Asterisk-Telefon-Server auf einem Raspberry Pi betreiben möchten und später ein kleines Netzwerk aus Asterisk-Servern planen, um ein eigenständiges Telefonnetz aufzubauen. Los geht es mit der Installation von Raspbian und Asterisk auf einem Raspberry Pi und dann nach Lust und Laune immer tiefer in die Programmierung von Asterisk. Die Themen werden laufend erweitert.
Selbstverständlich muss es nicht unbedingt ein Raspberry Pi sein. Andere Linux-Rechner gehen auch. – weiter – |

