Anwesenheitserkennung über Beacons
Oftmals würde man gerne alle Geräte automatisch ausschalten wollen oder die Heizung zurückregeln, wenn niemand zuhause ist. Aber wie können wir feststellen, ob das eigene Heim wirklich verwaist ist?
Im Artikel Anwesenheitserkennung über GPS-Position haben wir einen anderen Ansatz verfolgt.
Wir wollen hier nicht auf die Mittel von Geofencing zurückgreifen, sondern mit sog. Bluetooth Beacons oder Bluetooth LE Tags arbeiten. In diesem Falle handelt es sich um einen sehr kleinen Sender, den man normalerweise am Schlüsselbund bei sich trägt. Jedenfalls hat man dieses Gerät immer bei sich, also könnte die Haussteuerung diesen Beacon über Bluetooth erkennen und somit die Anwesenheit feststellen.
Der Vorteil dieses Ansatzes ist, dass der Beacon eigenständig ist. Man muss ihn im Gegensatz zum Smartphone nie laden und die Batterie hält ewig. Die Reichweite beträgt in etwa 30m (ohne Hindernisse).
Hard-und Software-Voraussetzungen
Zuerst brauchen wir einen Raspberry Pi mit entsprechendem Netzteil. Hierzu habe ich auch entsprechende Empfehlungen gegeben.
Genauso sollte man sich über die Vernetzung Gedanken machen, ob man die Raspberry Pis per Netzkabel oder per WLAN anbinden möchte. Dafür habe ich hier in meinen Artikeln über die Grundkonfiguration Tipps gegeben:
- Checkliste für Raspberry Pi mit FHEM
- Raspberry Pi Grundkonfiguration
- FHEM Grundkonfiguration
- um bei Änderung des Anwesenheitsstatus etwas schalten zu können: CUL Integration in FHEM
Bluetooth-Hardware-Voraussetzungen
Um mit Beacons arbeiten zu können müssen wir den Raspberry Pi mit einem entsprechenden Bluetooth USB-Dongle nachrüsten. Nicht jeder Bluetooth Dongle funktioniert hier, er muss Bluetooth 4.0 beherrschen, denn wir wollen die LE (Low Energy) Technologie benutzen. Gute Erfahrungen habe ich mit folgendem USB-Dongle gemacht:
Dieser lässt sich problemlos in den Raspberry Pi einbinden und wird von Raspbian Linux-Derivat erkannt.
Bluetooth-Dongle installieren
Sobald wir den Bluetooth-Dongle in den Raspberry Pi in einen USB-Port gesteckt haben, sollte dieser als USB-Gerät auftauchen. Hierfür schreiben wir auf der Konsole
lsusb
und sehen uns das Ergebnis an:
In unserem Falle taucht der Bluetooth-Dongle als Device 004 auf. Ohne Installation der notwendigen Pakete können wir jetzt aber noch nicht wirklich viel damit anfangen. Mit folgenden Kommandos holen wir uns die notwendige Software auf den Raspberry Pi:
sudo apt-get install bluetooth bluez-hcidump bluez blueman
Nach einem Restart über
sudo shutdown -r now
sollte die notwendige Software auf dem Rapberry Pi installiert sein. Aber das reicht noch nicht aus, um Beacons wie im Folgenden entsprechend zu lokalisieren. Dazu gleich mehr.
Passende Beacons
Grundsätzlich sollten alle Beacons bzw. Bluetooth LE Tags für unsere Funktionalität passen. Meistens werden diese als Schlüsselfinder verkauft. Ich habe hier nach einer sehr günstigen Variante gesucht, die auch nicht wirklich viel können muss. Das Entscheidende ist eher das Thema Reichweite. Ich habe es mit folgenden Beacons erfolgreich getestet:
Ferner gibt es diese auch in günstigeren Mehrfachpacks. Damit das Ganze funktioniert, sollte auch jeder in der Familie so einen Beacon an seinem Schlüsselanhänger haben.
Um die gezeigten Beacons in Betrieb zu nehmen, zieht man die durchsichtige Plastiklasche aus dem Gerät und setzt die Batterie damit aktiv.
Inbetriebnahme der Beacons
Zuerst sollten wir uns mit der Grundlage unserer neuen Funktionalität beschäftigen. Dies ist das hcitool
, das einen permanenten LE-Scan durchführt. Führen wir einmal in der Konsole das Kommando
sudo hcitool lescan
aus. Nachdem hier Zeile für Zeile mit MAC-Adressen gescannter Bluetooth-Geräte nach unten scrollt, halten wir einmal diesen Endlos-Prozess mit der Tastenkombination STRG
+C
bzw. auf dem Mac mit ctrl
+C
an.
Sobald unser Beacon aufgelistet wurde, halten wir die Endlosausgabe wie gerade beschrieben an. Solange wir nur einen Beacon haben, ist dieser leicht zu identifizieren. Sobald wir mehrere in Betrieb nehmen, müssen wir diesen Schritt wiederholen und uns jeweils die MAC-Adresse des Beacons aufschreiben und dem richtigen zuordnen. In unserem Falle merken wir uns die MAC-Adresse 7C:2F:80:AD:C2:0D
.
Hilfsskript für Erreichbarkeit eines speziellen Beacons
Da das hcitool nur einen Endlos-Scan ausführen kann und manuell unterbrochen werden muss, müssen wir uns ein Hilfsskript basteln, das für eine spezielle MAC-Adress nachsehen kann, ob der Beacon erreichbar ist oder nicht.
Dazu kommt noch ein weiteres Problem, das erst auftritt, sobald wir mehr als einen Beacon besitzen. Damit habe ich mich eine Weile herumgeplagt, denn dann läuft der Scan mehr als einmal gleichzeitig. Folglich kommt es zu einem Fehler, weil der Bluetooth USB-Dongle im Raspberry Pi bereits mit dem Scan auf LE Geräte beschäftigt ist. Denn dann meldet uns das hcitool
folgenden Fehler:
Set scan parameters failed: Input/output error
Dies müssen wir in unserem Hilfsskript entsprechend berücksichtigen. Hierzu erstellen wir ein Shell-Skript, das wir im Verzeichnis /opt/fhem
erstellen. Dementsprechend kopieren wir uns den unten aufgelisteten Code in eine leere Datei namens lescan.sh
. Hierfür können wir den kleinen Editor nano
benutzen und die neue Datei mit
cd /opt/fhem nano lescan.sh
erstellen. Weiters kopieren wir den unten stehenden Code in den geöffneten Editor und speichern ihn mit STRG
+O
ab. Schließlich beenden wir den Editor mit STRG
+X
.
Im Anschluß der Code:
#!/bin/bash devicefile=/tmp/le_device.$$ hcitool lescan 2>&1 > $devicefile & sleep 7 pkill --signal SIGINT hcitool sleep 1 errorresult=$(grep -c "Input/output error" $devicefile) if [ $errorresult -gt 0 ]; then echo 2 else scanresult=$(grep -c $1 $devicefile) if [ $scanresult -gt 0 ]; then echo 1 else echo 0 fi fi rm $devicefile
Wir müssen aber dieses Skript noch ausführbar machen und dafür sorgen, dass der User fhem
das hcitool
ausführen darf. Zuerst setzen wir die Zugriffsrechte für die neue Datei mit:
chown fhem:dialout lescan.sh chmod 777 lescan.sh
Daraufhin brauchen wir noch den Eintrag in der sudoers-Datei, was wir mit dem Befehl
sudo visudo
erledigen. Dort fügen wir die Zeilen an
fhem ALL=(ALL) NOPASSWD: /usr/bin/hcitool fhem ALL=(ALL) NOPASSWD: /opt/fhem/lescan.sh
und speichern die Datei wieder mit STRG
+O
ab. Schließlich beenden wir den Editor mit STRG
+X.
Dadurch ist der Benutzer fhem
, unter dem die Haussteuerung läuft, berechtigt, das gerade erstellte Shell-Skript auszuführen. Da im Skript lescan.sh aber das hcitool ausgeführt wird, muss dieses ebenfalls berechtigt werden. Das erledigt die erste Zeile.
Einbinden in FHEM
Im Folgenden müssen wir jetzt nur noch eine Hilfsfunktion für FHEM erstellen, die das gerade erzeugte Shell-Skript aufruft. Hierzu erstellen wir ein neues Include, das wir im Verzeichnis /opt/fhem/FHEM
erstellen. Dementsprechend kopieren wir uns den unten aufgelisteten Code in eine leere Datei namens 99_BTLEscanUtils.pm
. Hierfür können wir den kleinen Editor nano
benutzen und die neue Datei mit
cd /opt/fhem/FHEM nano 99_BTLEscanUtils.pm
erstellen. Weiters kopieren wir den unten stehenden Code in den geöffneten Editor und speichern ihn mit STRG
+O
ab. Schließlich beenden wir den Editor mit STRG
+X
.
Im Anschluß der Code:
############################################## # $Id: 99_BTLEscanUtils.pm 2691 2017-01-06 Martin Koch $ package main; use strict; use warnings; use Digest::MD5 "md5_hex"; use HttpUtils; sub BTLEscanUtils_Initialize($$) { my ($hash) = @_; } sub get_LEBT_Status($$) { my ($le_device,$statusvar) = @_; my $semaphor_file ="/opt/fhem/log/lestatus_semaphor"; my $oldvalue = ReadingsVal($statusvar,"state","absent"); my @resultstrings = (); my $resultstring = ""; my $exitcount = 0; my $return = 2; # wait for unique le process while(-e $semaphor_file) { sleep(5); $exitcount += 1; if($exitcount > 10) { unlink $semaphor_file; return $oldvalue; } } open(SEM,">$semaphor_file"); print SEM "Semaphor written by $le_device for $statusvar"; close(SEM); @resultstrings = `sudo /opt/fhem/lescan.sh $le_device`; foreach my $resultstring (@resultstrings) { if($resultstring =~ /(\d)*/) { $return = $1; } } if($return > 1) { $return = $oldvalue; } # delete semaphor unlink $semaphor_file; return $return; } 1;
Nun müssen wir nur noch eine Definition für die Anwesenheitsüberwachung per PRESENCE
-Konstrukt in die Konfigurationsdatei fhem.cfg
einbauen, die bei regelmässig die Anwesenheit durch Aufrufen der gerade erstellten Hilfsmethode überprüft:
define Martin_BT_Tag PRESENCE function {get_LEBT_Status("7C:2F:80:AD:C2:0D","Martin_BT_Tag")} 60 180 attr Martin_BT_Tag devStateIcon present:rc_dot@green absent:rc_dot@red attr Martin_BT_Tag group Anwesenheitsstatus_Martin attr Martin_BT_Tag room Anwesenheit define FileLog_Martin_BT_Tag FileLog ./log/Martin_BT_Tag-%Y-%m-%V.log Martin_BT_Tag.* attr FileLog_Martin_BT_Tag logtype text
Nun schaltet sich die Variable Martin_BT_Tag
auf present
, sobald der Beacon in Reichweite des Raspberry Pi ist. Falls unser Wunderkästchen den Bluetooth LE-Dongle nicht per Scan findet, schaltet sich die Variable Martin_BT_Tag
auf absent
.
Wir zeigen dies mit unseren Define-Attributen mit einem grünen bzw. roten Punkt an.
Zusammenfassung
In unserem Beispiel für die Anwesenheitserkennung per Beacon passiert also folgendes: Sobald sich dieser Bluetooth LE-Dongle in Reichweite unseres Raspberry Pi befindet, soll eine Variable schalten. Nun könnten wir natürlich auf diese Wertänderung genauso reagieren wir bei der Anwesenheitserkennung über GPS-Position und beispielsweise die Heizung einschalten. Oder wir könnten eine Steckdose automatisch einschalten.
Damit das Ganze zuverlässiger wird, könnten wir jetzt noch die Anwesenheit zusätzlich über den WLAN-Status unseres Smartphones überprüfen und die beiden Status kombinieren. Sobald beide Variablen auf absent
stehen, können wir sicher gehen, dass sich die Person wirklich nicht mehr zuhause befindet. Aber dazu mehr in einem weiteren Artikel.