APRS: Telemetriedaten vom Raspberry Pi 2 mit pymultimonaprs übertragen

Im vorigen Artikel habe ich beschrieben, wie ich pymultimonaprs auf einem Raspberry Pi 2 konfiguriert habe.

Nun möchte ich in der Status-Zeile ein paar Telemetriedaten übermitteln, die vom Raspberry ausgelesen werden. Konkret sind das:

  • Core Temperatur
  • Core Spannung
  • Core Spannung der SDRAM_p
  • Clock Speeds von Core und ARM

Dazu habe ich ein Script erstellt, das alle 5 Minuten über cron gestartet wird und die vollständige Status-Zeile in der Datei /tmp/aprs-telemetrie.txt hinterlegt. pymultimonaprs versendet dann den Inhalt dieser Datei als Statusmeldung.

Dieses Script (abgelegt als /home/pi/aprs-telemetrie.sh) liest die Werte aus und erstellt die Datei:

#!/bin/bash
echo "Raspberry Pi 2 mit RTL Stick core_temp="`vcgencmd measure_temp | awk -F'=' '{print $2}'\
`" core_volt="`vcgencmd measure_volts core | awk -F'=' '{print $2}'`\
" sdram_p_volt="`vcgencmd measure_volts sdram_p | awk -F'=' '{print $2}'`\
" core_clock="`vcgencmd measure_clock core | awk -F'=' '{print $2}'`\
" arm_clock="`vcgencmd measure_clock arm | awk -F'=' '{print $2}'` > /tmp/aprs-telemetrie.txt

Die Datei sieht nun so aus:

pi@roofpi ~ $ cat /tmp/aprs-telemetrie.txt 
Raspberry Pi 2 mit RTL Stick core_temp=26.1'C core_volt=1.2000V sdram_p_volt=1.2250V core_clock=250000000 arm_clock=600000000

Den Cron-Job habe ich so erstellt:

*/5 * * * *   root    /home/pi/aprs-telemetrie.sh

Nun habe ich folgende Einträge in der mymultimonaprs-Konfigurationsdatei /etc/pymultimonaprs.json geändert:

        "status": {
            "text": false,
            "file": "/tmp/aprs-telemetrie.txt"
        },

Nach einem Neustart von pymultimonaprs mittels

/etc/init.d/pymultimonaprs restart

hat das sofort geklappt:

Jan  2 13:17:40 roofpi pymultimonaprs: connecting... 95.155.111.242:14580
Jan  2 13:17:40 roofpi pymultimonaprs: connected
Jan  2 13:17:40 roofpi pymultimonaprs: # aprsc 2.0.14-g28c5a6a
Jan  2 13:17:40 roofpi pymultimonaprs: login OE1SCS-10 (PyMultimonAPRS 1.2.0)
Jan  2 13:17:40 roofpi pymultimonaprs: # logresp OE1SCS-10 verified, server T2KRAKOW
Jan  2 13:17:40 roofpi pymultimonaprs: sending: OE1SCS-10>APRS,TCPIP*:=4811.4 N/01623.2 E-RXonly APRS iGate
Jan  2 13:17:40 roofpi pymultimonaprs: sending: OE1SCS-10>APRS,TCPIP*:>Raspberry Pi 2 mit RTL Stick core_temp=25.6'C core_volt=1.2000V sdram_p_volt=1.2250V core_clock=250000000 arm_clock=600000000

 

APRS iGate über HAMnet mit pymultimonaprs

Seit kurzem habe ich bei mir im 3. Wiener Gemeindebezirk am Dach meines Wohnhauses (ca. 8. Stock) – unter anderem – folgendes Equipment installiert:

IMG_4834Der Raspberry und DVB-T-Stick sind in einem Outdoor-Gehäuse verbaut.

Mit diesem Setup möchte ich einen APRS iGate realisieren, also eine Konfiguration, mit der APRS-Pakete auf der europäischen APRS-Frequenz 144.800 MHz empfangen und dann weitergeleitet werden. Die Weiterleitung soll primär über HAMnet erfolgen und nur im Fehlerfall oder bei nicht-Verfügbarkeit meiner HAMnet-Anbindung direkt ans einen APRS-IS-Tier2-Server (vgl. http://www.aprs2.net/)  ins Internet übertragen werden.

Voraussetzung

Als Voraussetzung sollte die RTL-SDR-Software und Treiber am Raspberry bereits installiert sein. Der Vorgang ist unter anderem hier beschrieben: http://thardes.de/raspberry-pi-als-sdr-server/
(Update 2020: hier ein neuer Link zur Beschreibung: https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/raspberry-headless-setup-rtl-sdr)

Weiters habe ich mittels GSM-Netz den Raspberry kalibriert und so die Ungenauigkeit meines Sticks festgestellt: 26 ppm. (vgl. ua. http://www.rtl-sdr.com/how-to-calibrate-rtl-sdr-using-kalibrate-rtl-on-linux/)

Da pymultimonaprs die Messages nicht selbst dekodiert, müssen wir noch multimon-ng installieren:

cd ~
sudo apt-get install cmake
git clone https://github.com/EliasOenal/multimon-ng.git
cd multimon-ng
mkdir build
cd build
cmake ..
make
sudo make install

Installation

Die iGate-Software pymultimonaprs installiere und hole ich von GIT:

cd ~
sudo apt-get install python2.7 python-pkg-resources
git clone https://github.com/asdil12/pymultimonaprs.git
cd pymultimonaprs
sudo python2 setup.py install

Ich erstelle ein Startscript:

sudo cp pymultimonaprs.init /etc/init.d/pymultimonaprs
sudo chmod +x /etc/init.d/pymultimonaprs
sudo update-rc.d pymultimonaprs defaults

Um in das APRS-IS-Netzwerk Pakete zu übertragen, ist ein Passwort erforderlich, das sich aus dem Call ableitet und errechnet werden muss:

cd ~/pymultimonaprs
./keygen.py CALLSIGN
Key for CALLSIGN: 31983

Konfiguration

Nun passe ich die Konfigurationsdatei /etc/pymultimonaprs.json an. Fertig konfiguriert sieht sie so aus:

{
        "callsign": "OE1SCS-10",
        "passcode": "20123",
        "gateway": [
                "aprs.oe2xzr.ampr.at:14580", "44.143.40.90:14580",
                "aprs.oe1.ampr.at:14580", "44.143.10.90:14580",
                "aprs.oe6xrr.at.ampr.org:14580", "44.143.153.50:14580",
                "aprs.oe7xgr.ampr.at:14580", "44.143.168.68:14580",
                "44.225.41.232:14580",
                "44.225.42.181:14580",
                "euro.aprs2.net:14580"],
        "append_callsign": true,
        "source": "rtl",
        "rtl": {
                "freq": 144.800,
                "ppm": 26,
                "gain": 46,
                "offset_tuning": false,
                "device_index": 0
        },
        "alsa": {
                "device": "default"
        },
        "beacon": {
                "lat": 48.19060,
                "lng": 16.38670,
                "table": "/",
                "symbol": "-",
                "comment": "RXonly APRS iGate",
                "status": {
                        "text": "Raspberry Pi mit RTL Stick",
                        "file": false
                },
                "weather": false,
                "send_every": 1800,
                "ambiguity": 1
        }
}

Ich habe für meinen Call OE1SCS den Suffix -10, auch SSID genannt, gewählt, der lt. APRS SSID-Erklärung für „internet, Igates, echolink, winlink, AVRS, APRN, etc“ gedacht ist.

Im Eintrag „gateway“ habe ich eine Liste an APRS-IS Gateways eingetragen. Die Liste wird bei jedem Neustart von pymultimonaprs vom ersten Eintrag neu abgearbeitet. Ich habe also die Gateways, die ich bevorzuge, an den Anfang geschrieben. Die meisten iGates besitzen sprechende DNS-Namen. Ich will jedoch nicht von einem funktionierenden DNS-Dienst abhängig sein, daher trage ich die IP-Adressen ein. Damit dort nicht nur kryptische HAMnet-IP-Adressen (beginnen mit 44.) stehen habe, habe ich in der gleichen Zeile den DNS-Namen zusätzlich hinterlegt, zB.:
„aprs.oe2xzr.ampr.at:14580“, „44.143.40.90:14580“

Der Dienst versucht 120 Sekunden die APRS-iGates zu erreichen. Nach 120 Sekunden meldet er ein Timeout und probiert den nächsten iGate. Sollte das Netzwerk nicht verfügbar sein oder der iGate-Server am eingestellten Port nicht antworten, wartet pymultimonaprs das Timeout nicht ab, sondern probiert unmittelbar den nächsten iGate in der Liste.

Hier ein Beispiel aus meinem Logfile:

Jan  2 10:53:42 roofpi pymultimonaprs: connecting... 44.225.42.181:14580
Jan  2 10:53:42 roofpi pymultimonaprs: Error when connecting to 44.225.42.181:14580: '[Errno 101] Network is unreachable'
Jan  2 10:53:51 roofpi pymultimonaprs: connecting... 78.47.75.201:14580
Jan  2 10:53:51 roofpi pymultimonaprs: connected
Jan  2 10:53:51 roofpi pymultimonaprs: # aprsc 2.0.18-ge7666c5
Jan  2 10:53:51 roofpi pymultimonaprs: login OE1SCS-10 (PyMultimonAPRS 1.2.0)
Jan  2 10:53:51 roofpi pymultimonaprs: # logresp OE1SCS-10 verified, server T2EISBERG
Jan  2 10:53:51 roofpi pymultimonaprs: sending: OE1SCS-10>APRS,TCPIP*:=4811.4 N/01623.2 E-RXonly APRS iGate
Jan  2 10:53:51 roofpi pymultimonaprs: sending: OE1SCS-10>APRS,TCPIP*:>Raspberry Pi mit RTL Stick

Mittels „append_callsign“: true, gebe ich an, dass mein Call in den APRS-Pfad bei der Weiterleitung ans iGates dazugefügt werden soll.

im Abschnitt „rtl“ wähle ich die Frequenz 144.800 MHz als europäische APRS-QRG, gebe meine Ungenauigkeit des Sticks (26 ppm) an, die ich vorher gemessen habe und wähle einen Gain von 46. Offset-Tuning lasse ich unbenutzt und da ich nur einen DVB-T-Stick am Raspberry habe, lasse ich den device-index bei 0.

im Abschnitt „beacon“ konfiguriere ich die eigene, regelmäßige, Aussendung meiner „Station“:

Ich gebe die eigenen GPS-Koordinaten an, wähle als Darstellungssymbol ein Haus, gemäß dieser Tabelle:
http://www.aprs-dl.de/?APRS_Detailwissen:SSID%2BSymbole
Ganz unten bei diesem Link kann man die Symboltabelle als PDF runterladen!

Ich wähle einen statischen Text für „comment“ und „status„, außerdem übertrage ich im Moment keine Wetter-Informationen. Ich möchte, dass meine Aussendung alle 30 Minuten übertragen wird (30 Minuten * 60 Sekunden = 1800 Sekunden).

Um meine Positionen nicht 100%ig genau im APRS darzustellen, habe ich die „ambiguity“ auf „1“ gesetzt. Das verringert die Genauigkeit meiner GPS-Position um 1/10 Grad-Minute. Dadurch wird meine APRS-Position auf aprs.fi mit dem Hinweis „Position ambiguous: Precision reduced at transmitter by 1 digits, position resolution approximately 185.2 m.“ zB. so dargestellt:

aprs-ambiguous
meine Station wird bewusst mit einer Ungenauigkeit von ca. 185 Metern in dem violetten Feld angezeigt. Das Feld weist darauf hin, dass die Position nicht exakt ist.

Damit wäre alles konfiguriert und über das Kommando

/etc/init.d/pymultimonaprs start

habe ich den Dienst gestartet.

Die Funktion kann man über das Logfile /var/log/syslog rasch prüfen. Unmittelbar nach dem ersten Start war meine Station auf aprs.fi sichtbar: http://aprs.fi/info/a/OE1SCS-10

Erfahrungen, Tipps & Tricks

Zuverlässigkeit des USB-Sticks

Ich habe den Dienst einige Tage laufen gelassen. Nach zirka zwei Tagen habe ich folgende Fehlermeldung im Logfile gehabt. Auch über „dmesg“ war das Problem sichtbar:

Dec 30 21:23:34 roofpi kernel: [ 2139.021653] usb 1-1.3: usbfs: usb_submit_urb returned -121
Dec 30 21:23:34 roofpi kernel: [ 2139.022123] usb 1-1.3: usbfs: usb_submit_urb returned -121
Dec 30 21:23:34 roofpi kernel: [ 2139.022580] usb 1-1.3: usbfs: usb_submit_urb returned -121
Dec 30 21:23:34 roofpi kernel: [ 2139.023041] usb 1-1.3: usbfs: usb_submit_urb returned -121
Dec 30 21:23:34 roofpi kernel: [ 2139.023968] usb 1-1.3: USB disconnect, device number 4
Dec 30 21:23:34 roofpi kernel: [ 2139.260292] usb 1-1.3: new high-speed USB device number 6 using dwc_otg
Dec 30 21:23:34 roofpi kernel: [ 2139.372309] usb 1-1.3: New USB device found, idVendor=0bda, idProduct=2832
Dec 30 21:23:34 roofpi kernel: [ 2139.372335] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Dec 30 21:23:34 roofpi kernel: [ 2139.372353] usb 1-1.3: Product: RTL2832U
Dec 30 21:23:34 roofpi kernel: [ 2139.372369] usb 1-1.3: Manufacturer: Generic
Dec 30 21:23:34 roofpi kernel: [ 2139.372386] usb 1-1.3: SerialNumber: 77771111153705700

Es hat sich also der USB-Stick verabschiedet „usb 1-1.3: USB disconnect, device number 4“ und sofort wieder neu verbunden. Damit war natürlich ein Neustart des pymultimonaprs nötig, damit dieses wieder korrekt lauscht. Leider war es damit nicht getan und der Fehler ist wenige Minuten später wieder gekommen. Ich habe das ein paar Mal wiederholt und schon befürchtet, dass der Stick vielleicht kaputt ist. Ein Reboot hat die Situation aber entschärft und nun läuft der Stick wieder seit 2 Tagen stabil.

APRS-Meldungen der ISS

Mit einem einfachen Hack, der unter anderem hier beschrieben wird, soll es möglich sein, neben der primären APRS-Frequenz 144.800 MHz auch die APRS-Frequenz der Raumstation ISS zu empfangen. Diese sendet auf 145.825 MHz. Natürlich können diese Meldungen nur gehört werden, wenn sich die ISS in Reichweite befindet. Es gibt zahlreiche Webseiten im Internet, mit denen der Zeitpunkt der nächsten Überflüge der ISS am eigenen Standorts berechnet werden kann.

Leider hat sich dieser Hack bei mir nicht bewährt: mein Stick schafft es kaum noch APRS-Meldungen zu decoden, wenn er auf beide Frequenzen hört. Die Qualität nimmt rapide ab. Woran es genau liegt, kann ich schwer sagen. Ich habe aber die Vermutung, dass es am Squelch liegt, der bei dieser Konfiguration genutzt werden muss: das Programm rtl_fm, das dem Empfang der Pakete übernimmt, funktioniert ohne Squelch, sofern man nur auf einer QRG hört. Wenn man mehrere QRGs angibt (144.8, 145.825, …) muss ein Squelch-Wert angegeben werden. Ich habe zwar 1 als kleinsten möglichen Wert konfiguriert, vermute aber, dass der Squelch bei APRS-Paketen zu spät reagiert und daher viele Pakete nicht vollständig gehört werden. Sobald ich nur auf 144.8 ohne Squelch höre, empfange ich wieder viel mehr Pakete und alles scheint zu funktionieren.

Ein anderer Benutzer hat ähnliches erlebt: „I was unable to scan both 144.39 and 145.825 and decode the packets reliably.“ (http://www.algissalys.com/amateur-radio/raspberry-pi-sdr-dongle-aprs-igate)

Wetter- & Telemetriedaten übertragen

(Edit: ich habe in einem separaten Artikel hier mittlerweile die Übertragung von Telemetriedaten beschrieben…)

pymultimonaprs kann auch Wetterdaten mitsenden. Ich habe leider keine Wetterstation, möchte aber Telemetriedaten meines Raspberry Pi 2 übermitteln. Dazu kann man ein JSON-File erstellen, das diesem Format entspricht (Quelle: https://github.com/asdil12/pymultimonaprs/blob/master/README.md):

You can set weather to a json-file. eg: "weather": "/path/to/weather.json",

If you don’t want do send weather date, just leave it on false.
This will be read in like the status-file and can look like that:

{
    "timestamp": 1366148418,
    "wind": {
        "speed": 10,
        "direction": 240,
        "gust": 200
    },
    "temperature": 18.5,
    "rain": {
        "rainlast1h": 10,
        "rainlast24h": 20,
        "rainmidnight": 15
    },
    "humidity": 20,
    "pressure": 1013.25
}
  • timestamp is seconds since epoch – must be included
  • wind
    • speed is in km/h
    • direction is in deg
    • gust is in km/h
  • temperature is in °C
  • rain
    • rainlast1h is in mm
    • rainlast24h is in mm
    • rainmidnight is in mm
  • humidity is in %
  • pressure is in hPa

The timestamp must be included – everything else is optional.

Meine Idee wäre, die Temperatur & Spannung des Raspberry Core zu übermitteln, die mittels des Kommandos „vcgencmd“ ermittelt werden können. Details siehe hier: http://elinux.org/RPI_vcgencmd_usage

Ich müsste also ein JSON-File erstellen, in das ich

  • den aktuellen UNIX-Timestamp angebe,
  • bei temperature die Ausgabe von „vcgencmd measure_temp“
pi@roofpi ~ $ vcgencmd measure_temp
temp=27.2'C

Damit übertrage ich zwar nicht die Daten des Wetters, sondern die Temperatur der CPU, aber ich kann das zum Testen mal so machen.

Es würde sich auch anbieten, andere Telemetriedaten mitzusenden, wie zB. die Spannungen der Elemente des Raspberry:

pi@roofpi ~ $ vcgencmd measure_volts core
volt=1.2000V
pi@roofpi ~ $ vcgencmd measure_volts sdram_c
volt=1.2000V
pi@roofpi ~ $ vcgencmd measure_volts sdram_i
volt=1.2000V
pi@roofpi ~ $ vcgencmd measure_volts sdram_p
volt=1.2250V

Für die Spannungen ist kein Feld in den Wetterdaten vorgesehen. Man könnte diese Daten also über die „status„-Aussendung übermitteln. Dazu ändert man im Konfig file (/etc/pymultimonaprs.json) im Bereich „status“ folgendes:

"status": {
 "text": false,
 "file": "/tmp/aprs-status.txt"
 },

In die Datei /tmp/aprs-status.txt schreibt man nun eine Zeile, die man als Status aussenden will, beispielsweise:

Raspberry Pi mit RTL Stick core_temp=27.2'C core_volt=1.2000V sdram_c_volt=1.2000V sdram_i_volt=1.2000V sdram_p_volt=1.2250V

Ideen für weitere Werte, die man aussenden könnte:

  • uptime
  • clock-speeds von core, arm und anderen Modulen im Raspberry
  • uvm…

Ich habe mittlerweile die Übertragung der Telemetriedaten in einem eigenen Artikel beschrieben.