Anwesenheitserkennung über iBeacons
In letzter Zeit liest man immer wieder über Bluetooth Low Energy (BLE) bzw. iBeacons. Ein typisches bzw oft erwähntes Anwendungsszenario ist hierbei die Positions- bzw. Anwesenheitserkennung.
Ein Vorteil ist das BLE stark gegenüber “normalen” Bluetooth hinsichtlich des Stromverbrauchs verbessert wurde. Statt einiger Sekunden für einen Verbindungsaufbau benötigt man nur noch Millisekunden. Zusammen mit diversen anderen Protokoll Optimierungen ergibt das einen extrem niedrigen Energieverbrauch.
Ein typisches Szenario ist dass man überall iBeacons im Haus verteilt, das Handy permanent nach den Beacons scannt und anhand der Signalstärke berechnet wie weit jeder Beacon entfernt ist. Diese Information wiederum wird dann an einen Server gesendet.
Diese Variante hat allerdings 2 Schwachstellen. Erstens schwankt das BLE Signal in der Stärke extrem und ist erst mal nur bedingt geeignet die Position zu errechnen und zweitens verbraucht das Handy ziemlich viel Strom wenn es im Sekundentakt scannt und die Daten per WLAN an einen Server sendet.
Umsetzung
Für meine Umsetzung habe ich mich für den Umgekehrten Weg entschieden. Mein Handy sendet sobald es das heimische WLAN erkennt, permanent eine BLE Advertising Nachricht. Das geschieht ca. 10 mal die Sekunde mit dem LOW BLE Profile. Trotz dieser Häufigkeit wird der Akku kaum belastet da BLE Advertising Nachrichten extrem kurz sind. Über den Tag verteilt sind es nicht einmal 2% der Akku Kapazität. Als Empfänger habe ich mich für den neu erschienenen Raspberry Pi Zero W entschieden welchen man über den deutschen Distributor pi3g beziehen kann.
Dieser “Mini”-PC verbraucht 0,7 Watt und bringt von Hause aus BLE und WLAN mit. Insgesamt habe ich im Haus 15 davon verteilt. Sie machen jetzt nichts weiter als permanent nach BLE Advertising Nachrichten zu scannen und diese Daten dann zu einem zentralen Server zu schicken. Finden Sie keine Nachrichten schicken sie auch nichts zum Server wodurch unnötiger WLAN Traffic vermieden wird. Aufgrund des LOW Profiles muss sich mein Handy auch mindestens im Nebenzimmer befinden um überhaupt erkannt zu werden.
Serveranwendung
Meine Serveranwendung ist in Java geschrieben und läuft als Tomcat Anwendung. Sämtliche Raspberries sind über Websockets verbunden um die Reporting Latenz und den Netzwerktraffic möglichst gering zu halten.
Um das zuvor genannte erste Problem, der starken Signalschwankung zu mindern gibt es diverse Ansätze die ich in meiner Anwendung umgesetzt habe.
- Der Server synchronisiert alle Raspberries um möglichst im gleichen 1 Sekunden Zeitfenster zu messen. Auf die Art hat man die Sicherheit daß alle empfangen Signale durch die gleichen aktuell auftretenden Störungen beeinflusst wurden. Dies geschieht dadurch dass ich den Raspberries per Websockets mitteile in welchem Intervall sie senden sollen und jedes mal nachdem Sie gesendet haben auch noch mitteile wie viel es zu spät war. Auf diese Weise ist die Genauigkeit zwischen 1ms und 20ms. Die Restliche Ungenauigkeit kommt durch stark schwankende Netzwerklatenzen die sich leider nicht kompensieren lassen.
- Im Server werden räumliche Beziehungen hinterlegt. D.h. wenn ich im Wohnzimmer bin kann ich Signale im Schlafzimmer komplett ignorieren da es nicht direkt vom Wohnzimmer aus erreichbar ist. Auf diese Art kann man Signalspitzen aus nicht erreichbaren Räumen erst mal außer Acht lassen.
- Sobald man einen Raum betritt hat man erst mal ein starkes Signal. Durch dieses starke Signal “aktiviert” man den Raum quasi. Nun bleibt der Raum solange aktiv bis ein anderes starkes Signal einen Nebenraum aktiviert. In der Zwischenzeit bleibt der Raum aktiv auch wenn der Nebenraum ein kurzzeitig stärkeres Signal als im eigenen Raum sendet.
- Rein rechnerisch müssten bei einer Sendefrequenz von 10Hz, 10 BLE Nachrichten jede Sekunde empfangen werden. Die Anzahl an empfangenen Nachrichten interpretiere ich als eine Art Wahrscheinlichkeit dass das Durchschnitts Signal richtig ist. Diese Wahrscheinlichkeit wird nun benutzt um zwischen dem letzten gemessenen Signal und dem aktuell gemessenen Signal zu interpolieren.
Beispiel: Der letzte gemessene RSSI Wert lag bei -70db. Nun messe ich einen Durchschnittswert RSSI Wert von -80db bei 3 empfangenen Nachrichten. Die Differenz zwischen altem und neuem Signal liegt bei -10db. Mein neuer finaler Wert ist nun 73db. Bei 6 empfangen Nachrichten wären es 76db und bei 10 empfangenen Nachrichten wären es -80db.
Durch die Kombination dieser Ansätze erhält man eine relativ stabile und auch schnelle (1-2 sec) Präsenzerkennung.
Visualisierung
Um all diese Berechnungen zu ermöglichen und auch zu visualisieren muss man natürlich weitere Informationen im Server hinterlegen. Dies sind der eigene Grundriss als SVG Datei, die Position der einzelnen Tracker im Haus sowie die zu trackenden Handys.
Die eigentliche Visualisierung ist als Webanwendung realisiert welche die hinterlegte SVG Datei anzeigt. Die Kommunikation mit dem Server erfolgt per Websocket. Dieser sendet in regelmäßigen Abständen die genauen Koordinaten der aktiven Bereiche welche im SVG dann hervorgehoben werden.
Weitere Anwendung
Die eigentliche Anwendung besteht natürlich nicht in der Visualisierung. Statt dessen sende ich die erkannten Räume per REST API in mein openHAB System um es dann dort weiter zu verarbeiten.
Android App
Aktuell verwende ich noch eine dritt App welche iBeacon Signale senden kann. Dies werde ich aber in naher Zukunft durch eine eigene ersetzen welche das automatisch tut sobald das eigene WLAN erkannt wird.