Vorbemerkung
Der ursprüngliche Artikel stammte vom 1. August 2015, etwas weniger als ein Jahr später hat sich die Sache allerdings weiterentwickelt, daher habe ich den Artikel umdatiert und neu veröffentlicht. Das Wichtigste zuerst: Die Sache funktioniert, sauber sicher und stabil. Der ganze nachfolgend erträumte Funktionsumfang ist noch nicht erreicht, aber daran kann man ja noch arbeiten.
Vision
Wir alle bewgen uns viel durch die Welt, häufig nicht alleine. Und Karten sind ein fantastisches Medium, um solche Bewegungen auf einer sphärischen Fläche festzuhalten und darzustellen. Zwei interessante Fragen/Problemstellungen/Aufgaben tauchen dabei häufiger auf:
- Wo bin ich überall schon mal gewesen?
- Wo bin ich jetzt grade, wohin bin ich unterwegs, wie bewege ich mich fort und wann komme ich an? (Insbesondere, wenn man sich mit jemandem treffen möchte)
- (Spielen! Jedes Mal, wenn ich über diesen Komplex nachdenke, drängt sich der Gedanke auf, dass man daraus ein fantastisches (Gelände-/Real-)Spiel basteln könnte, etwas in der Art einer Schnitzeljagd oder Geocaching in Verwandschaft zu Scotland Yard oder Mister X, vielleicht sogar mit Carmen Sandiego. Auch Deutschlandreise oder Globetrotter kommen einem in den Sinn. Große Metropolregionen wie das Ruhrgebiet, in dem ich wohne, bieten sich dafür natürlich an, aber auch im Rahmen einer Jugendfreizeit ließe sich das sicher gut nutzen. Siedler- oder andere Segelspiele haben wir ja schonmal auch ganz offline hinbekommen. Andere haben sowas auch schon gemacht: z.B. auf dem 31C3 und vorher wurde in der Freakshow davon berichtet. Ingress trifft einen ähnlichen Nerv)
Ziel wäre also, die Position von mehreren Leuten zu erfassen, verfolgen, aufzuzeichnen und (auch im Verlauf, also als Spur) darzustellen, eventuell in Beziehung zu setzen mit einander oder anderen Daten (Wetter, Verkehr, ÖPNV), zusätzlich noch Ziel/Zwischenziele, Route, Verkehrsmittel, Voraussichtliche Ankunftszeit, passende Wikipedia-Artikel etc.
Das würde erstmal die Grundanforderungen abdecken, sich mit anderen Menschen besser absprechen zu können und auch im Nachhinein sehen zu können, wo man war.
Wenn es dann noch zusätzlich Berechtigungs-Einschränkungen gäbe (alle senden ihre Position, aber nicht jeder kann immer die Positionen aller anderen einsehen), käme man der Spiel-Nutzung näher.
Möglichkeiten
Es gab mal einen Dienst namens Google Latitude, der ungefähr in die Richtung ging, er ist mittlerweile in Google+/Maps (Timeline) aufgegangen, in Facebook, FourSquare/Swarm, Apples Find My Friends oder waze finden sich ähnliche Ansätze. Sehr nah an meine Vorstellung der Umsetzung kommt Glympse, gegenüber den anderen genannten Diensten benötigt man zum Angucken kein Konto und die Freigabe ist zeitlich beschränkt.
Aber einen Nachteil haben sie alle: Sie sind ein großer Eingriff in die Privatsphäre, man gibt Kontrolle ab, man muss (überwiegend sehr großen) Firmen trauen, die im Ausland und damit anderen Jurisdiktionen sitzen, von denen man abhängig und denen man ausgeliefert ist. Kurz: Sie sind nicht offen, noch frei.
Also sind sie keine echte Option. Ein paar gäbe es da aber schon schon: OsMo/OsmAnd, Userhash Location Reporting, Gps Cell Phone Tracker, Trackserver. Es gibt auch eine schöne Übersicht von Diensten mit Vergleich. So recht schien mir aber keins davon zu passen. Zwischenzeitlich trug ich mich mit dem Gedanken, selbst was auf reiner Browser/Javascript-Basis zu entwickeln, was eventuell mit einem NodeJS-Server spricht: Sehr viel Aufwand, aber wäre ein Anlass zum Lernen.
Ansatz
Doch in dem Vergleich wird OwnTracks erwähnt (nicht zu verwechseln mit owntrack, dessen Idee ähnlich, Umsetzung aber nicht so nachhaltig zu sein scheint), dazu gibt es auch einen Artikel bei Cashy und einen von nullniveau. (Und noch ein paar hier und dort). Das scheint mir eine Lösung voll nach meinem Geschmack. OwnTracks selbst ist eine OpenSource-App (sowohl für iOS als auch für Android), die die Position ermittelt und per MQTT (Message Queue Telemetry Transport), einem offenen Publish-/Subscribe-Protokoll für die dezentrale Übermittlung kleiner Nachrichten wie Sensor-Messdaten über Verbindungen, die auch schonmal aussetzen können, verteilt. Passt also sehr gut, hat auch den aparten Vorteil, dass die Server-Seite unabhängig von dem Geo-Thema ist und in der Heimautomatisierungsszene (s. openHAB) Zuspruch findet, man ist also da nicht allzusehr in der Nische und läuft Gefahr, dass man sich übernimmt oder die Weiterentwicklung eingestellt wird. Es gibt einen Open Source-MQTT Message Broker (=Server) namens Mosquitto, der auch von den OwnTracks-Machern unterstützt und empfohlen wird.
Einziger Wermutstropfen: OwnTracks ist zwar OpenSource, aber (noch) nicht im F-Droid-Repository zu finden, da es auf die proprietären Google Play Services zur Ortung zurückgreift. Kein Problem, das man nicht lösen könnte! 😉 (Allerdings ist die dafür notwendige Implementierung von Geofencing in LOST zur Zeit eingeschlafen.)
Die OwnTracks-App sendet und empfängt die Positionen und zeigt sie auf einer Karte an.
Der MQTT-Broker verteilt nur die Positions-Nachrichten aber zeichnet sie nicht auf, dazu gibt es mittlerweile ot-recorder (zuvor gab es schon das m2s-Backend bzw. auch mit Darstellung im Web den Nachfolger Pista. Um die Vision zu Erreichen, wäre außerdem der Einbau einer Authentifikation noch wichtig.
Mosquitto möchte ich gerne nicht auf einem Raspberry Pi installieren wie in der OwnTracks-Doku und allen anderen Anleitungen, die ich finden konnte, sondern in meinem Uberspace. Denn ich möchte die Position ja von Unterwegs aufzeichnen und einsehen, und ich möchte mein Netzwerk zuhause nicht nach Außen aufmachen. Das ist insofern problematisch, als die Anleitungen alle vom praktischen Weg „sudo apt-get“ ausgehen, der im uberspace logischerweise nicht funktioniert (keine sudo-Berechtigung). Also bleibt nur die andere Möglichkeit: Selbst kompilieren.
Umsetzung
Genug der langen Vorrede, werden wir etwas konkreter und kommen zur Umsetzung: Den Mosquitto-Broker im Uberspace kompilieren und starten.
Eine der Anleitungen beinhaltet das Kompilieren, aber als root, von der bin ich ausgegangen und habe sie dann ein wenig angepasst, um der User-Umgebung Rechnung zu tragen. Außerdem werden jetzt in der zweiten Version des Artikels direkt von Anfang an Websockets mit aktiviert und in der Konfiguration TLS verwendet.
Los geht’s:
Websockets
Geholfen haben mir zwei Artikel.
libwebsockets 1.6 ist die letzte explizit von mosquitto erwähnte Version und danach haben sich ABI-Changes ereignet, also nehmen wir die und kompilieren/installieren sie:
mkdir -p ~/projekte/mosquitto cd ~/projekte/mosquitto wget https://github.com/warmcat/libwebsockets/archive/v1.6.3.tar.gz tar xfv v1.6.3.tar.gz cd libwebsockets-1.6.3/ mkdir build cd build cmake .. make
Damit wird heruntergeladen, ausgepackt, das buildscript erzeugt und dann ausgeführt. Danach liegen in lib/ die nötigen libraries, die man nach ~/lib kopieren kann:
cp lib/* ~/lib/
Jetzt geht es weiter mit mosquitto selbst.
Mosquitto
mkdir -p ~/projekte/mosquitto cd ~/projekte/mosquitto wget http://mosquitto.org/files/source/mosquitto-1.4.9.tar.gz tar xvf mosquitto-1.4.9.tar.gz cd mosquitto-1.4.9 nano config.mk
Nun muss die config.mk angepasst werden, um die Websockets-Bibliothek erreichbar zu machen und zu linken
Also Folgendes jeweils an den richtigen Stellen in der Datei ändern:
WITH_WEBSOCKETS:=yes
BROKER_LIBS:=$(BROKER_LIBS) -L$(HOME)/lib -lwebsockets
prefix=${HOME}
Dann ändern, speichern und verlassen.
Es werden außerdem noch zwei header-Dateien gebraucht:
cp ../libwebsockets-1.6.3/lib/libwebsockets.h ./src/ cp ../libwebsockets-1.6.3/build/lws_config.h ./src/
Weiter mit
make all make install
Dabei passiert folgendes: Die Dateien werden kompiliert und unter $HOME/ in entsprechenden Verzeichnissen (~/bin, ~/include, ~/lib, ~/sbin, ~/share) abgelegt, aber am Ende des Kompilierens erscheint der Fehler
install -d /etc/mosquitto install: kann Zugriffsrechte von „/etc/mosquitto“ nicht ändern: Datei oder Verzeichnis nicht gefunden make: *** [install] Fehler 1
Man kann auch erkennen warum: Die Dateien, die eigentlich in /etc/mosquitto landen sollen, berücksichtigen aus unerklärlichen Gründen den Prefix nicht, und auf das systemweite /etc-Verzeichnis haben wir natürlich keinen Zugriff. Ist aber auch nicht weiter schlimm, wir legen einfach eine eigene Konfigurationsdatei an, sie wird gleich editiert:
mkdir ../etc cp mosquitto.conf.example ../etc/mosquitto.conf
TLS
Doch zunächst müssen noch einige Vorbereitungen bezüglich des TLS getroffen werden. Der Server soll unter einer eigenen Domain erreichbar sein und es soll ein Zertifikat von Let’s Encrypt zum Einsatz kommen, das passt gut in die Uberspace-Architektur und wird auf den Mobilgeräten automatisch akzeptiert. Alternativ, insbesondere wenn man keine Domain hat oder dafür nur die normale Uberspace-Domain ($USER.$SERVER.uberspace.de) benutzen möchte, wäre es auch möglich, das Zertifikat selbst zu generieren/signieren (Weiteres dazu unter http://owntracks.org/booklet/features/tls/ und http://mosquitto.org/man/mosquitto-tls-7.html) und das dazu passende CA-Zertifikat auf den Geräten in das System zu importieren oder in der App anzugeben. Das macht die Einrichtung aber unnötig kompliziert und hat z.B. bei Android als Nebeneffekt zur Folge, dass die Bildschirmsperre mindestens per Muster deaktiviert werden muss (was ohnehin eine gute Sache wäre).
Nun also – Im virtuellen User-Webroot wird ein Verzeichnis als Platzhalter angelegt:
mkdir /var/www/virtual/$USER/mqtt.example.com
Es ist sinnvoll, hier eine eigene, sonst nicht benutzte Subdomain zu vergeben, (der Name muss natürlich entsprechend angepasst werden) um das Let’s Encrypt-Zertifikat separat zu verwalten.
Die (Sub-)Domain muss dann im DNS angelegt werden, z.B. bei INWX, was ich nur empfehlen kann. Im Wiki von Uberspace gibt es noch genauere Informationen.
Es muss sichergestellt sein, dass die Server von Let’s Encrypt unter der Domain auch wirklich den Uberspace-Server erreichen, also am besten nochmal von außen probieren, z.B. eine Test-Datei aus dem Platzhalter-Verzeichnis herunterzuladen.
Wenn Let’s Encrypt bisher noch nicht im Einsatz war ist es an der Zeit (den Uberspace-Wiki-Eintrag zu lesen und dann) für
uberspace-letsencrypt
Jetzt, oder falls Let’s Encrypt schon im Einsatz war findet sich unter ~/config/letsencrypt/cli.ini eine Konfigurationsdatei, in der alle Domains eingetragen sind. Die wird nun kopiert, bearbeitet (also alle Domains außer der für Mosquitto entfernt) und zum Erzeugen der Zertifikate benutzt:
cp ~/.config/letsencrypt/cli.ini ~/.config/letsencrypt/cli.ini.mqtt.example.com nano ~/.config/letsencrypt/cli.ini.mqtt.example.com letsencrypt certonly -c ~/.config/letsencrypt/cli.ini.mqtt.example.com
Die Zertifikate werden nun für mosquitto kopiert. Im Prinzip könnten sie auch aus dem .config-Ordner heraus verwendet werden, aber so hat man alles zusammen. Geschmackssache:
cp -H ~/.config/letsencrypt/live/mqtt.example.com/fullchain.pem ~/projekte/mosquitto/ cp -H ~/.config/letsencrypt/live/mqtt.example.com/cert.pem ~/projekte/mosquitto/ cp -H ~/.config/letsencrypt/live/mqtt.example.com/privkey.pem ~/projekte/mosquitto/
Konfiguration
Es sind zwei offene Ports in der Firewall nötig, die bekommt man durch doppeltes Aufrufen von
uberspace-add-port -p tcp --firewall
Die dabei ausgegebenen Ports merken und gleich benutzen, denn jetzt geht es an’s Einstellen in der vorhin angelegten Konfigurations-Datei. Eine Hilfe dabei war ein Artikel:
nano ~/projekte/mosquitto/etc/mosquitto.conf
Hier im Beispiel ist der normale MQTT-Port (Standard 1833/8883) auf 61883 und zusätzlich ein Websockets-Port (Standard 9002) auf 61884 konfiguriert, beide geschützt mit TLS. Aufgelistet sind hier alle Änderungen im Verhältnis zur Standard-Konfiguration. Die müssen in der Datei jeweils an den entsprechenden Stellen vorgenommen werden. Also nicht einfach alles reinkopieren. Außerdem müssen die $HOME-Variablen manuell aufgelöst werden, also stattdessen direkt/home/username hinschreiben.
bind_address mqtt.example.com port 61883 cafile $HOME/projekte/mosquitto/fullchain.pem certfile $HOME/projekte/mosquitto/cert.pem keyfile $HOME/projekte/mosquitto/privkey.pem tls_version tlsv1.2 listener 61884 protocol websockets cafile $HOME/projekte/mosquitto/fullchain.pem certfile $HOME/projekte/mosquitto/cert.pem keyfile $HOME/projekte/mosquitto/privkey.pem tls_version tlsv1.2 log_dest file $HOME/projekte/mosquitto/mosquitto.log log_type error log_type warning log_type notice log_type information log_type all connection_messages true log_timestamp true
Starten und Testen
Es kann fast losgehen, dazu müssen wir aber noch das Verzeichnis, in dem die frisch kompilierte Mosquitto-Bibliothek liegt, in den LD_LIBRARY_PATH aufnehmen, damit beim Ausführen des Binarys gleich auch darin nach ihr gesucht wird:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib/: echo $LD_LIBRARY_PATH
$HOME/lib/ wird an den bisherigen Pfad angehängt und dann wieder in der Umgebungsvariablen gespeichert (der Doppelpunkt ist das Trennzeichen), danach wird sie ausgegeben. Damit das fortan automatisch beim Einloggen geschieht, ergänzen wir die erste Zeile in der .bashrc:
nano ~/.bashrc
Und jetzt braucht man vier Konsolen-Fenster:
1. Der Broker. Hier sollten zum Start ein paar Meldungen erscheinen:
~/sbin/mosquitto -v -c $HOME/projekte/mosquitto/etc/mosquitto.conf
1438439447: mosquitto version 1.4.2 (build date 2015-08-01 09:52:48+0200) starting 1438439447: Config loaded from /home/$USER/mosquitto/etc/mosquitto.conf. 1438439447: Opening ipv4 listen socket on port 61883. 1438439447: Opening ipv6 listen socket on port 61883.
2. Das Log. Auch hier sollten bei den folgenden Aufrufen einige Meldungen erscheinen:
tail ~/projekte/mosquitto/mosquitto.log
3. Der Subscribe-Client. Er sollte beim nächsten Aufruf die gesendete Nachricht anzeigen:
~/bin/mosquitto_sub -h mqtt.example.com -d -v -p 61883 --cafile /etc/pki/tls/certs/ca-bundle.trust.crt --tls-version tlsv1.2 -t owntracks/+/+
4. Der Publish-Client:
~/bin/mosquitto_pub -h mqtt.example.com -d -p 61883 --cafile /etc/pki/tls/certs/ca-bundle.trust.crt --tls-version tlsv1.2 -t owntracks/user/device -m '{"_type":"location","acc":36,"batt":44,"lat":50.00000,"lon":6.000000,"tid":"xy","tst":1465234220}'
Ein uberspace-list-ports -l zeigt außerdem die jetzt offenen Ports mit dem horchenden Mosquitto-Server:
tcp 61883: mosquitto (2395), /home/user/sbin/mosquitto-v-c/home/user/projekte/mosquitto/etc/mosquitto.conf tcp 61884: mosquitto (2395), /home/user/sbin/mosquitto-v-c/home/user/projekte/mosquitto/etc/mosquitto.conf
Als nächsten Schritt kann man jetzt die OwnTracks-App mit dem Broker verbinden. Das sollte sich ebenfalls in den Logs und im Subscribe-Client niederschlagen, außerdem müsste in Luxembug ein User angezeigt werden.
Die Websocket-Verbindung kann man direkt hier testen: http://www.eclipse.org/paho/clients/js/utility/index.html
Oder einen dieser MQTT-Websocket-Clients klonen und konfigurieren:
https://github.com/eclipse/paho.mqtt.javascript.git
https://github.com/jpmens/simple-mqtt-websocket-example
https://github.com/owntracks/contrib
Daemontools
Zur besseren Kontrolle des Brokers übergibt man ihn in die Obhut der deamontools (die zum Testen gestartete Instanz in der „1. Konsole“ muss natürlich vorher per Strg+C beendet werden):
uberspace-setup-svscan mkdir ~/etc/run-mosquitto nano ~/etc/run-mosquitto/run
In dieses Skript kommt nun (den Usernamen ersetzen):
#!/bin/sh export USER=username export HOME=/home/$USER # Include the user-specific profile . $HOME/.bash_profile exec $HOME/sbin/mosquitto -v -c $HOME/projekte/mosquitto/etc/mosquitto.conf 2>&1
Zum Abschluss wird das Skript ausführbar gemacht, aktiviert und der Daemon gestartet:
chmod +x ~/etc/run-mosquitto/run ln -s ~/etc/run-mosquitto ~/service/mosquitto svc -u ~/service/mosquitto
Ein abschließendes
ps fuxwww
sollte nun den Mosquitto-Superviser und den eigentlichen Broker zeigen.
Das war’s, alles geht! 🙂
Achtung, mit dieser Konfiguration gestattet der Broker alle Verbindungen und Subscriptions! Eine ACL würde Abhilfe schaffen…
Bliebe noch, den ot-recorder und ein
-Backend einzurichten. Mal schauen, wann das kommt…Update: ot-recorder
Der ot-recorder klappt auch, wegen der Nachfrage in den Kommentaren hier noch ein kleiner Hinweis dazu. Ist leider aus Zeitmangel nicht ganz so ausführlich, aber besser wie nix:
Ich habe Version 0.6.5 vom 30. Mai 2016 ans Laufen bekommen und beziehe mich daher hier auf diese, würde mich aber nicht wundern, wenn auch eine neuere Version funktionieren würde. Vielleicht einfach mal ausprobieren. Leider weiß ich nicht mehr genau den Weg, den ich damals genommen habe, und kann daher nur Hinweise geben, keine Anleitung.
Man benötigt wohl auch noch die libconfig in Version 1.5 (möglicherweise geht auch hier die neuere 1.6?). Die kann man einfach runterladen, in ein Verzeichnis entpacken (in meinem Fall /home/$USERNAME/projekte/libconfig/libconfig-1.5), dann
./configure
ausführen und hernach
make
Das reicht schon, dann ist die Bibliothek dort verfügbar.
Es sieht so aus, als wären die nötigen Änderungen im Ordner von owntracks-recorder allesamt in der config.mk und dessen Kompilieren sollte danach klappen. Würde mich freuen von jemandem, der es ausprobiert hat, eine Rückmeldung zu bekommen. Also, meine config.mk hat folgende Änderungen:
INSTALLDIR = /home/$USERNAME/projekte/owntracks-recorder STORAGEDEFAULT = /home/$USERNAME/projekte/owntracks-recorder/store DOCROOT = /home/$USERNAME/projekte/owntracks-recorder/htdocs JSON_INDENT ?= yes CONFIGFILE = /home/$USERNAME/projekte/owntracks-recorder/etc/config MOSQUITTO_INC = -I/home/$USERNAME/projekte/mosquitto/mosquitto-1.4.9/lib -I/home/$USERNAME/projekte/libconfig/libconfig-1.5/lib MOSQUITTO_LIB = -L/home/$USERNAME/lib MORELIBS = -L/home/$USERNAME/projekte/libconfig/libconfig-1.5/lib/.libs -lconfig # -lssl
($USERNAME jeweils von Hand ersetzen durch den eigenen Benutzernamen, die anderen Pfade jeweils auf eigene Gegebenheiten anpassen)
Nach dem Kompilieren müsste ./owntracks-recorder funktionieren. Allerdings gab es, wenn ich mich recht erinnere, noch kleinere Probleme, die Web-Oberfläche aufzurufen, die ich nie wirklich behoben habe, weil mir die Daten in den Verzeichnissen schon gereicht haben.
Ich hoffe, das hilft schonmal?