Bau eines Raspberry Pie Echtzeit-GPS-Trackers
Lasst uns ein schickes Gerät bauen, welches Eure aktuelle Position verfolgen und diese Daten in Echtzeit auf Eure Drupal-Seite anzeigen kann.

1. Die Idee
Schon als Kind hatte ich das dringende Bedürfnis nach einem Gerät, das jede meiner Bewegungen verfolgen und jeden wissen lassen kann, wo genau ich bin. Nur ein Scherz - die Idee basiert auf einem realen Anwendungsfall, der mir vor einigen Monaten begegnet ist. Wenn Sie mit der "Basler Fasnacht" vertraut sind, können Sie das vielleicht nachvollziehen. Im Grunde sind wir eine grosse Gruppe von Menschen, die Fasnacht feiern. Ab und zu ziehen wir tagsüber in Formation und wechseln häufig den Standort. Während dieser Zeit des Umzugs ist niemand in der Lage, sein Telefon zu benutzen und andere Freunde über unseren aktuellen Standort zu informieren. Ausserdem neigen die Leute, je später es wird und je mehr "Mineralwasser" wir trinken, dazu, die Gruppe für kurze Zeit zu verlassen oder bestimmte, vorher festgelegte Zeiten zu verpassen. Wie sollen sie uns nun wiederfinden, wenn ihnen niemand unsere aktuelle Position texten kann? Ja, ich denke, Sie wissen, worauf das hinausläuft....
Lasst uns direkt eintauchen...
2. Geräteeinrichtung und Architektur
Öffne Google und Kreditkarte bereithalten. Lasst uns einkaufen gehen.
2.1 Hardware
Andere Dinge
Für die Ausführung des Linux-Images und unseres Codes benötigen wir eine Micro-SD-Karte. Ich verwende eine 32GB (10) (Kosten: SFR 30.-). Natürlich brauchen wir auch eine SIM-Karte von unserem bevorzugten Anbieter. Good Guys Sunrise hat einen fairen Prepaid-Tarif mit schnellem Internet. Ideal für unsere Bedürfnisse. Die Stromversorgung wird von der Power Bank 'USB Battery Pack 10400mAh - 2 x 5V @ 2A' übernommen (Kosten: SFR 40.-). Für einen knallharten Look habe ich mich entschlossen, auch in ein schickes mattschwarzes Gehäuse zu investieren. (Kosten: SFR 15.-). Bilder: https://www.fust.ch
https://www.pi-shop.ch
2.1 Schnittstellen und Protokolle
Bevor wir mit der Konfiguration beginnen, müssen wir uns vergewissern, über welche Schnittstellen die Teile miteinander verbunden sind: Das GSM-Modul wird über den 40 Pin GPIO (General Purpose Input Output) direkt am Pie angeschlossen. Damit ist es automatisch mit dem Serial UART Rx/Tx verbunden, über den man mit dem Modul direkt über den Hayes-Befehlssatz (AT-Befehle) kommunizieren kann. Wir werden diese Befehle am Ende nicht verwenden, aber sie sind sehr hilfreich zum Testen und Debuggen von Funktionalitäten (z.B. Show connected ports, send/receive sms, show signal strength, general behaviour). Das GSM verwendet die Stromversorgung vom Pie und wird (wenn richtig konfiguriert) automatisch starten, wenn der Pie gestartet wird. Als serielle Schnittstelle wird standardmässig '/dev/ttyS0' (für Raspberry Pie 3) verwendet.
Der GPS Stick wird in einen der USB Slots des Pie eingesteckt. Der Stick verwendet den Port '/dev/ttyACM0' für die Kommunikation mit dem Pie.
Die Verbindung zum Internet wird über die SIM-Karte mittels des PPP-Protokolls hergestellt. Das Gerät ist nun im Grunde ein grosses, fettes Handy ohne Display und Tastatur.
3. Raspberry Pie-Konfiguration
Es sind grundsätzlich 6 Schritte zu beachten:
Einrichten des Betriebssystems auf dem Raspberry
Das GSM-Modul zum Laufen bringen
Das GPS zum Laufen bringen
Internetverbindung bereitstellen
Implementieren eines Service Workers zum Sammeln und Senden von Koordinaten
Ausführen des Skripts beim Start
3.1 Das Pie-Betriebssystem
Wir verwenden das spezielle Image 'RaspiBrick-Firmware', welches eine erweiterte Version des gängigen Raspian OS für Raspberry Pies ist, unter Verwendung der praktischen 'NOOBS'-Installation (einfacher Betriebssystem-Installer).
RaspiBrick: http://www.aplu.ch/home/raspibrick_inst.html
NOOBS: https://www.raspberrypi.org/downloads/noobs/
In diesem Bild sind die meisten wichtigsten Software bereits vorinstalliert und der Einrichtungsprozess ist gut dokumentiert und erklärt. Es enthält auch fast alle Python-Bibliotheken, die wir zum Schreiben und Ausführen unserer benutzerdefinierten Skripte benötigen.
3.2 GSM-Konfiguration
Das GSM-Modul sollte automatisch booten. Um seine Funktionalität zu testen, können wir AT-Befehle über die serielle Schnittstelle mit minicom verwenden. Der folgende Befehl startet das minicom mit einer bestimmten Baudrate auf der ttyS0-Schnittstelle:
$ ssh pi@192.168.0.129
$ sudo minicom −b 9600 −D /dev/ttyS0 −o
Dann können alle möglichen Dinge getestet werden, z.B.:
// send SMS to +41791234567
AT+CMGF=1
OK
AT+CMGS="+41791234567"
> This is the text message.
+CMGS: 198
OK
// location lat lng calculated from nearest CELL TOWERS
AT+CIPGSMLOC=1,1
+CIPGSMLOC: 0,7.584216,47.546936,2017/11/25,14:48:49
OK
// get IP of some website
AT+CDNSGIP="www.google.com"
OK
+CDNSGIP: 1,"www.google.com","172.217.17.100"
3.3 GPS-Konfiguration
Ich habe versucht, den aktuellen Standort durch Triangulation über die GPRS-Signalstärken mit den Standorten der umliegenden Mobilfunkmasten zu berechnen. Leider waren die Ergebnisse dieser Berechnungen sehr ungenau (+- 50m). Daher entschied ich mich, einen zusätzlichen GPS-Empfänger zu kaufen, um genauere Ergebnisse zu erhalten.
Um die GPS-Pakete für die Anwendung verfügbar zu machen, sind die folgenden Schritte erforderlich:
Den Stick einstecken.
GPS Deamon und Python-Integration installieren
$ sudo apt−get install gpsd gpsd−clients python−gps
$ sudo nano /etc/default/gpsd
Dann sollte geprüft werden, ob die folgenden Konfigurationen eingestellt sind:
# FILE gpsd
# Start the gpsd daemon automatically at boot time
START_DAEMON="true"
# Use USB hotplugging to add new USB devices automatically to the daemon
USBAUTO="true"
# Devices gpsd should collect to at boot time.
DEVICES="/dev/ttyACM0"
# Other options you want to pass to gpsd
GPSD_OPTIONS="−n"
GPSD_SOCKET="/var/run/gpsd.sock"
Um zu testen, ob der GPS-Deamon funktioniert, geben Sie
$ cgps
//or
$ gpsmon
3.4 Internet-Konfiguration
Um unsere Koordinaten in die Cloud zu bekommen, müssen wir die PPP-Verbindung einrichten.
Holt die Bibliotheken und
erstellt die Weboberfläche
Sicherstellen, dass die Konfiguration richtig eingestellt ist
Netzwerkschnittstellen bearbeiten, indem Sie die neue ppp-Schnittstelle hinzufügen
$ sudo apt−get install ppp screen elinks
$ cd /etc/ppp/peers/ && nano rnet
# FILE rnet
# ’internet’ is the apn for sunrise connection
connect "/usr/sbin/chat −v −f /etc/chatscripts/gprs −T internet"
# communication port:
/dev/ttyS0
# baudrate
9600
# Assumes that your IP address is allocated dynamically by the ISP.
noipdefault
# Try to get the name server addresses from the ISP.
usepeerdns
# Use this connection as the default route to the internet .
defaultroute
# Makes PPPD "dial again" when the connection is lost.
persist
# Do not ask the remote to authenticate.
noauth
# FILE /etc/network/interfaces
auto rnet
iface rnet inet ppp
provider rnet
Wir können nun das PPP-Protokoll verwenden, um uns mit dem Internet zu verbinden. Ein Kinderspiel!
3.5 Python Service Worker
Fangen wir an zu programmieren! Das Wichtigste, was der Worker erledigen muss, ist die Weiterleitung der vom GPS Deamon empfangenen Daten an die Cloud-Datenbank. Das einfache Skript baut auf demjenigen auf, das auf https://gist.github.com/wolfg1969/4653340 zu finden ist. Ich habe lediglich die PubNub-Bibliothek hinzugefügt und einige Änderungen an der Laufzeit Logik vorgenommen. Der Worker sendet alle 15 Sekunden Daten. Hier ist ein kleiner Ausschnitt aus dem Code:
...
# Import PubNub Library and Settings
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub
from pubnub.exceptions import PubNubException
pnconfig = PNConfiguration()
pnconfig.subscribe_key = "sub-key"
pnconfig.publish_key = "pub-key"
pnconfig.ssl = False
pnchannel = 'map-channel'
...
pubnub = PubNub(pnconfig)
pubnub.subscribe().channels(pnchannel).execute()
while True:
# GET GPS DATA
gpsData['lat'] = gpsd.fix.latitude
gpsData['lan'] = gpsd.fix.longitude
gpsData['time'] = gpsd.utc, ' + ', gpsd.fix.time
gpsData['alt'] = gpsd.fix.altitude
gpsData['eps'] = gpsd.fix.eps
gpsData['epx'] = gpsd.fix.epx
gpsData['epv'] = gpsd.fix.epv
gpsData['ept'] = gpsd.fix.ept
gpsData['speed'] = gpsd.fix.ept
gpsData['climb'] = gpsd.fix.speed
gpsData['track'] = gpsd.fix.climb
gpsData['mode'] = gpsd.fix.track
gpsData['sats'] = gpsd.fix.mode
trigger = float(gpsData['lat'])
if math.isnan(trigger):
data = {'lat': 0,'lng': 0}
else:
data = {'lat': gpsData['lat'],'lng': gpsData['lan']}
try:
envelope = pubnub.publish().channel(pnchannel).message(data).sync()
print("publish timetoken: %d" % envelope.result.timetoken)
except PubNubException as e:
print("Error %s" % str(e))
time.sleep(15)
...
3.6 Lauf bei Start
Fast fertig! Der letzte Schritt ist die Ausführung des Workers beim Gerätestart. Dazu rufen wir einfach unser Skript innerhalb der Pies-Profilkonfiguration auf. Auf diese Weise können wir, falls das Skript abstürzt, einfach das Gerät neu starten und das Skript wird wieder ausgeführt. Fügen Sie die folgenden Zeilen in das Profil ein:
$ sudo nano /etc/ profile
# ’/home/pi/myscript.py’ is the path to your script .
sudo python /home/pi/myscript.py
4. PubNub-Datenbank
Für die Speicherung und Übermittlung der Daten verwende ich die PubNub Real Time Database. Deren 'Free Plan' erlaubt uns die Nutzung von bis zu 100 Geräten und 1M Nachrichten pro Monat, was für dieses Projekt mehr als ausreichend ist. Nach der Registrierung melden wir uns an und erstellen eine neue Projekt-App. Sie stellen uns sofort die beiden wichtigen Schlüssel zur Verfügung - den "Publish Key" und den "Subscribe Key". Diese werden als Anmeldeinformationen verwendet, wenn wir Nachrichten unserer App pushen oder abhören wollen. Innerhalb der App können wir mehrere Kanäle haben, auf denen wir veröffentlichen und/oder abonnieren können. PubNub bietet, neben einer sehr schönen Dokumentation, viele grundlegende Beispiele, die Ihnen helfen zu verstehen, wie alles funktioniert. PubNub kümmert sich nicht darum, welche Art von JSON-Daten Sie veröffentlichen. Für unsere App sind es Breiten- und Längengradkoordinaten.
Anwendungen, die einen Kanal abonniert haben, erhalten automatisch Updates/werden ausgelöst, wenn neue Nachrichten in denselben Kanal gepusht werden. Das ist sehr praktisch, da wir uns nicht um Echtzeit Aspekte kümmern müssen. Alles wird automatisch für uns erledigt.
5. Drupal-Integration
Lassen Sie uns den benutzerdefinierten Block namens tracking_map erstellen. Zuerst müssen wir die Bibliotheken, die wir verwenden werden, in tracking_map.libraries.yml defin
# tracking_map.libraries.yml
google.maps:
version: 3
js:
https://maps.googleapis.com/maps/api/js?key=[yourkey]: { type: external, minified: true }
pubnub:
js:
js/pubnub.min.js: {}
custom_map:
version: 1.0
js:
js/tracking_map.js: {}
dependencies:
- core/jquery
- core/drupal
- tracking_map/google.maps
- tracking_map/pubnub
Wir stellen eine benutzerdefinierte Vorlage tracking_map.html.twig bereit, die nur das Div enthält, auf das die Google Map-Zeichnung abzielt.
<div id="tracking−map"></div>
Da wir den kostenlosen PubNub-Plan verwenden, sind wir auf 100 verbundene Geräte pro Tag beschränkt. Jeder Seitenaufruf wird als ein Gerät gezählt, auch wenn es sich um dasselbe Gerät handelt. Daher müssen wir eine eindeutige ID entlang der PubNub-Anmeldeinformationen übergeben, um Geräte zu identifizieren. Meine Website ist 'login-only', also ist die Drupal USER ID perfekt für dieses Szenario. Auf diese Weise kann die Seite mehrfach auf demselben Gerät geladen werden und es wird nur als ein Aufruf gezählt. Damit das funktioniert, holen wir uns die ID in einer Modul-Preprocess-Funktion und übergeben sie direkt als Variable an das Javascript.
// inside tracking_map.module
function tracking_map_preprocess_tracking_map(&$attachments) {
/** @var \Drupal\user\Entity\User $user */
$user = \Drupal::currentUser();
$userID = $user->id();
$attachments['#attached']['drupalSettings']['uuidpubnub'] = 'pubnubuuid' . $userID;
}
Die letzte wichtige Sache, die zu tun ist, ist das Schreiben des einfachen Javascript-Controllers, der die Funktionalität der Tracking-Karte orchestrieren wird. Das Skript muss sich mit PubNub verbinden, die aktuellen Koordinaten abrufen und sie auf der Karte zeichnen. Hier sind die wichtigsten Teile der tracking_map.js, um die PuBNub-Integration zu zeigen.
//snippet from tracking_map.js
...
var pnChannel = "map-channel";
var pubnub = new PubNub({
publishKey : 'pub-key',
subscribeKey : 'sub-key',
uuid: drupalsettings.uuidpubnub
});
var redraw = function(payload) {
lat = payload.message.lat;
lng = payload.message.lng;
map.setCenter({lat:lat, lng:lng, alt:0});
marker.setVisible(true);
marker.setPosition({lat:lat, lng:lng, alt:0});
lineCoordinatesPath.setMap(null);
if (cordinates.length > 20) {
cordinates.shift();
}
cordinates.push({lat: lat, lng: lng});
lineCoordinatesPath.setPath(cordinates);
lineCoordinatesPath.setMap(map);
};
pubnub.subscribe({channels: [pnChannel]});
pubnub.addListener({message:redraw});
...
Als letztes fügen Sie den Block im Blocklayout ein und platzieren ihn auf den gewünschten Seiten.
6. Seht es in Aktion
Nehmt den Pie in Betrieb, indem es an die Stromquelle angeschlossen wird. Der GPS-Stick beginnt sofort, nach Satelliten zu suchen. Startet das GSM-Modul, indem dessen Startknopf für zwei Sekunden gedrückt wird. Ein langsam rot blinkendes Licht am GSM-Modul zeigt an, dass die Verbindung zum Mobilfunknetz hergestellt ist. Sobald der Satellitenfix hergestellt ist, werden die Koordinaten über PubNub in die Kartenvisualisierung übertragen.
Im Grossen und Ganzen arbeitet das Gerät wie vorgesehen. Natürlich gibt es viele Dinge, die verbessert werden können, aber für den Proof of Concept funktioniert es wirklich gut. Ich habe vorher noch nie mit einem Raspberry Pie gearbeitet und war ein totaler Anfänger. Nachdem ich eine Menge Referenzen gelesen und eine Menge Probleme behoben hatte, wurde ich besser und besser. Ich habe eine Menge Zeit damit verbracht, Referenzen, Handbücher und Stackoverflow-Threads vor- und rückwärts zu lesen. Und ich meine wirklich SEHR viel. Am Ende habe ich alles zum Laufen gebracht und ich denke, ich habe mir ein grundlegendes Verständnis dafür angeeignet, wie Dinge innerhalb und ausserhalb eines Raspberry Pie funktionieren. Das war definitiv der zeitaufwendigste Teil. Danach war die Verwendung von PubNub und die Erstellung der Drupal-Integration ein Kinderspiel.
Wenn man darüber nachdenkt, könnte ich dasselbe innerhalb von Sekunden erreichen, indem ich einfach die Whatsapp-Chat-Live-Position aktiviere und sie an einen Freund schicke. Es hätte mich nichts gekostet und ich hätte nicht dieses grosse schwarze Ding mit mir herumtragen müssen. Aber wo bliebe da der Spass, oder?.
About the author
This is Mario
It ain’t over till it’s over!
