Smart Home openHAB Installation Teil 6 – Anwesenheitserkennung


Update 12.11.2020

Ab Dezember  2020 habe ich das Glück, ein Eigenheim zu besitzen. Mit dem Umzug werde ich mein Smart Home zukünftig mit Home Assistant steuern, sodass die Serie Smart Home openHAB Installation nicht länger fortgeführt und gepflegt wird.


Teil 6 meiner Beitragsreihe Smart Home openHAB Installation befasst sich mit dem Thema „Anwesenheitserkennung“. Aktuell nutze ich drei Apple Geräte, ein iPhone, ein iPad und eine Watch. Alle drei möchte ich in meine openHAB Installation einbinden und insbesondere die Werte des iPhones zur Anwesenheitserkennung nutzen. Darüberhinaus lassen sich natürlich weitere Werte in die Sitemap einbinden.

Der Anwesenheitsstatus kann später dazu dienen, um davon abhängie Aktionen auszuführen.

Binding: iCloud

Das iCloud Binding ist eins der komplizierteren Sorte. Grund dafür ist, dass Apple regelmäßig (jährlich) ein Zertifikat austauscht, welches für die Kommunikation benötigt wird. Daher funktioniert das Binding, das über die PaperUI installiert werden kann i.d.R. nur bis maximal zum nächsten Ablauf des Zertifikats.

Deshalb muss das Binding manuell installiert und angepasst werden, um es dauerhaft funktionsfähig zu halten.

Der Vorgang ist entsprechend jährlich zu wiederholen.

$OPENHAB_CONF$/things/icloud.things

Nachdem nun das Binding eingerichtet ist, werden die Apple-ID und die Geräte in der Things-Datei angelegt.

Bridge  icloud:account:appleId  "Apple/iCloud: Apple ID"   [ appleId="<AppleID>", password="<AppleID-Password>", refreshTimeInMinutes=5 ]
{
   Thing  device  iphone  "Apple/iCloud Device: iPhone"  [ deviceId="<Device-ID aus der PaperUI Inbox>" ]
   Thing  device  ipad    "Apple/iCloud Device: iPad"    [ deviceId="<Device-ID aus der PaperUI Inbox>" ]
   Thing  device  iwatch  "Apple/iCloud Device: Watch"   [ deviceId="<Device-ID aus der PaperUI Inbox>" ]
}

$OPENHAB_CONF$/items/icloud.items

Im Anschluss konfiguriere ich die Items für die Geräte. Für jedes Gerät lege ich eine Gruppe und die dazugehörigen Parameter an.

Group     Apple_iCloud_iPhone              "Apple/iCloud Group: iPhone"           <icloud_iphone>
Group     Apple_iCloud_iPad                "Apple/iCloud Group: iPad"             <icloud_ipad>
Group     Apple_iCloud_Watch               "Apple/iCloud Group: Watch"            <icloud_iwatch>

String    Apple_iPhone_BatteryStatus       "Apple/iCloud iPhone: Battery Status [%s]"                          <battery>    (Apple_iCloud_iPhone)  { channel="icloud:device:appleId:iphone:batteryStatus "}
Number    Apple_iPhone_BatteryLevel        "Apple/iCloud iPhone: Battery Level [%d %%]"                        <battery>    (Apple_iCloud_iPhone)  { channel="icloud:device:appleId:iphone:batteryLevel" }
Switch    Apple_iPhone_FindMyPhone         "Apple/iCloud iPhone: Trigger Find My iPhone"                                    (Apple_iCloud_iPhone)  { channel="icloud:device:appleId:iphone:findMyPhone", autoupdate="false" }
Switch    Apple_iPhone_Refresh             "Apple/iCloud iPhone: Force iPhone Refresh"                                      (Apple_iCloud_iPhone)  { channel="icloud:device:appleId:iphone:location", autoupdate="false" }
Location  Apple_iPhone_Location            "Apple/iCloud iPhone: Coordinates"                                               (Apple_iCloud_iPhone)  { channel="icloud:device:appleId:iphone:location" }
Number    Apple_iPhone_LocationAccuracy    "Apple/iCloud iPhone: Coordinates Accuracy [%.0f m]"                             (Apple_iCloud_iPhone)  { channel="icloud:device:appleId:iphone:locationAccuracy" }
DateTime  Apple_iPhone_LocationLastUpdate  "Apple/iCloud iPhone: Last Update [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]"  <time>      (Apple_iCloud_iPhone)  { channel="icloud:device:appleId:iphone:locationLastUpdate" }
Switch    Apple_iPhone_Home                "Apple/iCloud iPhone: iPhone Home"                                   <presence>  (Apple_iCloud_iPhone)

String    Apple_iPad_BatteryStatus         "Apple/iCloud iPad: Battery Status [%s]"                             <battery>   (Apple_iCloud_iPad)    { channel="icloud:device:appleId:ipad:batteryStatus" }
Number    Apple_iPad_BatteryLevel          "Apple/iCloud iPad: Battery Level [%d %%]"                           <battery>   (Apple_iCloud_iPad)    { channel="icloud:device:appleId:ipad:batteryLevel" }
Switch    Apple_iPad_FindMyPhone           "Apple/iCloud iPad: Trigger Find My iPad"                                        (Apple_iCloud_iPad)    { channel="icloud:device:appleId:ipad:findMyPhone", autoupdate="false" }
Switch    Apple_iPad_Refresh               "Apple/iCloud iPad: Force iPad Refresh"                                          (Apple_iCloud_iPad)    { channel="icloud:device:appleId:ipad:location", autoupdate="false" }
Location  Apple_iPad_Location              "Apple/iCloud iPad: Coordinates"                                                 (Apple_iCloud_iPad)    { channel="icloud:device:appleId:ipad:location" }
Number    Apple_iPad_LocationAccuracy      "Apple/iCloud iPad: Coordinates Accuracy [%.0f m]"                               (Apple_iCloud_iPad)    { channel="icloud:device:appleId:ipad:locationAccuracy" }
DateTime  Apple_iPad_LocationLastUpdate    "Apple/iCloud iPad: Last Update [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]"    <time>      (Apple_iCloud_iPad)    { channel="icloud:device:appleId:ipad:locationLastUpdate" }
Switch    Apple_iPad_Home                  "Apple/iCloud iPad: iPad Home"                                       <presence>  (Apple_iCloud_iPad)

String    Apple_Watch_BatteryStatus        "Apple/iCloud Watch: Battery Status [%s]"                            <battery>   (Apple_iCloud_Watch)   { channel="icloud:device:appleId:iwatch:batteryStatus" } 
Number    Apple_Watch_BatteryLevel         "Apple/iCloud Watch: Battery Level [%d %%]"                          <battery>   (Apple_iCloud_Watch)   { channel="icloud:device:appleId:iwatch:batteryLevel" } 
Switch    Apple_Watch_FindMyPhone          "Apple/iCloud Watch: Trigger Find My Watch"                                      (Apple_iCloud_Watch)   { channel="icloud:device:appleId:iwatch:findMyPhone", autoupdate="false" } 
Switch    Apple_Watch_Refresh              "Apple/iCloud Watch: Force Watch Refresh"                                        (Apple_iCloud_Watch)   { channel="icloud:device:appleId:iwatch:location", autoupdate="false" } 
Location  Apple_Watch_Location             "Apple/iCloud Watch: Coordinates"                                                (Apple_iCloud_Watch)   { channel="icloud:device:appleId:watch:location" } 
Number    Apple_Watch_LocationAccuracy     "Apple/iCloud Watch: Coordinates Accuracy [%.0f m]"                              (Apple_iCloud_Watch)   { channel="icloud:device:appleId:iwatch:locationAccuracy" } 
DateTime  Apple_Watch_LocationLastUpdate   "Apple/iCloud Watch: Last Update [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]"   <time>      (Apple_iCloud_Watch)   { channel="icloud:device:appleId:iwatch:locationLastUpdate" } 
Switch    Apple_Watch_Home                 "Apple/iCloud Watch: Watch Home"                                     <presence>  (Apple_iCloud_Watch)

$OPENHAB_CONF$/rules/icloud.rules

Die Rules Datei dient dazu zu definieren, ob die Geräte zu Hause sind oder nicht. Hierzu werden bei einer Veränderung des Standorts die Koordinaten des Geräts mit den Koordinaten meines Wohnorts verglichen. Bei einer Abweichung von mehr als 100 Metern wird der Anwesenheitsstatus auf abwesend gesetzt.

Für die Berechnung der Dezimalkoordinaten für die Home Location habe ich folgende URL verwendet: https://www.gpskoordinaten.de/gps-koordinaten-konverter

rule "Apple iPhone Home/Away Status"
when
   Item Apple_iPhone_Location changed
then
   val PointType home_location = new PointType(new DecimalType(48.1502867), new DecimalType(11.8526639))
   val PointType phone_location = Apple_iPhone_Location.state as PointType
   val int distance = phone_location.distanceFrom(home_location).intValue()
   if ( distance < 100) { Apple_iPhone_Home.postUpdate(ON) } else { Apple_iPhone_Home.postUpdate(OFF) }
end

rule "Apple iPad Home/Away Status"
when
   Item Apple_iPad_Location changed
then
   val PointType home_location = new PointType(new DecimalType(48.1502867), new DecimalType(11.8526639))
   val PointType phone_location = Apple_iPad_Location.state as PointType
   val int distance = phone_location.distanceFrom(home_location).intValue()
   if ( distance < 100) { Apple_iPad_Home.postUpdate(ON) } else { Apple_iPad_Home.postUpdate(OFF) }
end

rule "Apple Watch Home/Away Status"
when
   Item Apple_Watch_Location changed
then
   val PointType home_location = new PointType(new DecimalType(48.1502867), new DecimalType(11.8526639))
   val PointType phone_location = Apple_Watch_Location.state as PointType
   val int distance = phone_location.distanceFrom(home_location).intValue()
   if ( distance < 100) { Apple_Watch_Home.postUpdate(ON) } else { Apple_Watch_Home.postUpdate(OFF) }
end

$OPENHAB_CONF$/transform/icloud.map

In der Sitemap möchte ich den Anwesenheitsstatus nicht als ON/OFF anzeigen lassen sondern als ✔/✘. Zudem soll der Batteriestatus in Deutscher Sprache angezeigt werden. Dazu verwende ich eine Mapping Datei.

// PRESENCESTATE / ANWESENHEITSSTATUS
ON=✔
OFF=✘

// BATTERYSTATE / BATTERIESTATUS
NotCharging=wird nicht geladen
Charging=wird geladen
Charged=vollständig geladen
Unknown=unbekannt

$OPENHAB_CONF$/sitemaps/home.sitemap

In der Sitemap lege ich für jedes Gerät einen Eintrag im Frame Sonstiges unter Anwesenheitsstatus an, um anzuzeigen, ob das Gerät zu Hause ist oder nicht. Darunter zeige ich jeweils die zum Gerät gehörenden Item-Werte an, die ich sehen möchte. Die Standortkarte wird dabei nur eingeblendet, wenn das Gerät unterwegs ist.

Frame   label="Sonstiges" { 
   Text   label="Anwesenheitsstatus"   icon="presence" {
       Text    item=Apple_iPhone_Home   label="Apple iPhone [MAP(icloud.map):%s]"   icon="icloud_iphone" {
           Text      item=Apple_iPhone_BatteryLevel    label="Batterieladung  [%d %%]"            icon="batterylevel"
           Text      item=Apple_iPhone_BatteryStatus   label="Ladezustand [MAP(icloud.map):%s]"   icon="battery"
           Mapview   item=Apple_iPhone_Location        label="Standort"            height=5       icon="icloud_map"     visibility=[Apple_iPhone_Home == OFF]
       }
       Text    item=Apple_iPad_Home     label="Apple iPad [MAP(icloud.map):%s]"     icon="icloud_ipad" {
          Text      item=Apple_iPad_BatteryLevel       label="Batterieladung  [%d %%]"            icon="batterylevel"
          Text      item=Apple_iPad_BatteryStatus      label="Ladezustand [MAP(icloud.map):%s]"   icon="battery"
          Mapview   item=Apple_iPad_Location           label="Standort"            height=5       icon="icloud_map"     visibility=[Apple_iPad_Home == OFF]
       }
       Text    item=Apple_Watch_Home    label="Apple Watch [MAP(icloud.map):%s]"    icon="icloud_iwatch" {
          Text      item=Apple_Watch_BatteryLevel      label="Batterieladung  [%d %%]"            icon="batterylevel"
          Text      item=Apple_Watch_BatteryStatus     label="Ladezustand [MAP(icloud.map):%s]"   icon="battery"
          Mapview   item=Apple_Watch_Location          label="Standort"            height=5       icon="icloud_map"     visibility=[Apple_Watch_Home == OFF]
      }
   }
}

Ein Hinweis noch zu o.g. Szenario:
Bitte beachten, dass die regelmäßige Abfrage der Geräte enormen Einfluss auf die Batterieladezeiten hat. Bei mir hat sich der Zyklus, wann ich z.B. das iPhone laden musste, halbiert. Somit muss man sich genau überlegen, ob diese Funktion der Anwesenheitserkennung wirklich genutzt wird. Ich habe die Funktion inzwischen auch wieder abgeschaltet und verwende das iCloud Binding nicht mehr.

Quellen:
https://www.openhab.org/

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.