Schlagwort-Archive: G-Tag

Anwesenheitserkennung über Beacons

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:

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:Bluetooth lsusb

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.

sudo hcitool lescan

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.

FHEM Beacon

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.

 

Zuletzt aktualisiert am 02.05.2017.