FHEM Geräte mittels Google Kalender schalten

Nachdem ich aus meinem Urlaub zurück bin will ich die Gelegenheit direkt einmal nutzen, meine Urlaubsschaltung als Anregung für die Schaltung von Geräten mittels Google Kalender darzustellen. Auf Grund der kürzlichen Änderung des Kalender-Moduls musste ich meine bisherige Urlaubsschaltung leicht modifizieren und habe das zum Anlass genommen, direkt eine etwas generischere Funktion zu realisieren.

FHEM Device mittels Kalender schalten

FHEM Device mittels Kalender schalten

Kalendermodul und seine Ereignisse

Das FHEM Kalendermodul sendet zu den Terminen des verknüpften Kalenders diverse Ereignisse. So wird z.b. „triggered“ gesendet, sobald der Kalender sich updated. Wird ein Kalendereintrag geändert, so wird ein „changed“ Ereignis gesendet. Die interessantesten Ereignisse sind sicherlich „start“ und „end“, die den Start und das Ende eines konkreten Termins signalisieren.

Diese Ereignisse können mittels einer notify-Definition nun ganz einfach zur Schaltung von Geräten in der FHEM Haussteuerung genutzt werden. Für unser Beispiel nehmen wir an, dass wir einen speziellen Google Kalender „Kalender_Aktionen“ für diese Funktion definiert haben.

In FHEM wird dieser Kalender dann mit folgendem Befehl eingebunden:

define Kalender_Aktion CALENDAR ical url https://www.google.com/calendar/ical/euregooglecalenderurl.calendar.google.com/private-euercode/basic.ics 14400 

Mit der Angabe 14400 wird der Kalender alle 4 Stunden aktualisiert. Das sollte in der Regel ausreichend sein und dient in erster Linie der Ermittlung von Kalenderänderungen.

Auf ein Kalender-Ereignis reagieren

Nun wollen wir ja feststellen, wann ein Termin startet oder beendet wird. Hierzu wird ein entsprechendes notify definiert. In meinem Fall frage ich beide Zustände mit einem notify-Befehl ab. Man könnte natürlich aber jeweils ein notify für den Start bzw. das Ende eines Termin definieren.

define notKalender_Aktion notify Kalender_Aktion:(start|end):.* { KalenderAktion($EVTPART0, $EVTPART1)}

In den geschweiften Klammern habe ich meine Funktion eingefügt, die sich dann um die konkrete Steuerung kümmert. Im einfachsten Fall könnte man die Schaltaktion auch direkt hier eintragen und keine extra Funktion aufrufen. In der Kalendermodulbeschreibung gibt es ein entsprechendes Beispiel, so dass ich hier nicht näher darauf eingehe.

Ich wollte aber eine etwas generischere Funktion nutzen und zum Beispiel nicht die Devicenamen selbst in den Kalender eintragen. Für meine Urlaubsschaltung nutze ich z.B. einen Dummy. Meine Dummy beginnen immer mit „du“, so dass der Name also „duUrlaub“ lautet. Im Kalender möchte ich aber nur „Urlaub“ oder „Besuch“ eintragen und damit entsprechende Aktionen schalten.

Funktion zur Steuerung der Aktionen

Damit die nachfolgend dargestellte Funktion ihren Dienst auch korrekt vollzieht, sollten die zu schaltenden Geräte mittels „on“ und „off“ ein- bzw. ausgeschaltet werden können. Dies ist eigentlich bei den meisten Geräten der Fall. Bei der ursprünglichen Definition meines Urlaubs Dummy hatte ich aber die Werte „ja“ und „nein“ mit einem „setlist“ definiert. In diesem Fall musste ich mit dem Attribut „EventMap“ noch eine entsprechende Übersetzung einbauen (ja:on nein:off).

Die Kalender Funktion zur Steuerung der FHEM Geräte sieht nun wie folgt aus und sollte sich hoffentlich selbst erklären:

#
# Kalenderfunktion zur zeitgesteuerten Schaltung von Devices
#
sub
KalenderAktion($$)
{
   my ($KalenderEreignis, $KalenderUids) = @_;
   my @uids=split(/;/,$KalenderUids);
   my $aktion;
   my @DeviceList = ("Urlaub","Besuch"); #Einträge im Kalender
   my @DeviceNames = ("duUrlaub", "duGast"); #Übersetzung zum Device

   if($KalenderEreignis eq "start:") { $aktion = "on" } else { $aktion = "off" }

   #falls mehrere Termine gleichzeitig starten, diese nun durchlaufen
   foreach my $uid (@uids)
   {
      #Summary auslesen und prüfen, ob es sich um ein Device handelt
      my $Device = fhem("get Kalender_Aktion summary $uid");

      #falls das Device existiert, so wie es im Kalender steht kann die Schaltung direkt erfolgen
      if( defined($defs{$Device}) )
      {  fhem("set $Device $aktion"); }
      else
      {
         #wenn ein entsprechendes Device gefunden wird
         if (true { /$Device/ } @DeviceList)
         { fhem("set $DeviceNames[ first_index { /$Device/ } @DeviceList ] $aktion"); }
      }
   }
}

Damit nun die Geräte zum richtigen Zeitpunkt geschaltet werden trägt man nur die entsprechenden Bezeichnungen im Google Kalender ein. Natürlich könnte man die Funktion noch erweitern, um komplexere Schaltungen zu realisieren. Wenn Geräte z.B. nicht nur einfach mittels on/off geschaltet werden können, müsste man diese explizit abfragen und die entsprechende Schaltfunktion einbauen.

Denkbar ist auch die Ergänzung der Kalendereinträge um weitere Schaltinformationen. So könnte man z.B. eintragen „Devicename on-for-timer 300“. In diesem Fall muß man dann den Summary noch weiter untersuchen und die Aktion entsprechend anpassen.

Ich selbst nutze die Funktion allerdings aktuell tatsächlich in erster Linie für eine spezielle Steuerung meiner Geräte während der Urlaubsabwesenheit. So wird der Wecker ignoriert und die Rolladen zu einer festgelegten Zeit hochgefahren oder Abends per Zufallssteuerung das Flurlicht geschaltet.

18 comments

  1. Hey Jürgen,
    wieder ein toller Artikel. Mich würde es sehr freuen, wenn du in einem deiner nächsten Artikel deine Sonos Integration vorstellen könntest. Bei mir läuft sie mit FHEM leider nicht so rund und hackt in jeglicher Hinsicht. Sei es das Cover oder die Auswahl der Playlisten.

    Lieben Gruß
    Thorben

  2. Hallo Juergen
    Möchte dich auf einen Fehler in deinem Code hinweisen.
    Deine Subrutine heisst „KalenderAktion“, sollte aber „Kalender_Aktion“ heissen

    Gruss und Danke für deine tolle Arbeit
    Jonas

  3. Danke für den Hinweis. Wird sofort angepasst.

  4. Hallo Jürgen

    Sehr cool und beschäftigt sich genau mit dem was ich in gerade am Planen bin, aber erst einmal ein paar andere Projekte zu Ende bringen. Im Moment hole ich mir da eher ein paar Ideen.
    Bei mir sieht es so aus das ich an den unterschiedlichsten Tagen zu unterschiedlichen Zeiten aufstehen muss und mein Wecker dank des Google Kalenders immer weiß wann ich aus den Federn muss… ein paar nützliche Erweiterungen schwirren mir da bereits im Kopf herum um morgens freundlicher geweckt zu werden. Quasi ein intelligentes Wecksystem welches erst einmal meine Jalousie auf fährt, einen Helligkeitsabgleich durchführt und je nach Bedarf eine Aufstehfreundliche Beleuchtung zuschaltet (Im Winter ist es ja üblicherweise morgens gegen 4 noch ziemlich dunkel). Dem nachgeschaltet eine leichte Weckmelodie die sich weiter spinnen lässt bis maximale Beleuchtung an und ordentlich Metal auf die Ohren.
    Wie schwierig schätzt du die Programmierung für jemand ein der mit FHEM und Raspberry Pi eher keine Erfahrung hat aber gewillt ist sich da durchzubeißen und nicht gleich bei den ersten Fehlversuchen aufgibt? Bis jetzt spiele ich eher mit Arduino und bringe mir da auch alles irgendwie selbst bei und freue mich am Ende umso mehr wenn Fehler aus dem Sketch behoben sind und alles funktioniert.

  5. Ich denke, dass eine solche Umsetzung grundsätzlich relativ einfach machbar ist. Ich selbst bin auch kein Perl Profi und mit den vielen Code-Beispielen in der FHEM Community kann man jede Menge lernen. Außerdem sind dort alle sehr hilfsbereit. Wahrscheinlich ist die eigentliche Herausforderung die Ansteuerung der jeweiligen Geräte bzw. deren Einbindung in FHEM. Für die Ermittlung der Helligkeit oder Sonnenauf-/untergangszeiten gibt es diverse Module. Einfach mal die Wetter-Module oder das Twilight-Modul prüfen.

  6. Hi,
    ich habe nach deinen angaben meinen Google Kalender eingerichtet. Das schalten der Geräte klappt. Wie mache ich das , wenn ich meine Rolladen im Urlaub darüber steuern will. Die kennen als Befehl nur up und down.

  7. Wenn du meinen Code übernommen hast, dann kannst du in der Funktion statt „on“ deinen BEfehl „up“ eintragen und für „off“ den Text „down“ ersetzen. Eine weitere Variante wäre es, den Rolladen mit dem „eventmap“ Attribut weitere Schaltbefehle zu verpassen. Zum Beispiel mit:

    attr ROLLADE eventMap up:on down:off

    Damit müssten sich die Rolladen auch mit on und off schalten lassen.

  8. Hallo.
    Interessanter Artikel aber leider für Anfänger nicht so geeignet. Es fehlt noch wie man die Dummy verknüpfen muss, der Artikl umfasst nur den Kalender und das Notify, was nur die Hälfte ist. Jemand wie ich, der sich mit der Sache noch nicht auskennt, steht da ganz schön auf dem Schlauch.

  9. Das mit dem Dummy ist ja nur eine mögliche Option, die ich bei mir als „Merker“ nutze. Durch den entsprechenden Kalendereintrag wird zum Beispiel ein Dummy duUrlaub auf „on“ oder „off“ gesetzt. Diesen Dummy nutze ich dann in diversen anderen Funktionen und frage zum Beisiel ab, ob ich gerade in Urlaub bin. Dann wird zum Beispiel Abends eine Zufallsschaltung für das Flurlicht aktiviert.

    Als Einführung für den Umgang mit FHEM ist darüber hinaus das sehr gute Wiki und das FHEM Forum zu empfehlen.

  10. Wie ich einen Dummy erstelle und die Optionen wie eventmap, setlist oder webcmd sind mir bekannt und habe ich auch verstanden.
    Ich habe nach der Anleitung hier im Blog den Kalender eingerichtet, Google Kalender nutze ich schon lange und war somit kein Problem einen weiteren zu erstellen. Dann habe ich das notify erstellt und die myUtils mit der Funktion erweitert. myUtils neu geladen und gewartet bis der Zeitpunkt zum schalten des Dummy da war aber es tut sich nichts, der Dummy wird nicht geschaltet und im Log habe ich auch nichts stehen.
    Also suche ich gerade nach dem Fehler und dazu finde ich keine Hinweise oder Tipps im Blog und die Einführung in Fhem ist da auch nicht hilfreich. Deswegen währe es gut zu wissen, wie der Dummy mit dem notify verbunden sein muss. Ich habe den Dummy dem notify per RegexpPart mit * hinzugefügt.

  11. OK, dann habe ich jetzt verstanden, wo dein Problem liegt. Lösen kann ich es aber nicht so ohne Weiteres, da eigentlich alle Infos hierzu im Artikel stehen und irgendetwas davon bei dir nicht funktioniert. Streng genommen gibt es keine direkte Verbindung zwischen dem notify und dem „Dummy“ bzw. jedem anderen Gerät, welches man schalten will. Das notify für den Kalender dient dazu, bei einer Kalenderaktion festzustellen, ob im Kalender ein Device eingetragen ist und dieses dann zu schalten. Hierzu wird die Funktion „KalenderAktion“ aufgerufen, die dann das Schalten übernimmt. Es wäre also mal zu prüfen, ob die Funktion richtig aufgerufen wird und was in der Funktion passiert. Hierzu solltest du einfach mal ein paar Log-Einträge hinzufügen (z.B. Log3 undef, 3, „Aufruf der Funktion“)

  12. Ah, okay.
    Dann liegt der Fehler glaube ich im Kalender, weil da scheint nicht alles anzukommen. Mache ich ein Update, sieht es wie folgt aus:
    2016-10-01 08:23:53 Calendar Kalender_Aktion calname: Kalender_Aktionen
    2016-10-01 08:23:53 Calendar Kalender_Aktion lastUpdate: 2016-10-01 08:23:52
    2016-10-01 08:23:53 Calendar Kalender_Aktion all: 5krtdvo5qhpq82tj8dbi706r74googlecom;ckrm8chmcoqj0bb371hm8b9k6kr68b9o6orm8bb560rjacpm6go66e1o74googlecom;imvlr2fnhh2egrmgttv9dm3qeogooglecom;mm4890uor8obrpo6useckfbet8googlecom;s0rn77301e6jhiiff2kbjm7gdcgooglecom
    2016-10-01 08:23:53 Calendar Kalender_Aktion stateNew:
    2016-10-01 08:23:53 Calendar Kalender_Aktion stateUpdated:
    2016-10-01 08:23:53 Calendar Kalender_Aktion stateDeleted:
    2016-10-01 08:23:53 Calendar Kalender_Aktion stateChanged:
    2016-10-01 08:23:53 Calendar Kalender_Aktion lastCheck: 2016-10-01 08:23:52
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeUpcoming: 5krtdvo5qhpq82tj8dbi706r74googlecom;ckrm8chmcoqj0bb371hm8b9k6kr68b9o6orm8bb560rjacpm6go66e1o74googlecom;s0rn77301e6jhiiff2kbjm7gdcgooglecom
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeAlarm:
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeAlarmed:
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeAlarmOrStart: imvlr2fnhh2egrmgttv9dm3qeogooglecom;mm4890uor8obrpo6useckfbet8googlecom
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeChanged:
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeStart: imvlr2fnhh2egrmgttv9dm3qeogooglecom;mm4890uor8obrpo6useckfbet8googlecom
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeStarted:
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeEnd:
    2016-10-01 08:23:53 Calendar Kalender_Aktion modeEnded:
    Und wenn ich das jetzt richtig verstanden habe, sollte da ein Eintrag Urlaub zu sehen sein.

  13. Nicht ganz. Im Kalender tauchen nur die Ids zu deinen Terminen auf. Wenn ich es richtig sehe, stehen hier drei kommende und zwei gestartete Termine drin. In der Funktion KalenderAktion wird dann ermittelt, welches Summary (das ist der Betreff des Kalendereintrags) zu einer ID gehört. Ich füge mal meine aktuelle Fuktion hinzu, die auch ein paar Logeinträge hat.

    #
    # Kalenderfunktion zur zeitgesteuerten Schaltung von Devices
    #
    sub
    KalenderAktion($$)
    {
       my ($KalenderEreignis, $KalenderUids) = @_;
       my @uids=split(/;/,$KalenderUids);
       my $aktion;
       my @DeviceList = ("Urlaub","Besuch"); #Einträge im Kalender
       my @DeviceNames = ("duUrlaub", "duGast"); #Übersetzung zum Device
    
    Log3 undef, 3, "Kalenderereignis:".$KalenderEreignis;
    
       if($KalenderEreignis eq "start:") { $aktion = "on" } else { $aktion = "off" }
    
    Log3 undef, 3, "Kalenderaktion:".$aktion;
    
       #falls mehrere Termine gleichzeitig starten, diese nun durchlaufen
       foreach my $uid (@uids)
       {
          #Summary auslesen und prüfen, ob es sich um ein Device handelt
          my $Device = fhem("get Kalender_Geburtstage summary $uid");
    
    Log3 undef, 3, "Kalendersummary:".$Device;
    
          #falls das Device existiert, so wie es im Kalender steht kann die Schaltung direkt erfolgen
          if( defined($defs{$Device}) )
          {
    Log3 undef, 3, "Kalender Device existiert";
    
              fhem("set $Device $aktion");
          }
          else
          {
             #wenn ein entsprechendes Device gefunden wird
             if (true { /$Device/ } @DeviceList)
             {
    Log3 undef, 3, "Kalender Device wurde gefunden: ".$DeviceNames[ first_index { /$Device/ } @DeviceList ];
    
                fhem("set $DeviceNames[ first_index { /$Device/ } @DeviceList ] $aktion");
             }
          }
       }
    }
    

    Darüber hinaus habe ich nochmal nachgedacht, welche Fragestellung du wirklich hast. Evtl. habe ich es doch noch nicht richtig interpretiert. Schaltet dein Dummy den den Status auf „on“ oder „off“? Wenn ja, möchtest du dann vielleicht irgend etwas tun, wenn dieses Ereignis eintritt und möchtest dafür ein notify? Wenn das der Fall ist, dann würde ich allerdings ersteinmal sagen, dass du den Umweg über den Dummy gar nicht gehen musst. In diesem Fall solltest du in der Funktion KalenderAktion direkt den gewünschten Befehl eintragen.

  14. Okay, versuche mal meinen Wunsch zu beschreiben.
    Ich habe mehrere Terrarien und die brauchen verschiedene Versorgungen.
    Deswegen möchte ich im Kalender zum Beispiel rein schreiben Schlangen und dann soll ein Dummy auf on gesetzt werden. Dieser Dummy sagt mir dann, die Schlangen müssen gefüttert werden und danach will ich den dummy von Hand auf aus setzen.
    Um das jetzt zu testen, habe ich erstmal die Einträge von dir übernommen, Urlaub und Gast, wenn es klappt, wollte ich die Einträge in der myUtils dementsprechend ändern. Zum test habe ich auch in den Kalender Einträge geschrieben, names Urlaub und Gast.
    Kurz gesagt, will ich mir ne Aufgabenliste in Fhem erstellen, die ich dann in der FTUI über Buttons anziegen lasse, da ich neben meiner eingangstür ein tablet hängen habe, wo ich beim betreten immer direkt drauf schaue.

  15. Alles klar. Dann müsste es allerdings quasi mit meiner Funktion klappen. Denn im Prinzip wird hier ja nichts anderes gemacht, als ein Dummy zu einem bestimmten Zeitpunkt auf „on“ zu setzen. Wäre evtl. noch die Frage, wie der Termin in deinem Kalender eingetragen ist. Sobald der Termin beendet ist, wird der Dummy mit meiner Beschreibung ja auch wieder ausgeschaltet. Wenn der Zeitraum also sehr kurz ist, dann bekommt man evtl. gar nicht mit, das der Dummy geschaltet wurde.

    Dies kann dann nur verhindert werden, wenn man z.B. „Tagestermine“ einträgt oder in der Funktion dafür sorgt, dass bei Beendigung des Termin keine „off-Schaltung“ durchgeführt wird.

  16. Die Termine beziehen sich nur auf Tage, weil ich nicht immer zur gleichen Uhrzeit füttere, Futter kommt in der Natur ja auch nicht nach Minutenzeitplan vorbei. Und andere dinge an Terrarien sind mindestens zwei Stunden, wobei ich der Meinung bin, das man das abschalten bestimmt unterbinden kann, wenn man die Subroutine etwas verändert, Habe jetzt die neue Funktion von Dir eingesetzt und den meiner Meinung nach vorhanden Fehler mit dem Eintrag Kalender_Geburtstage auf Kalender_Aktion geändert.
    Aber es tut sich nciht, im Log steht nur Kalender wakup und chekc und der notify taucht gar nciht im Log auf und im Eventmonitor ist auch nichts zu sehen.

  17. Okay. Ich habe jetzt mal meine Funktion nochmal getestet, ob diese überhaupt noch funkioniert und tatsächlich einen Fehler gefunden, den ich nicht ganz erklären kann, der aber eigentlich nichts mit deinem Problem zu tun hat. Bei mir hat er in der Funktion KalenderAktion die Funktionen „true“ und „first_index“ angemeckert. Diese sind wohl in einer bestimmten Library, die anscheinend nicht geladen wurde. Dieses Problem habe ich nun beheben können, in dem ich in der myutils ganz oben bei den „use“-Angaben folgendes eingetragen habe:

    use List::MoreUtils qw{
            true first_index
        };
    

    Nun versuchen wir mal deinem Problem auf die Schliche zu kommen. Dazu sollten wir mal schrittweise vorgehen:

    1. Trag einen Testtermin „TEST“ in deinen Google-Kalender ein, der möglichst nah an der aktuellen Zeit liegt – also in ein paar Minuten starten würde.
    2. In FHEM gehst du nun zu deinem Kalender und führst ein reload durch
    3. Nun rufst du den Event-Monitor auf und zur ZEit des Kalendereintrags sollten hier ein paar Calendar Events auftauchen
    4. Nun schaust du dir wieder deinen Kalender in FHEM an. Hier sollte bei dem notify-Eintrag (Im Abschnitt „Probably Associated“), der die Funktion „KalenderAktion“ aufruft auch die Uhrzeit drin stehen.
    5. Wenn die Uhrzeit erscheint hätte nun eigentlich die Kalenderfunktion aufgerufen werden müssen und einer der Logeinträge sollte im Logfile auftauchen

    Eine Anmerkung noch. In der Funktion „KalenderAktion“ wird ein get ausgeführt. Hier muss natürlich der Name aus dem Define des zugeordneten Kalenders in FHEM stehen. Bei mir heißt dieser Kalender „Kalender_Geburtstage“ und muß richtigerweise auf die eigene Definition angepasst werden.

    Wenn wir jetzt heraus bekommen, wo bei dir im oberen Ablauf etwas hakt, können wir weiter nach dem Fehler schauen.

  18. Wenn ich die Funktion in der myUtils einbinde, erhalte ich beim speichern eine Fehlermeldung, das ich keine moreUtils habe.
    Habe Dir mal eine Einladung zu einem Hangout geschickt, da ich Deinen Blog nicht voll müllen will.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Why ask?

Allnet Flat 728x090
x

Check Also

FHEM Tablet UI – Testumgebung als Schutz vor umfangreichen Updates

Aktuell bin ich dabei, meine Tablet UI Umgebung zu optimieren und die Dateien für eine ...

Durch die weitere Nutzung der Seite stimmen Sie der Verwendung von Cookies zu. Mehr Infos

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um Ihnen das beste Surferlebnis zu ermöglichen. Wenn Sie diese Website ohne Änderung Ihrer Cookie-Einstellungen verwenden oder auf "Akzeptieren" klicken, erklären Sie sich damit einverstanden.

Schließen