Presence Management mit openHAB und iBeacons

Da ich seit längerem schon (zugegeben: ziemlich neidisch) auf die Android-User mit ihren Möglichkeiten zur Nutzung von NFC und Tasker geschielt hatte war es wohl an der Zeit, dass ich mich einmal mit iBeacons, iOS und openHAB beschäftige. Dabei kam ein Lösungsansatz für das leidige Thema „Presence Management“ heraus, mit der ich ganz gut leben kann.

Bisher hatte ich zu diesem Themengebiet bereits MQTT, ARP-Ping, owntracks und so einige andere Ansätze ausprobiert, jedoch fand ich immer irgendwo das Haar in der Suppe. Aufgrund der Tatsache, dass iOS-Devices nach einer bestimmten Zeit im Netz nicht mehr erreichbar sind, Bluetooth mir an sich schon wegen der Notwendigkeit eines erfolgreichen Pairings nicht gefällt und mir der Aufwand bei MQTT in Kundenprojekten einfach zu groß ist, kam mir auf der letzten iOS-Developer-Conference in Hamburg das Thema iBeacon ganz gelegen. Bluetooth Low Energy hat definitv einige Vorteile: So lässt sich zum Beispiel, unter Verwendung von 3. Party Lösungen,  ein definiertes App starten, sobald der passende Beacon in Reichweite ist. Ausprobiert hatte ich das bereits mit dem App „Launch here“. In meinem Fall startet mein Navigationssystem „Scout“, sobald ich ins Auto einsteige und die Zündung angeschaltet wird. Damit das funktioniert, muss lediglich der Beacon (ich verwende einen des deutschen Anbieters „Beacon Inside“ aufgrund des USB Anschlusses und der Möglichkeit, auch auf Batteriebetrieb zu wechseln) an ein Ladegerät im Zigarettenanzünder angeschlossen werden. Da der Zigarettenanzünder an Klemme 15 (Zündungsplus) hängt, startet der Beacon auch erst, wenn die Zündung angeschaltet wurde. In der Praxis sieht das dann wie folgt aus:

 

Was passiert ist folgendes: Launch here erkennt den Beacon und weißt mich darauf hin. Ich wische über die Aktion und Launch here startet eine sog. Launch URL. Das kann per Definition alles mögliche sein, im Falle von Scout (früher Skobbler) lautet der Aufruf schlicht und einfach:
hybridnavigation://

Das ganze würde z.B. auch mit sms:// (wie der Name sagt: Nachrichten-App), maps:// (Karten) oder mailto:// (Mail) funktionieren, festgelegt ist das in den Launch URL References von Apple oder, im Fall von Skobbler, in den Custom URLs, die jedes App, sofern vom Entwickler dafür konzipiert, mitliefert. Tipp: Falls ihr für das App der Wahl kein URL findet, so kann es hilfreich sein, den Entwickler zu kontaktieren und einfach nach der Adresse zu fragen.

Da das mit dem Navi ganz gut in der Praxis funktioniert, sollte sich das also auch für Presence Management verbiegen lassen. Und tatsächlich, es geht eigentlich ganz einfach – man muss sich lediglich der Rest-API bedienen. Aktuell habe ich in openHAB einen Switch definiert, welcher festlegt, ob jemand zuhause ist oder eben nicht, der Schaltbefehl kann entweder manuell in openHAB erfolgen oder per REST-Buttons, einem kleinen App von meinem Kollegen, welches auf GitHub verfügbar ist (danke an Manfred an dieser Stelle). REST-Buttons liest den Zustand eines Items aus und stellt diesen Zustand dann entsprechend grafisch dar. Durch einen Klick / Touch auf das entsprechende Symbol setzt REST-Buttons exakt den gegenteiligen / negierten Zustand des bisher aktuellen, in meinem Fall also „Alarmanlage aus“ wenn an und umgekehrt. Der Zustand „Alarmanlage an“ wird von mir generell manuell gesetzt, hierfür hängt ein altes iPhone neben der Eingangstüre, dieses zeigt eigentlich immer REST-Buttons in Safari an, daran wollte ich auch nichts ändern. Anders sieht es jedoch mit dem gegenteiligen Zustand aus – nichts ist nerviger als vollgepackt mit Einkaufstüten, Rucksack und Post die Türe aufzusperren und dann als erstes zum Handy zu greifen, um die Alarmanlage auszuschalten und keinen Alarm auszulösen. Um also den Schaltbefehl „Alarmanlage aus“ zu automatisieren sollte der Vorgang wie folgt aussehen:

Beacon erkannt > WLAN erkannt und eingebucht > URL im Hintergrund aufrufen > Alarmanlage ausschalten

Da gerade der Teil mit „WLAN erkannt und eingebucht“ mit Launch here nicht lösbar ist und Launch

here auch noch Geld kostet musste eine Alternative her. Bei der Suche nach anderen Apps, die meine Zwecke erfüllen könnten, stiess ich auf „Beecon“. Dieses App kann alles, was ich brauche, ist kostenlos und funktioniert nebenbei auch noch wesentlich genauer und performanter als sein Kollege. Einziger Nachteil: Es werden standardmäßig nicht alle Beacon-Hersteller automatisch erkannt. Um einen nicht unterstützen Beacon hinzuzufügen muss man (fummligerweise) erst für die Zone seiner Wahl die UUID des Beacon-Herstellers manuell hinzufügen, danach klappts dann auch mit dem Rest der App.

Einmal hinzugefügt können nun Aktionen definiert werden. In meinem Fall soll Beecon beim ersten Erkennen des Beacons in der Home Zone eine URL auf meinem openHAB Server aufrufen, diese wiederum setzt den Status des Schalter „Presence_Global“ auf „an“, ergo „Alarmanlage aus“. Das ganze soll aber nur passieren, wenn mein iPhone schon im WLAN eingebucht ist. Nach dem schalten erhalte ich dann von Prowl noch eine informative Nachricht, welche mir mitteilt, dass die Wohnung nun nicht mehr scharf geschaltet ist.

 

Auf openHAB bzw. Rest-Seite sieht das ganze so aus:

set.php

alarm_on.php (wird von Beecon referenziert)

Wie ihr seht – eigentlich wirklich simpel und schnell umzusetzen. Die PHP-Files können z.B. im Standardverzeichnis mit Apache in einem Unterordner (/var/www/rest/) liegen, achtet lediglich darauf, dass die Berechtigungen auf dem Ordner entsprechend gesetzt sind.

[Update:]
Ich wurde heute gefragt, wieso ich das ganze mit PHP und REST aufrufe, statt einfach den Befehl über eine URL und somit an REST vorbei zu übergeben, z.B. so:
http://IP-OPENHAB:8080/CMD?Light=ON

Das würde natürlich so auch klappen, im oben beschriebenen Anwendungsfall wäre das auch völlig ausreichend. Allerdings wird diese Methode spätestens bei komplexeren Aufgaben nicht mehr ziehen, ein gutes Beispiel dafür ist bereits in REST-Buttons implementiert:
https://github.com/stardriver2k/RestButtons/blob/master/index.html

Von daher empfiehlt es sich aus meiner Sicht, gleich den entsprechenden Code zu schreiben und die REST API nativ zu bedienen, somit ist man auch für alle weiteren Ansätze gewappnet.

Danke jedoch für den Hinweis bzw die Frage, die Möglichkeit sollte auf jeden Fall erwähnt werden