Die Soft­ware

Feed

In­stal­la­tion und Funktionsbeschreibung 

Letzte Änderung: 29. Apr 2023

Die Soft­ware auf dem Ser­ver und den Clients besteht zum einen aus einem Python-Skript, das die gesamte Steu­erung von Funk­ge­rät, Be­dien­e­le­men­ten des Clients und die Ko­or­di­na­tion über­nimmt. Un­ter­stützt wird es vom Pulse­au­dio-Dämon, der die Über­tra­gung des Tons durch das Netz­werk besorgt.

Im fol­gen­den wird zuerst die In­stal­la­tion der Soft­ware auf dem Ser­ver und den Clients be­schrie­ben. Im An­schluß folgt ein Über­blick über die Funk­tion der Soft­ware. Die De­tails sind im Quell­code do­ku­men­tiert.

Installation

Basis des OVF-Te­le­phons ist das Be­triebs­sys­tem Rasp­ber­ry Pi OS, auf dem dann das OVFT-Pyhton-Skript als System-Daemon läuft.

Die fol­gen­de In­stal­la­tions­be­schrei­bung ist im we­sent­lich­en aus der Datei INSTALL über­nom­men. Es wird die händische In­stal­la­tion eines einzelnen Rasp­ber­rys be­schie­ben.

Das Betriebssystem

Die In­stal­la­tion und Ein­stel­lung­en am Be­triebs­sys­tem können sich­er­lich auch mit dem „Imager“, der In­stal­la­tions­soft­ware von Rasp­ber­ry Pi, gemacht werden. Hier wird aller­dings der Weg mit üb­lich­en Bord­mit­teln be­schrie­ben.

1. Download des Images Download des Rasp­ber­ry-Pi-OS: Das OVF-Te­le­phon ist auf der Ver­sion 2021-10-30-raspios-bullseye-armhf-lite entwickelt worden. Diese Ver­sion 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 ver­wendeten 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-Zu­gangs­da­ten lauten: Benutzer „Pi“, Passwort „raspberry“.

Die fol­gen­den Schritte werden an der Kom­man­do­zei­le des Rasp­ber­ry durch­ge­führt, nachdem man sich dort per SSH ein­ge­loggt hat.

4. Netz­werkeinstellungen Wifi und Blue­tooth werden nicht ge­braucht und daher ab­ge­schal­tet. Dazu werden die fol­gen­den Zeilen zu /boot/config.txt am Ende hin­zu­ge­fügt.

    $ sudo vi /boot/config.txt

    dtoverlay=disable-wifi
    dtoverlay=disable-bt

5. Setzen des Host­namens Um die ver­schie­den­en Clients und den Ser­ver später un­ter­schei­den zu können, empfiehlt es sich, jeweils einen eigenen Host­namen zu setzen. Das geschieht in den Da­tei­en /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 Rasp­ber­ry Pi neu gestartet.

    $ sudo reboot

OVFT-Python-Skripte

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 Ser­ver zusätzlich

    $ sudo apt-get install python3-pyaudio python3-numpy

2. OVFT-Skripte installieren Die Python-Skripte des OVF-Tele­phons finden sich im Ver­zeich­nis src im Download-Archiv. Sie werden per scp auf den Rasp­ber­ry kopiert. Die IP-Adres­se muß auf die tatsächliche Adres­se des Raspis angepaßt werden.

    $ scp -r src pi@192.168.10.106:OVF

3. Systemdienste einrichten

    $ sudo systemctl enable pigpiod

Im fol­gen­den werden entweder die Dienste für den Ser­ver oder die Dienste für den Client ein­ge­rich­tet.

    $ 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 In­stal­la­tion ab­ge­schlos­sen.

Client-Images

Grund­sätz­lich 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:

Funktionsübersicht

Der Quell­code ist insgesamt ganz gut do­ku­men­tiert (hoffe ich). Hier soll also nur ein kurzer Über­blick gegeben werden, zum einen, damit man sich im Code schneller zurecht findet, zum anderen, um Hacking, Fehleranalysen, oder Integration in andere Soft­ware­um­ge­bung zu er­leich­tern.

Struktur des Quell­codes

Der Quell­code be­steht aus einer Reihe von Python-Dateien, die im fol­gen­den auf­ge­lis­tet sind. Die aus­führ­bar­en Dateien sind ovf-server.py und ovf-client-pi.py. Au­ßer­dem gibt es noch einen GUI-Client, der auf einem normalen Rechner laufen kann, ovf-client-gui.py. Letzterer ist aller­dings haupt­säch­lich zum Testen ent­wickelt worden und daher recht spar­tanisch. Die Auswahl der richtigen Audio­ein- und -aus­ga­be­geräte erfolgt im Quell­code oder bei lau­fen­dem Pro­gramm über Pulse­au­dio selbst, z. B. mit Pavu­control.

Ser­ver
ovf-server.py Ser­ver-Skript. Stan­dard­mä­ßig für einen Raspi kon­fi­gu­riert, 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-Pro­gramm
ovf_client_common.py Logik des Clients, wird vom Raspi-Skript und vom GUI-Pro­gramm benutzt.
Kon­fi­gu­ra­tion für Ser­ver und Client
config_net.py Gemeinsame Netz­werk­einstel­lung­en für Ser­ver 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 Frequenz­analyse zur Ruf­ton­erken­nung
thread_set.py thread-sichere Menge (Set)

Pulse­au­dio

Die Be­dien­ung von Pulse­au­dio findet voll­stän­dig im Modul pa-rtp.py statt. Um die Audio­ströme zwischen Netz­werk und Sound­karte steuern zu können, werden eine Reihe von Modulen geladen. Die fol­gen­de Il­lustra­tion stammt aus dem Quell­code.

  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 ent­sprech­en­den Audio-Stream stumm­schal­ten zu können, ohne andere Pro­gramme, die den selben Laut­sprech­er/das selbe Mi­kro­fon benutzen, zu stören. Im Ser­ver wird so außerdem ermöglicht, daß der FFT-Audio-Thread zur 1750 Hz-Erkennung nicht auch stumm­geschaltet wird. Die Loop­back-Module sind nötig, um einen lesen­den mit einem schrei­ben­den Audio­strom zu ver­binden. Gegenüber einer Senke (z. B. Laut­sprech­er) ver­halten sie sich wie ein Audioplayer, der Daten schreibt. Gegen­über einer Quelle (z. B. einem Mikrofon) ver­halten sie sich wie ein Auf­nah­me­pro­gramm, das Daten liest.

Netz­werkverkehr

Der Audio­strom wird per RTP über eine Multicast-IP an alle Clients und den Ser­ver geschickt. Dieser Audio­strom ver­hält sich wie eine Te­le­phon­ie­verbin­dung auf SSB: Jeder, der etwas sendet, wird von allen, die zuhören, gehört. Die Ko­or­di­na­tion zwischen den Clients und dem Ser­ver erfolgt über einfache Text­nach­rich­ten, die bis auf den ini­ti­alen UDP-Broadcast per TCP ver­schickt werden. Die Multicast-IP und die TCP- und UDP-Ports werden in der Datei config_net.py ein­ge­tra­gen. Standardmäßig ist die Multicast-IP 224.0.0.47 und alle TCP- und UDP-Ports sind 11570. Eine Änderung der Werte ist ei­gent­lich nur dann nötig, wenn in einem Netz­werk zwei OVF-Te­le­phon-Anlagen un­ab­hängig von­ein­an­der betrieben werden sollen.

Im fol­gen­den werden die ein­zel­nen TCP- und UDP-Nach­rich­ten zur Ko­or­di­na­tion von Ser­ver und Clients be­schrie­ben. Zu­erst­ein­mal müssen sich Client und Ser­ver finden. Dazu müssen Sie sich im selben Netz befinden. Eine Vor­ab­kon­fi­gu­ra­tion der IP-Adres­sen ist nicht nötig.

OVF-REGISTER Diese Nach­richt wird vom Client als UDP-Broadcast gesendet. Es ant­wortet hof­fent­lich genau ein Ser­ver.

OVF-REGISTER-OK Hiermit ant­wor­tet der Ser­ver. Mit dem Emp­fang dieser Nach­richt erstrahlt die An­zei­ge „verbunden“ am Client. Ab jetzt kennen Ser­ver und Client ge­gen­seit­ig ihre IP.

PING Um zu prüfen, ob der Ser­ver noch da ist, sendet der Client diese Nach­richt per TCP regel­mäßig an den Ser­ver. Es handelt sich also um keinen echten Ping. Der Ser­ver ant­wor­tet auf diese Nach­richt nicht. Wenn die TCP-Ver­bin­dung scheitert, reicht das, um dem Client einen fehlenden Ser­ver zu sig­nal­isie­ren. In diesem Fall erlischt die „ver­bun­den“-An­zei­ge.

Wenn ein Client senden möchte, also die PTT-Taste gedrückt wird, teilt er das mit fol­gen­den Nach­richten dem Ser­ver mit.

PTT-ON wird beim Drücken der PTT gesendet. Mit dem Empfang dieser Nach­richt schaltet der Ser­ver das Funkgerät auf Sendung. Damit ein plötz­lich ver­schwin­den­der Client den Ser­ver nicht mit ein­ge­schal­te­tem Sender zu­rück­läßt, wird diese Nach­richt in re­gel­mäß­ig­en Ab­stän­den wiederholt, solange die PTT gedrückt ist. Fehlen weitere PTT-ON-Nach­richten, schaltet der Ser­ver den Sender wieder aus.

PTT-OFF wird beim Los­lassen der PTT gesendet. Dadurch schaltet der Ser­ver das Funk­gerät sofort wieder in den Emp­fangs­mod­us, so daß man die Ant­wort auf die gemachte Aus­sen­dung hören kann.

Die fol­gen­den Signale steuern den Anruf von Clients, also die Mög­lich­keit, einen Client von anderen Stellen (Clients oder Ser­ver) auf Empfang zu stellen.

LISTEN Wenn der Ser­ver den Ruf­ton von 1750 Hz erkennt, schickt er an alle Clients ein LISTEN. Die Clients schalten da­rauf­hin auf Empfang und die Laut­stär­ke auf 70 %.

LISTEN-INT-REQ Mit dieser Nach­richt sig­nal­i­siert ein Client an den Ser­ver, daß er ein in­tern­es Ge­spräch an­fang­en möchte. Der Ser­ver hat zwei Mög­lich­kei­ten, zu ant­wor­ten …

LISTEN-INT-REJ Diese Ant­wort des Ser­vers erhält der an­for­dern­de Client auf ein LISTEN-INT, wenn gerade ein ex­ter­nes Ge­spräch ge­führt wird.

LISTEN-INT wird vom Ser­ver an alle Clients ge­sen­det, wenn ein einzelner Client ein in­tern­es Ge­spräch mit LISTEN-INT-REQ an­ge­for­dert hat. Die Clients be­han­deln ein LISTEN-INT wie ein LISTEN, nur daß gleich­zei­tig auf „intern“ geschaltet wird.