READY.
Die Software auf dem Server und den Clients besteht zum einen aus einem Python-Skript, das die gesamte Steuerung von Funkgerät, Bedienelementen des Clients und die Koordination übernimmt. Unterstützt wird es vom Pulseaudio-Dämon, der die Übertragung des Tons durch das Netzwerk besorgt.
Im folgenden wird zuerst die Installation der Software auf dem Server und den Clients beschrieben. Im Anschluß folgt ein Überblick über die Funktion der Software. Die Details sind im Quellcode dokumentiert.
Basis des OVF-Telephons ist das Betriebssystem Raspberry Pi OS, auf dem dann das OVFT-Pyhton-Skript als System-Daemon läuft.
Die folgende Installationsbeschreibung ist im wesentlichen aus der Datei INSTALL übernommen. Es wird die händische Installation eines einzelnen Raspberrys beschieben.
Die Installation und Einstellungen am Betriebssystem können sicherlich auch mit dem „Imager“, der Installationssoftware von Raspberry Pi, gemacht werden. Hier wird allerdings der Weg mit üblichen Bordmitteln beschrieben.
1. Download des Images Download des Raspberry-Pi-OS: Das OVF-Telephon ist auf der Version 2021-10-30-raspios-bullseye-armhf-lite entwickelt worden. Diese Version steht auch hier zum Download bereit.
2. Image auf SD-Karte kopieren Das ZIP-Archiv wird entpackt und auf die SD-Karte kopiert.
sudo dd status=progress if=2021-10-30-raspios-bullseye-armhf-lite.img of=/dev/sdd bs=1M
Die Namen der Image-Datei und des verwendeten Block-Gerätes der SD-Karte (hier /dev/sdd/) müssen angepaßt werden.
3. SSH-Zugang Zu Aktivierung des SSH-Zugangs muß die boot-Partition eingehängt werden und dort eine leere Datei des Namens „ssh“ erstellt werden.
$ pmount /dev/sdd1 $ touch /media/sdd1/ssh $ pumount /media/sdd1
Die SSH-Zugangsdaten lauten: Benutzer „Pi“, Passwort „raspberry“.
Die folgenden Schritte werden an der Kommandozeile des Raspberry durchgeführt, nachdem man sich dort per SSH eingeloggt hat.
4. Netzwerkeinstellungen
Wifi und Bluetooth werden nicht
gebraucht und daher abgeschaltet. Dazu werden die folgenden Zeilen zu
/boot/config.txt
am Ende hinzugefügt.
$ sudo vi /boot/config.txt dtoverlay=disable-wifi dtoverlay=disable-bt
5. Setzen des Hostnamens
Um die verschiedenen Clients
und den Server später unterscheiden zu können, empfiehlt es sich, jeweils
einen eigenen Hostnamen zu setzen. Das geschieht in den Dateien
/etc/hostname
und /etc/hosts
.
# Change the name in /etc/hostname $ sudo vi /etc/hostname ovf-1 # and in /etc/hosts $ sudo vi /etc/hosts 127.0.1.1 ovf-1
Anschließend wird der Raspberry Pi neu gestartet.
$ sudo reboot
1. Pakete aktualisieren und installieren
Pakete aktualisiern
$ sudo apt-get update $ sudo apt-get upgrade
Neue Pakete installieren
$ sudo apt-get install python3-pigpio pulseaudio
… für den Server zusätzlich
$ sudo apt-get install python3-pyaudio python3-numpy
2. OVFT-Skripte installieren
Die Python-Skripte des
OVF-Telephons finden sich im Verzeichnis src
im Download-Archiv. Sie werden per scp auf den
Raspberry kopiert. Die IP-Adresse muß auf die tatsächliche Adresse des
Raspis angepaßt werden.
$ scp -r src pi@192.168.10.106:OVF
3. Systemdienste einrichten
$ sudo systemctl enable pigpiod
Im folgenden werden entweder die Dienste für den Server oder die Dienste für den Client eingerichtet.
$ sudo ln -s /home/pi/OVF/ovf-client.service /etc/systemd/system $ sudo systemctl enable ovf-client $ sudo ln -s /home/pi/OVF/ovf-server.service /etc/systemd/system $ sudo systemctl enable ovf-server
4. Neustart
$ sudo reboot
Hiermit ist die Installation abgeschlossen.
Grundsätzlich könnte man, nachdem der erste Client installiert ist, von dessen SD-Karte ein Image erzeugen und dann auf die anderen Clients kopieren. Dabei ist aber zu beachten:
Der Quellcode ist insgesamt ganz gut dokumentiert (hoffe ich). Hier soll also nur ein kurzer Überblick gegeben werden, zum einen, damit man sich im Code schneller zurecht findet, zum anderen, um Hacking, Fehleranalysen, oder Integration in andere Softwareumgebung zu erleichtern.
Der Quellcode besteht aus einer Reihe von Python-Dateien, die im folgenden
aufgelistet sind. Die ausführbaren Dateien sind
ovf-server.py
und ovf-client-pi.py
. Außerdem gibt
es noch einen GUI-Client, der auf einem normalen Rechner laufen kann,
ovf-client-gui.py
. Letzterer ist allerdings hauptsächlich zum
Testen entwickelt worden und daher recht spartanisch. Die Auswahl der
richtigen Audioein- und -ausgabegeräte erfolgt im Quellcode oder bei
laufendem Programm über Pulseaudio selbst, z. B. mit Pavucontrol.
Server | |
---|---|
ovf-server.py | Server-Skript. Standardmäßig für einen Raspi konfiguriert, kann aber auch auf anderem Rechner laufen; PTT dann über RS-232. |
Client | |
ovf-client-pi.py | Client-Script für den Raspi |
ovf-client-gui.py | Client als GUI-Programm |
ovf_client_common.py | Logik des Clients, wird vom Raspi-Skript und vom GUI-Programm benutzt. |
Konfiguration für Server und Client | |
config_net.py | Gemeinsame Netzwerkeinstellungen für Server und Client |
Funktionsmodule | |
incremental_encoder.py | Abfrage des Drehgebers (Lautstärke am Client) |
out74595.py | Ausgabe mit Schieberegistern (LEDs am Client) |
physical_ptt.py | Bedienung der PTT am Funkgerät, Pin oder RS2332 |
pa_rtp.py | Kapselung von Pulseaudo mit RTP-Modulen |
th_audio_fft.py | Thread zur Frequenzanalyse zur Ruftonerkennung |
thread_set.py | thread-sichere Menge (Set) |
Die Bedienung von Pulseaudio findet vollständig im Modul
pa-rtp.py
statt. Um die Audioströme zwischen Netzwerk und
Soundkarte steuern zu können, werden eine Reihe von Modulen geladen. Die
folgende Illustration stammt aus dem Quellcode.
Set-up of pulseaudio modules ---------------------------- rtp-recv null-sink loopback speaker sink rtp-rx-sink rx ,----,, ,,------, ,----,, ,,------, / \\ || | / \\ || | ( ||==>====|| |-->----| ||==>==|| | \ // || | \ // || | '----'' ''------' '----'' ''------' rtp-send null-sink loopback mic/line-in rtp-tx-sink tx source ,-----, ,------,, ,,----, ,------, / \ | || // \ | \ ( |--<----| ||==<====|| |--<--| ) \ / | || \\ / | / '-----' '------'' ''----' '------' ===== writing stream (data is pushed by player) ----- reading stream (data is pulled by recorder)
Die null-sinks rtp-tx-sink
und rtp-rx-sink
dienen
dazu, den entsprechenden Audio-Stream stummschalten zu können, ohne andere
Programme, die den selben Lautsprecher/das selbe Mikrofon benutzen, zu
stören. Im Server wird so außerdem ermöglicht, daß der FFT-Audio-Thread zur
1750 Hz-Erkennung nicht auch stummgeschaltet wird. Die Loopback-Module
sind nötig, um einen lesenden mit einem schreibenden Audiostrom zu
verbinden. Gegenüber einer Senke (z. B. Lautsprecher) verhalten sie
sich wie ein Audioplayer, der Daten schreibt. Gegenüber einer Quelle
(z. B. einem Mikrofon) verhalten sie sich wie ein Aufnahmeprogramm,
das Daten liest.
Der Audiostrom wird per RTP über eine Multicast-IP an alle Clients und den
Server geschickt. Dieser Audiostrom verhält sich wie eine
Telephonieverbindung auf SSB: Jeder, der etwas sendet, wird von allen,
die zuhören, gehört. Die Koordination zwischen den Clients und dem Server
erfolgt über einfache Textnachrichten, die bis auf den initialen
UDP-Broadcast per TCP verschickt werden. Die Multicast-IP und die TCP- und
UDP-Ports werden in der Datei config_net.py
eingetragen.
Standardmäßig ist die Multicast-IP 224.0.0.47 und alle TCP- und UDP-Ports sind
11570. Eine Änderung der Werte ist eigentlich nur dann nötig, wenn in einem
Netzwerk zwei OVF-Telephon-Anlagen unabhängig voneinander
betrieben werden sollen.
Im folgenden werden die einzelnen TCP- und UDP-Nachrichten zur Koordination von Server und Clients beschrieben. Zuersteinmal müssen sich Client und Server finden. Dazu müssen Sie sich im selben Netz befinden. Eine Vorabkonfiguration der IP-Adressen ist nicht nötig.
OVF-REGISTER Diese Nachricht wird vom Client als UDP-Broadcast gesendet. Es antwortet hoffentlich genau ein Server.
OVF-REGISTER-OK Hiermit antwortet der Server. Mit dem Empfang dieser Nachricht erstrahlt die Anzeige „verbunden“ am Client. Ab jetzt kennen Server und Client gegenseitig ihre IP.
PING Um zu prüfen, ob der Server noch da ist, sendet der Client diese Nachricht per TCP regelmäßig an den Server. Es handelt sich also um keinen echten Ping. Der Server antwortet auf diese Nachricht nicht. Wenn die TCP-Verbindung scheitert, reicht das, um dem Client einen fehlenden Server zu signalisieren. In diesem Fall erlischt die „verbunden“-Anzeige.
Wenn ein Client senden möchte, also die PTT-Taste gedrückt wird, teilt er das mit folgenden Nachrichten dem Server mit.
PTT-ON wird beim Drücken der PTT gesendet. Mit dem Empfang dieser Nachricht schaltet der Server das Funkgerät auf Sendung. Damit ein plötzlich verschwindender Client den Server nicht mit eingeschaltetem Sender zurückläßt, wird diese Nachricht in regelmäßigen Abständen wiederholt, solange die PTT gedrückt ist. Fehlen weitere PTT-ON-Nachrichten, schaltet der Server den Sender wieder aus.
PTT-OFF wird beim Loslassen der PTT gesendet. Dadurch schaltet der Server das Funkgerät sofort wieder in den Empfangsmodus, so daß man die Antwort auf die gemachte Aussendung hören kann.
Die folgenden Signale steuern den Anruf von Clients, also die Möglichkeit, einen Client von anderen Stellen (Clients oder Server) auf Empfang zu stellen.
LISTEN Wenn der Server den Rufton von 1750 Hz erkennt, schickt er an alle Clients ein LISTEN. Die Clients schalten daraufhin auf Empfang und die Lautstärke auf 70 %.
LISTEN-INT-REQ Mit dieser Nachricht signalisiert ein Client an den Server, daß er ein internes Gespräch anfangen möchte. Der Server hat zwei Möglichkeiten, zu antworten …
LISTEN-INT-REJ Diese Antwort des Servers erhält der anfordernde Client auf ein LISTEN-INT, wenn gerade ein externes Gespräch geführt wird.
LISTEN-INT wird vom Server an alle Clients gesendet, wenn ein einzelner Client ein internes Gespräch mit LISTEN-INT-REQ angefordert hat. Die Clients behandeln ein LISTEN-INT wie ein LISTEN, nur daß gleichzeitig auf „intern“ geschaltet wird.