home     Inhaltsverzeichnis
erste Version am 29.06.2016
letzte Änderung am 03.07.2016

Raspberry Pi als GPS-Tracker
Seite 2



Erweiterungen

Über die folgenden Änderungs-Ideen wäre noch nachzudenken:
  1. WPA2 aufs WLAN
  2. Serialisieren von set_time und gps-Tracker-Dateinamen-Init
  3. Die Button im WebGUI brauchen noch eine Bestätigungs-Abfrage
  4. Geräte-Verfügbarkeit determiniert Track-schreiben
  5. Mehr try/except-Blöcke
  6. Vielleicht noch eine Art Wardriving-Funktion zufügen


WPA2 aufs WLAN

Das ist schnell gemacht. Einfach die /etc/hostapd/hostapd.conf erweitern um:
wpa=2
wpa_passphrase=superGeheimesPasswort
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
Nach dem nächsten Reboot brauchts dann eine Passwort-Eingabe am Smartphone.

Serialisieren von set_time und gps-Tracker-Dateinamen-Init

Wenn der RasPi mit dem Akku verbunden wird und startet, läuft Datum und Uhrzeit vom letzten Shutdown-Zeitpunkt aus weiter.
Sowohl GPS_set_time.py als auch GPS_tracker.py starten automatisch und quasi zeitgleich.
Weil das Tracker-Script als erstes den Dateinamen der GPX-Datei anhand von Datum+Uhrzeit einstellt, das SetTime-Script dann aber garantiert noch keine Satelliten (und somit auch keine Uhrzeit) sieht, wird die GPX-Datei gemäß der letzten Shutdown-Zeit benannt. Schlimm ist das nicht. Primär muss der Name nur eindeutig sein.
Aber natürlich soll er lieber passend zur Startup-Zeit benannt werden. Somit brauchts hier ein aktives warten auf die aktuelle Zeit.
Bevor Datum und Uhrzeit vom GPS kommen, sind auch keine Positions-Daten verfügbar. Es gehen also keine Daten verloren.
Jedoch braucht es einen Mechanismus, durch den GPS_tracker.py feststellen kann, dass die Systemzeit aktualisiert wurde...und jetzt zur Bestimmung des Dateinamens verwendet werden kann. Eine Environment-Variable wäre denkbar.
Oder die gesamte Funktionalität von GPS_set_time.py wandert einfach in GPS_tracker.py mit rein.
Das spart den Autostart in /etc/rc.local und vor allen Dingen den Sync zwischen den zwei Scripten.

Die Button im WebGUI brauchen noch eine Bestätigungs-Abfrage

Vor dem Einbau der Bestätigungsseite nach einem Button-Klick, wollte ich erstmal diese URL-Erweiterung wie z.B. "?action=Stop+Tracker" wieder loswerden, nachdem sie vom Script erkannt wurde. Eine entsprechende Anfrage auf stackoverflow brachte mich zwar weiter, aber irgendeiner Wurst war meine Anfrage wohl zu trivial - so dass meinem Reputations-Wert dafür (ohne Begründung) zwei Punkte abgezogen wurden.
Die Lösung war, bei jedem Seiten-Refresh wieder auf die Haupt-Seite zu verweisen bzw. umzuleiten.
Allerdings sieht ein Smartphone-Browser die Seite auf einer anderen IP-Adresse, als ein Browser, der über LAN mit dem RasPi verbunden ist.
Folglich muss die IP-Adresse des RasPi für jeden Browser individuell eingetragen werden - abhängig vom Interface, über das der Browser reinkommt.
Das Interface bekomme ich nicht. Aber die IP-Adresse. Und zwar mit cgi.escape(os.environ["REMOTE_ADDR"]).
Daraus kann dann die IP-Adresse des Browsers abgeleitet werden. Konkret sieht die Änderung so aus, dass die Zeile
print('<meta http-equiv="refresh" content="5">')
nach
print('<meta http-equiv="refresh" content="5;url=http://%s/cgi-bin/status.py3">'%(data["server IP"],))
geändert wird.
Und um Bestätigungs-Seiten für Button-Klicks anzeigen zu können, wandert die Erkennung von Button-Klicks vor die Ausgabe der HTML-Seiten.
Je nach Button-Klick kann nun eine andere Seite ausgegeben werden.
Nach der Rückkehr aus der Bestätigungs-Seite wird die Funktion dann ausgeführt .... oder auch nicht, wenn der Abbruch-Button gewählt wurde.
Weiterhin habe ich in dem neuen status.py3 die Haupt-Seite mit tabellarischer Anzeige und Nutzung von Status-Icons etwas angehübscht:

Screenshot   Screenshot   Screenshot   Screenshot

Geräte-Verfügbarkeit determiniert Track-schreiben

Das einzig relevante Gerät wäre diesbezüglich eigentlich nur der USB-Stick, weil der Track ja jetzt schon nur dann geschrieben wird, wenn die vom GPS-Modul gemeldete Position und Uhrzeit valide ist. Und das wird nicht der Fall sein, wenn das GPS-Modul ein -wie auch immer geartetes- Problem hat.
Das der USB-Stick im laufenden Betrieb gezogen wird, ist eher unwahrscheinlich ... bzw. wäre grober Unfug, der dann auch gerne zu einem Programm-Fehler führen dürfte. Also muss das höchstens zu Beginn des Scripts geprüft werden.
Aber was soll dann passieren?
Am Smartphone wird es schließlich schon jetzt gemeldet.
Das Script könnte stattdessen auf SD-Karte schreiben. Also etwa ins Home-Verzeichnis.
Damit wäre dann der Fall abgefangen, dass man eine Tour aufzeichnen möchte, deswegen den RasPi mit dem Akku verbindet, aber vergessen hat, den USB-Stick reinzustecken und vor Tour-Antritt dann auch noch zusätzlich nicht den Tracker-Status am Smartphone überprüft. Ist zwar unwahrscheinlich, aber es sollten nur ein paar zusätzliche Programm-Zeilen nötig sein, um das abzufangen bzw. zu implementieren.

Mehr try/except-Blöcke

Jaaa .... das kann natürlich nie schaden. Aber im except-Fall muss man dann ja auch was sinnvolles machen.
Das status.py3 zur WebSeiten-Aufbereitung braucht es eher nicht, weil das ohnehin alle fünf Sekunden von lighttpd neu gestartet wird.
Aber GPS_tracker.py soll nicht mittendrin abbrechen und dann damit quasi den gesamten (bisher geschriebenen) Track mehr oder weniger nutzlos machen. Die schließenden XML-Tags könnte man noch von Hand dranhängen...aber was will man mit einem halben Track.
Ideal wäre es, wenn man dem Smartphone per WLAN (oder BlueTooth) ein Alert-Meldung schicken könnte - und zwar vor allen Dingen auch dann, wenn der WebBrowser gerade nicht die Status-Seite anzeigt. Aber zumindest über den sollte der RasPi akustische Meldungen von sich geben können. Das muss ich demnächst mal recherchieren.
Noch sicherer wäre es, den RasPi selbst mit einem Piezo-Beeper auszustatten, über den dieser dann ggf. seinen Unmut äußern könnte.
Oder erstmal dem Browser mit geöffneter Status-Seite beibringen, sich bemerkbar zu machen - auch wenn er nicht im Vordergrund läuft.
Will heißen: akustisch. Das geht mittlerweile einfach per html-Tag, hier gefunden. Und einen schön fiesen Sound habe ich hier gefunden.
Es hat fast auf Anhieb funktioniert, dass bei jedem Seiten-Refresh ein Ton kommt, wenn ein Gerät, Dienst oder Programm nicht [richtig] läuft oder weniger als drei Satelliten genutzt werden können. Konkret mit diesen zwei Zeilen im HTML-Header (vom Setzen von "warn" mal abgesehen):
if warn:
  print('<audio src="i-am-being-serious.mp3" autoplay></audio>')
Aber dann....das blöde Smartphone dreht dem Browser offenbar das Audio ab, wenn er nicht im Vordergrund läuft.
Nützt also rein gar nix - nervt höchstens. Bei drei [getesteten] Browsern das Gleiche.
Das wird wohl eine unverschämte Bevormundung von diesem unsäglichen Android sein.

Vielleicht noch eine Art Wardriving-Funktion zufügen

Hier wäre erstmal zu prüfen, ob das eingebaute WLAN-Interface sowohl Access-Point als auch gleichzeitig Client sein kann.
Ansonsten müsste der USB-WLAN-Stick wieder zum Einsatz kommen.
Cool wäre es schon, wenn man parallel zum Track auch noch sehen könnte, wo (speziell offene) WLANs verfügbar sind.
Damit werde ich mich befassen, wenn alles andere rund läuft.


Tests zur Genauigkeit

Eben habe ich ca. 70 Minuten lang einen Track schreiben lassen, bei dem das GPS-Modul nicht bewegt wurde.
Auf wegeundpunkte.de kommt folgendes (begrenzt erfreuliches) Bild dabei raus:
Screenshot
In der gpx-Datei sind 852 Track-Punkte enthalten.
Wenn ich deren jeweiligen Abstand zur Position (54.805109, 9.524913) mit einem Script bestimmen lasse, kommen folgende Abweichungs-Häufungen raus:
    0,42m bei 181 Punkten
    6,74m bei 192 Punkten
    9,06m bei 104 Punkten
und auch
    22,31m bei einem Punkt
Insgesamt 47 unterschiedliche Positionen.
Der durchschnittliche Abstand zu (54.805109, 9.524913) beträgt 6,87m.
Nicht sehr viel anders bei der Verteilung sieht es aus, wenn ich die Koordinate mit den 192 Punkten als Referenz/Basis nehme.

Na gut, die gewählte Position hier am Kellerfenster ist zum Empfang eines GPS-Signals nicht gerade ideal.
Wenn der Regen vorbei ist, werde ich den Test wiederholen und das GPS-Modul mitten in den Garten legen.
Damit hat das Ding dann einen sehr viel größeren Winkel zum freien Himmel.

Wegen des Dauer-Regens habe ich das GPS-Modul jetzt im Zimmer von Sohnemann bei einem der Dachfenster unter das runter gezogene Rollo geklemmt.
Die Anzahl der genutzten Satelliten liegt jetzt mindestens bei 7, meistens bei 8, manchmal sogar bei 10.
Eine gute Stunde später sieht der auf wegeundpunkte.de hochgeladene Track so aus:
Screenshot
Und mein Analyse-Script meldet 784 Punkte mit genau einer Abweichungs-Häufung:
    7,67m bei 784 Punkten
Genau so will ich das sehen.
Lasse ich mir die Koordinate (54.805055000, 9.524838333) von google-maps auf dem Satellitenbild anzeigen, dann liegt die angezeigte Position ca. 3m nördlicher und 6m westlicher, als die von dem Fenster, an dem das GPS-Modul lag.
Wäre mal interessant zu wissen, ob das nun der normale GPS-Fehler ist, am GPS-Modul oder an einem verschobenen Satellitenbild bei google liegt.

BTW: ich fände es albern, hier sämtliche GPS-Koordinaten aus-zu-X'en oder mitten in den Atlantik zu legen, weil sich meine Adresse ja ohnehin problemlos im Impressum finden ließe.


Zweiter outdoor-Test

Eben habe ich meinen zweiten Test außer Haus gemacht. Diesmal etwas länger und gleichzeitig mit etwas Sinnvollem verbunden.
Der Track war nun lang genug, um ihn auf GPSies hochladen und als öffentlich markieren zu können.
Offenbar verändert GPSies jedoch die Koordinaten und die Zeiten im Track.
Laut meinem Track bin ich von 08:19:20Z bis 09:04:18Z gefahren. Also etwa 45 Minuten.
Der Track auf GPSies hat das Datum 01.01.2010 und geht von 00:00:00Z bis 01:36:47Z. Das soll wohl so eine Art Privacy-Feature sein...
Das Datum ist mir egal. Aber die reale Zeit will ich eigentlich schon haben. Und die Geschwindigkeit.

Die gibt es z.B. über diesen GPX Track Report Generator. Der liefert u.a. ein Speed-Profile zur Zeit und zur Distanz.

Aber ich will das lieber selber machen.
Eigentlich könnte das der RasPi auch gleich direkt berechnen und in den Track mit rein schreiben.
Lässt man OSMand eine Route mitschreiben, kommt da zwischen <trkpt ....> und </trkpt> sowas vor:
<extensions>
  <speed>6.503000736236572</speed>
</extensions>
Das scheint die Geschwindigkeit in Meter pro Sekunde zu sein.
Ich will aber eigentlich lieber direkt lesbare Kilometer pro Stunde da drin haben.
Es sollte ja wohl Standard-konform sein, wenn ich ein eigenes Tag <speedkmh> dafür verwende.
Mal schauen.... hier erstmal ein Einstiegspunkt. Hier dann offenbar der Standard.
Und laut dem darf ich das unter <extensions> durchaus machen.

Die Funktion zur Bestimmung der Distanz zwischen zwei Punkten habe ich von hier. Die liefert die Distanz in Kilometer.
Dann muss ich nur noch die zwei zugehörigen Zeiten in je ein datetime-Objekt umwandeln.
Anschließend die jüngere Zeit von der älteren Zeit abziehen und nach Stunde umrechnen.
Damit kann ich dann ab dem zweiten Track-Punkt zusätzlich eine Geschwindigkeit eintragen.

Als erstes habe ich ein Script fürs Post-Processing zusammengepfuscht, das die Zeilen mit Track-Punkten etwas verlängert. Sieht danach so aus:
<trkpt lat="54.802680000" lon="9.531146667"><time>2016-07-02T08:22:05.000Z</time><extensions><speedkmh>026.838</speedkmh></extensions></trkpt>
<trkpt lat="54.802588333" lon="9.531841667"><time>2016-07-02T08:22:10.000Z</time><extensions><speedkmh>032.901</speedkmh></extensions></trkpt>

Auf allen drei hier bisher verlinkten Seiten zur GPX-Track-Verarbeitung wird eine derart aufgebaute GPX-Datei angenommen und korrekt verarbeitet.
Dann werde ich das nachher mal in GPS_tracker.py einbauen.

Nun ist es eingebaut und zusätzlich zur Geschwindigkeit wird auch noch die Anzahl der genutzten Satelliten zum Track-Punkt abgelegt.
Anbei die neusten Versionen von GPS_tracker.py und status.py3.

Die Fortsetzung folgt auf Seite 3.