Stöpsel fährt mit (Linux-Magazin, Oktober 2016)

Ein in den OBD-(On Board Diagnose)-Port gestöpselter Stecker sendet per Bluetooth aktuelle Informationen wie Geschwindigkeit, Beschleunigung, Benzinverbrauch des fahrenden Kraftfahrzeugs an das mitreisende Mobiltelefon. Eine App und eine programmierbare API lesen die Daten aus und stellen sie ansprechend dar.

Wer wie ich den Gedanken absurd findet, ein halbes Jahresgehalt in ein neues Auto zu investieren, und statt teurer deutscher Wertarbeit lieber gebrauchte japanische "Opel-Manta"-ähnliche Boliden aus den 90er-Jahren fährt, bekommt leider nicht den elektronischen Schnickschnack unter dem Motto "Connected Car" geboten, der heutzutage üblich ist. In meiner Wahlheimat San Francisco hat sich deshalb vor einiger Zeit eine Startup-Firma namens Automatic (automatic.com) aufgemacht, einen Stecker für den On-Board-Diagnose-(OBD)-Port zu entwickeln, der laufend Daten aus dem Autocomputer ausliest und per Bluetooth in eine auf dem mitgeführten Handy laufenden App einspeist ([2]).

Diese fasst die Daten nach Abschluss der Autofahrt zusammen, übermittelt sie bei vorliegender Internetverbindung an den Automatic-Server, wo der erstaunte Fahrer dann später nachsehen kann, wo er langgefahren ist, wie oft er wie ein Irrer Gas gegeben, stark gebremst, wieviel Benzin er verbraucht hat und wieviel der Trip demnach gekostet hat. Abbildung 2 zeigt, dass mein Integra GSR unter meiner Obhut 27.3 Meilen pro Gallone gefahren ist, also 11.6 Liter auf 100km verbraucht hat. Die Wertung von nur 29 von maximal 100 möglichen Punkten für sparsames Fahren ist noch stark verbesserungswürdig (Abbildung 2).

Abbildung 1: Der Automatic-Adapter steckt im OBD-Port des Autos und übermittelt drahtlos per Bluetooth Motordaten an das Handy.

Abbildung 2: Die Automatic-App auf dem Handy gibt dem Schnellfahrer nur 29 von 100 Punkten in punkto Verbrauchseffizienz.

Sogar für Fuhrparks

Falls jemand wie ich mehrere Autos besitzt, benötigt jedes seinen eigenen Automatic-Stecker. Der OBD-Port findet sich meist unter dem Armaturenbrett im Bereich des Fußraums, meist auf der Fahrer- aber auch manchmal auf der Beifahrerseite (Abbildung 3). Einmal registrierten Adapter ticken dann aber alle nahtlos mit verschiedenen Familienhandys zusammenarbeiten, auf denen die Automatic-App installiert ist. Ohne dass der jeweilige Fahrer des jeweiligen Autos etwas dazutun müsste, verbindet sich das Handy in der Hosentasche nach dem Anstellen des Motors automatisch mit dem Stecker, der dies durch eine fröhlich klingende Tonsequenz kundtut, und speichert die aktuellen geografischen Koordinaten als Anfangsort der Reise.

Abbildung 3: Der OBD-Port zum Einstecken des Adapters befindet sich meist unterhalb des Armaturenbretts.

Abbildung 4: Auf der Automatic-Webseite kann der User nachsehen, wann er mit welchem Auto wohin gefahren ist, wieviel Benzin verbraucht und wie sein Fahrverhalten bewertet wurde.

Nach der Ankunft am Zielort bemerkt das Handy, dass sich das Auto nicht mehr fortbewegt, speichert die aktuelle Adresse als Zielort des Trips, und lädt die Daten automatisch übers Internet zum Server hoch, ohne dass dies der Fahrer überhaupt mitbekommt, denn die mobile App läuft immer im Hintergrund mit. Die Tripdaten lassen sich später entweder über die App oder auf Wunsch auch im Browser eines Desktopcomputers anzeigen (Abbildung 4), und auch eine API bietet Automatic, die angemeldeten Usern per JSON maschinenlesbare Daten zurückliefert, die weitere Skripts aufbereiten und anzeigen können.

Abbildung 5: Die Autofahrt von San Francisco zum Strand in Pacifica hat 18 Minuten gedauert, und das Auto hat für die zurückgelegten 13.4 Meilen $1.28 an Benzin verbraucht.

Wo hab ich geparkt?

Wir Großstädter zirkeln ja schon mal eine Viertelstunde um den Block, bis wir endlich einen Parkplatz für unser Automobil finden. Später kommt oft die Frage auf: "Wo hab ich nochmal geparkt?". Dank dem Automatic-Stöpsel ist das nun sonnenklar, denn am geografischen Ende eines "Trips" in der Automatic-Welt muss das Auto stehen, falls es nicht gerade schon wieder in der Gegend herumfährt.

Das Einholen der Daten funktioniert dank der Automatic-API auch mit einem Perl-Skript von der Kommandozeile aus. Dazu muss der User die Applikation zunächst auf Automatics Developer-Seite (https://developer.automatic.com/) anmelden und erhält nach dem sogenannten OAuth-Token-Dance einen Access-Token, mit dem ein API-Client wie zum Beispiel das Skript in Listing 1 im Auftrag des Users private Daten vom Server bekommt.

Abbildung 6: Ein Perl-Skript holt die Autodaten vom Automatic-Server und bestimmt wo die Fahrzeuge des Users geparkt wurden.

Listing 1 holt zunächst mittels des API-Calls vehicle in Zeile 10 die Beschreibungen aller registrierten Autos des Users ein. Die for-Schleife ab Zeile 13 iteriert dann durch den Fuhrpark und ruft für jedes Fahrzeug in Zeile 17 die API-Methode trip mit der ID des aktuellen Fahrzeugs auf. Die API-Aufrufe liefern Daten im JSON-Format an den Client, diese wandelt die aus dem CPAN-Modul JSON exportierte Funktion from_json() in Perl-Daten um, in denen der Code dann mittels Hash- oder Arrayzugriff herumstöbern kann. Die Ausgabe in Abbildung 6 zeigt, dass der Acura Integra GSR, der Opel Manta Amerikas, gerade auf der 24. Straße in San Francisco parkt, während der Honda Fit, das Pendlerfahrzeug der Perlmeisterfrau, gerade im benachbarten Oakland weilt, wo sie zur Arbeit geht.


=head2 Trip-Mitschnitt

Die Ergebnissdaten liegen unter dem Schlüssel results in einem Array und im Fall des trip-Aufrufs enthält jener eine Reihe von Trip-Objekten, die die Koordinaten einer Reise, Angaben zur Geschwindigkeit, die Anzahl der Beschleunigungs- und Bremsmanöver, sowie sogar die Straßenadressen am Ausgangs- und Endpunkt der Reise enthalten. Die Trips kommen in umgekehrter chronologischer Folge an, also ist der erste Trip in der Liste immer jeweils der letzte abgeschlossene.

Listing 1: wheresmycar

    01 #!/usr/local/bin/perl -w
    02 use strict;
    03 use OAuth::Cmdline::Automatic;
    04 use JSON qw( from_json );
    05 
    06 my $oa = OAuth::Cmdline::Automatic->new();
    07 $oa->raise_error( 1 );
    08 
    09 my $vehicles = 
    10   from_json $oa->http_get(
    11      "https://api.automatic.com/vehicle" );
    12 
    13 for my $car ( 
    14     @{ $vehicles->{ results } } ) {
    15 
    16   my $trips = 
    17     from_json $oa->http_get(
    18         "https://api.automatic.com/trip",
    19         [ vehicle => $car->{ id } ]
    20     );
    21 
    22   for my $trip ( 
    23       @{ $trips->{ results } } ) {
    24     printf "%20s: %s\n", 
    25       "$car->{ make }-$car->{ model }-" .
    26       "$car->{ year }",
    27       $trip->{ end_address }->{ name };
    28     last;
    29   }
    30 }

Der unter dem Eintrag end_address vermerkte Endpunkt ist die Adresse an der Stelle, an der das Fahrzeug geparkt wurde. Bleibt nur noch, zur Unterscheidung der Fahrzeuge im Fuhrpark Marke, Modell und Baujahr des Autos auszugeben (in der Perlmeistergarage standen vor einiger Zeit tatsächlich mal zwei Integras unterschiedlicher Jahrgänge), zusammen mit dem "name"-Feld der Zieladresse des Trips, und schon ist klar, wo der Wagen geparkt wurde. Der Befehl last in Zeile 28 bricht die Bearbeitung der Tripdaten jeweils nach dem ersten Satz ab, und die for-Schleife ab Zeile 13 geht mit dem nächsten Auto aus dem Fuhrpark in eine neue Runde.

Abbildung 7: Vor dem API-Zugriff muss der User das Skript auf Automatics Developerseite anmelden.

OAuth bittet zum Tanze

Wie nun kann der User das Skript dazu autorisieren, in seinem Namen private Daten vom Automatic-Server einzuholen? Das CPAN-Modul OAuth::Cmdline bietet neben Helfern für Anbieter wie Google Drive, Spotify oder Microsoft Online seit Version 0.05 auch eine Schnittstelle für Automatic.com an. Um den User mittels eines Webbrowsers durch den Tokentanz zu führen, muss er die Applikation auf der Automatics-Developerseite erst einmal anmelden (Abbildung 7). Unter "My Apps" wird dazu der "+"-Knopf gedrückt und neben dem App-Namen (hier "Perlsnapshot") im Feld "OAuth Redirect URL" der Wert

    http://localhost:8082/callback

eingetragen, damit der Automatic-Server den Kommandozeilen-Client nach getaner Arbeit wieder zu seinem eigenen Webserver zurücklotst und ihn den einfangenen Access-Token lokal auf der Festplatte ablegen lässt. Automatic besteht bei kommerziellen Applikationen darauf, diese vor Inbetriebnahme zur Freischaltung zu überprüfen, aber im Testmodus kann der Betreiber auch ohne gestrenges Tribunal bis zu 25 User-Accounts verwalten. Die Registrierung der App quittiert Automatic mit zwei Schlüsseln, der Client ID und dem Client Secret. Beide legt der User nun in der Datei .automatic.yml im YAML-Format im Home-Verzeichnis ab:

    ~/.automatic.yml
    client_id: XXXXX
    client_secret: YYYY

Im Verzeichnis eg des CPAN-Moduls OAuth::Cmdline liegt ein Skript namens automatic-token-init, das nach dem Starten die Meldung ausgibt, dass es auf dem heimischen Rechner localhost auf Port 8082 einen Webserver gestartet hat. Nordet der User dann seinen Browser auf http://localhost:8082 ein, zeigt dieser einen mit "Login on automatic" betitelten Link an, der auf einen Mausklick hin zur Login-Seite des Automatic-Servers verzweigt (Abbildung 8).

Abbildung 8: Der lokal gestartete Webserver dirigiert den User zum Login auf der Automatic-Webseite, um die Applikation "Perlsnapshot" zu autorisieren.

Zugriff genehmigt

Loggt der User sich dort ein und erklärt sich damit einverstanden die neue namentlich angezeigte Applikation "Perlsnapshot" zum Einholen von Nutzerdaten zuzulassen (Abbildung 8), verzweigt der Automatic-Server wieder zurück zum Webserver des init-Skripts, das daraufhin in der Datei ~/.automatic.yml einige weitere Parameter wie den Access-Token ablegt, mit denen Skripts zukünftig Fahrdaten holen können, ohne dass der Nutzer sein Passwort eingeben muss. Das CPAN-Modul bietet eine Methode zum Einholen von authentisierten Web-Requests die Methode http_get() an, die hinter den Kulissen den Access-Token aus der YAML-Datei holt und ihn dem ordnungsgemäß dem Request in Headerform beilegt, sodass der Server ohne Fiesematenten zu machen die privaten Daten herausrückt.

Ein kleines Detail am Rande: Anders als andere OAuth-Implementierungen bietet Automatic keinen sogenannten Refresh-Token an, aber dafür bleibt ein einmal ausgestellter Access-Token ein ganzes Jahr lang gültig, nach dessen Ablauf der User erneut durch den Tokentanz muss.

Abbildung 9: Die "Perlsnapshot" App wurde erfolgreich in den Account eingebunden.

Malen nach Zahlen

Die aufgezeichneten Tripdaten der Automatic-App enthalten aber noch weitere informationstechnische Leckerbissen. Im Feld "path" findet sich ein kryptischer String, der in der sogenannten Polyline-Kodierung ([3]) alle paar Sekunden den aktuellen Ort des Fahrzeugs während eines Trips als geographische Breite und Länge mitschreibt:

    qzjeFb|hjVDkBh@gAY]hBiDrAwBt@_A...

Mit dem CPAN-Modul Algorithm::GooglePolylineEncoding ist die Zeichenkolonne schnell entschlüsselt: (37.74393, -122.43922), (37.74369, -122.43832), ... wobei der erste Zahlenwert jeweils die geographische Breite ("latitude") angibt, während der zweite die Länge ("longitude") angibt.

Abbildung 10: Morgendliche Fahrt zum Semmelholen in San Francisco gezeichnet mit der Google Maps API.

Listing 2: trip-path

    01 #!/usr/local/bin/perl -w
    02 use strict;
    03 use OAuth::Cmdline::Automatic;
    04 use JSON qw( from_json to_json );
    05 use YAML qw( Dump );
    06 use Algorithm::GooglePolylineEncoding;
    07 
    08 my $oa = OAuth::Cmdline::Automatic->new();
    09 $oa->raise_error( 1 );
    10 
    11 my $trips = from_json $oa->http_get(
    12   "https://api.automatic.com/trip", [] );
    13 
    14 my @locs = Algorithm::GooglePolylineEncoding::decode_polyline( 
    15     $trips->{ results }->[ 0 ]->{ path } );
    16 
    17 print Dump ( \@locs );

Während der 10-minütigen Testfahrt zum Semmelholen von San Franciscos Stadtteil Noe Valley zum Supermarkt in Diamond Heights kamen so 38 Datenpunkte zusammen, die Listing 2 dekodiert und für die grafische Darstellung aufbereitet. Wie nun gelangen die Messwerte auf eine Landkarte wie in Abbildung 10 gezeigt? Die Google-Maps-API bietet dafür eine praktische Schnittstelle und tatsächlich kam diese schon in einer sechs Monate zurückliegenden Ausgabe zum Einsatz: Der Perl-Snapshot im März 2016 ([4]) stellte dazu das Skript map-draw vor, das Latitude/Longitude-Punkte im YAML-Format entgegen nimmt und Javascript produziert, mit dem der Browser mit der Google-Mpas-API in Landkarten einzeichnet. Listing 2 muss also lediglich YAML mit lat/lon-Paaren produzieren, dann erzeugt der Aufruf

    ./trip-path | ./map-draw >map.html

zu einer HTML-Seite, die man einfach mit file:///...map.html in den Browser lädt und eine interaktive Landkarte mit der Wegstrecke bestaunen kann.

Auch in Echtzeit

Neben der in den Skripts genutzten REST-API bietet Automatic auch noch eine Realtime-Stream API an, entweder über Websockets oder Webhooks, die Applikationen praktisch verzögerungsfrei benachrichtigt, wenn bestimmte Ereignisse eintreten. Beim Start des Wagens, am Ende eines Trips, beim Übertreten eines voreingestellten Geschwindigkeitswerts, scharfem Bremsen oder wenn die Kontrolllampe aufflackert, schickt der Webservice damit sofort eine Nachricht an die lauschende App, die diese auch auf der Lockscreen des versperrten Handys anzeigt und es auf Wunsch vibrieren oder einen Ton spielen lässt.

Der im zurückliegenden Perl-Snapshot zur Integration des Fernschalters WeMo ([5]) besprochene Webservice ifttt.com erleichtert auch im Fall des Autostöpsels das Einklinken beträchtlich. Statt API-Integration trägt sich der User dort auf dem Automatic-Channel ein, wird ähnlich wie beim vorher verwendeten CPAN-Modul durch den Tokentanz geführt und aufgefordert, ifttt.com Zugriff auf die Automatic-Daten zu gewähren. Abbildung 11 zeigt das ifttt-Rezept, das jedes Mal eine Kurznachricht auf das Mobiltelefon des Users schickt, falls ein Fahrer die Zündung des Wagens anstellt. Allerdings wieder naturgemäß mit der Einschränkung, dass ein anderes Handy mit installierter Automatic-App mitfährt, denn sonst hat der Adapter keine Verbindung zum Internet.

Abbildung 11: Mit Ifttt.com integriert sendet der Automatic-Adapter Push-Notifications aufs mobile Telefon wenn ein Auto startet.

Kosten und Ausblick

Der Automatic-Stecker der aktuellen 2. Generation kostet in der Anschaffung etwa $90, die App kostet nichts, und weitere Kosten für das Sammeln und Anzeigen der Daten fallen ebenfalls nicht an. Das Gerät arbeitet ausgesprochen zuverlässig, manchmal dauert es allerdings etwas, bis ein Trip zum Server hochgeladen wird, falls das Handy mal keine Verbindung zum Internet oder Zugang zu GPS-Daten findet. Denn der Stecker kann alleine wirklich nichts außer OBD-Daten abzugreifen und per Bluetooth ans mitfahrende Handy zu senden, das dann die Hauptarbeit erledigt. Gegen den Diebstahl des Fahrzeugs hilft er also nicht. Es existieren bereits etwa zwei Dutzend weitere Apps für's iPhone or Android und mit der einfach zu handhabenden API sollte es nicht lange dauern, bis ein ganzes Ökosystem mit weiteren praktischen Anwendungen entsteht.

Infos

[1]

Listings zu diesem Artikel: http://www.linux-magazin.de/pub/listings/magazin/2016/10/perl-snapshot

[2]

"Automatic.com: Dieser Adapter macht Ihr Auto schlau", http://www.computerbild.de/artikel/cb-Tests-App-Check-Automatic-com-Adapter-Connected-Car-11378727.html

[3]

"Encoded Polyline Algorithm Format", https://developers.google.com/maps/documentation/utilities/polylinealgorithm

[4]

Skript map-draw aus Perl-Snapshot "Steighilfen" (03/2016): http://www.linux-magazin.de/pub/listings/magazin/2016/03/Perl

[5]

"Klick-klack", Michael Schilli, Linux-Magazin 07/2016, http://www.linux-magazin.de/Ausgaben/2016/07/Perl-Snapshot

Michael Schilli

arbeitet als Software-Engineer in der San Francisco Bay Area in Kalifornien. In seiner seit 1997 laufenden Kolumne forscht er jeden Monat nach praktischen Anwendungen der Skriptsprache Perl. Unter mschilli@perlmeister.com beantwortet er gerne Ihre Fragen.