Posts für Suchanfrage kalender werden nach Relevanz sortiert angezeigt. Nach Datum sortieren Alle Posts anzeigen
Posts für Suchanfrage kalender werden nach Relevanz sortiert angezeigt. Nach Datum sortieren Alle Posts anzeigen

Mittwoch, 18. Juli 2018

Kalender in FHEM einbinden

Die älter Bereitstellung des Link habe ich bereits hier gezeigt. In der neuen Form des Google Kalenders gibt es den grünen iCal Button nicht mehr, der Link steht jetzt unter Einstellungen/<Kalendername>/Kalendereinstellungen und dort weit unten in der Box:
Privatadresse im iCal Format
Darunter steht der wichtige Hinweis:
Mit dieser Adresse können Sie von anderen Anwendungen aus auf den Kalender zugreifen, ohne ihn öffentlich zu machen.

Das Kalender Modul in FHEM ist aktuell überarbeitet und die Funktionen sind erweitert und geändert worden. Mittlerweile weiß ich, dass es keine gute Lösung ist ein Modul einzusetzen, welches auf einem anderen Modul aufsetzt aber völlig getrennt von dem entwickelt wird. Man schafft unnötig Abhängigkeiten.
Bei der Einbindung eines Kalenders in FHEM sollte man sich über den praktischen eigenen Umgang mit dem Kalender und dem Aktualisierungsintervall (Standard 1 h) Gedanken machen. Ein Abfallkalender der sich das ganze Jahr praktisch nicht ändert muss entweder nie oder höchsten 1 mal Tag aktualisiert werden.

1. Beispiel: 

Signalisierung der Abfalltonne, Aktualisierung einmal am Tag
define AbfallKalender Calendar ical url https://... 86400
Dann brauchen wir ein Gerät wo die aktuelle Tonne drin steht, im einfachsten Fall ein Dummy
define Tonne dummy
Und ein Timer der einmal am Tag den Kalender ausliest und das Ergebnis ablegt.
define a_Tonne at *12:00:00 set Tonne {(my $evt=fhem('get AbfallKalender events format:custom="$S" limit:from=1d,to=1d');;;;$evt?$evt:"0")}
Die Funktion:
  • Am Mittag den Ganztagestermin für morgen auslesen -> limit:from=1d,to=1d
  • Nur den Textinhalt des Eintrages lesen -> format:custom="$S"
  • $evt?$evt:"0" -> Falls kein Termin gefunden wird, wird der dann leere String durch eine 0 ersetzt.
  • Den resultierenden Text in den Dummy Tonne schreiben.
Damit kann man am Vortag des Termines ein Aktion auslösen: z.B. Nachmittag den Hinweis geben: die Tonne muss morgen raus. Und am Morgen des Termines kann man nochmal den Hinweis geben: die Tonne muss heute raus. Der Zeitpunkt im Timer entscheidet über das Auftauchen und Verschwinden des Inhaltes von der "Tonne".
Hinweis:
Bei Perl Code innerhalb von einem at Kommando müssen die ; verdoppelt werden, im define müssen sie auch verdoppelt werden, deshalb ;;;; !
Bei Perl Code im set Befehl muss eine zusätzliche Klammer () stehen, sonst wird der Perlausdruck als String gesehen: set Tonne {3+5} ergibt {3+5} im Dummy, set Tonne {(3+5)} ergibt 8 im Dummy.

2. Beispiel: 

Im Kalender stehen FHEM Device Namen (z.B. Aktoren), die Terminzeiten sind die Schaltzeiten.
Das Beispiel gilt für Einzeltermine (eigene uid). Serientermine haben eine uid für alle Termine, hier muss man weiter filtern(limit:from ...).
Der Kalender mit stündlicher Aktualisierung:
define TestKalender Calendar ical url https://... 
Dann wiederum ein Dummy:
define Urlaub dummy
Und ein notify, welches exakt zu Beginn (start) und Ende (end) des Einzeltermines den Dummy auf on oder off setzt. (Code für die Raw Def)
define n_TestKalender notify TestKalender:changed:.* {\
  my $cmd ='on';;\
  $cmd = 'off' if ($EVTPART2 eq 'end');;\
  my $actor = fhem('get '.$NAME.' events format:custom="$S" filter:uid=="'.$EVTPART1.'" limit:count=1');;\
  fhem("set $actor $cmd");;\
}

Funktion
Das Calendar Modul wirft zum Zeitpunkt des Termines ein paar Events, davon spricht das notify genau auf diese Beiden an:
2018-07-16 16:25:00 Calendar TestKalender changed: 123456googlecom start
...
2018-07-16 16:30:00 Calendar TestKalender changed: 123456googlecom end
Der Event hat drei Teile:
  • $EVTPART0 ist uninteressant, 
  • $EVTPART1 enthält die ID des Eintrages und 
  • $EVTPART2 "start" bzw. "end".

Mit Hilfe der ID wird der Kalendertext gelesen und mit den umgewandelten "on" (start) und "off" (end) Befehlen das Device in FHEM gesetzt.
Warum sieht der Befehl so kompliziert aus?

  • Der uid/format String muss im String die doppelten Anführungszeichen enthalten! Damit dies funktioniert, muss der gesamte Befehl in ' ' gesetzt werden. Innerhalb werden dann zwar " akzeptiert aber keine Variablen mehr aufgelöst. Diese muss man hier mit Verkettung/concatenation einbauen.

Weiter unten habe ich eine (für den Anfänger) besser lesbare Variante eingebaut.

Komplexen Code auslagern

Für komplexeren Code sollte man alles in die 99_myUtils auslagern und im notify lediglich die wichtigen Parameter übergeben:
define n_TestKalender notify TestKalender:changed:.* {KalenderSub($EVTPART1,$EVTPART2,$NAME)} 
Das folgende Beispiel filtert das Ereignis (Devicenamen) "Urlaub" aus dem Kalender und setzt das gleichlautendes Device bei Start und Ende auf ja /nein. Alle anderen Events werden zwar getriggert aber verworfen.
Die sub kann man beliebig komplex gestaltet. Damit der get Befehl lesbar bleibt, habe ich alles in extra Variablen gepackt. (Code für die 99_myUtils.pm)
sub KalenderSub ($$$)
   {
     my ($uid,$cmd,$cname) = @_;
     #Logging der Paramter bei Bedarf;     #Log 1, "uid: $uid | Start/End: $cmd | cal: $cname";
     my $format = '"$S"';
     my $dev = 'Urlaub';
     $uid='"'.$uid.'"';
     $cmd = 'ja' if ($cmd eq 'start');
     $cmd = 'nein' if ($cmd eq 'end');
     
     my $actor = fhem("get $cname events format:custom=$format filter:uid==$uid limit:count=1");
     # Unterschiedliche Abfragen auf ist exakt oder enthält möglich;
     #fhem("set $actor $cmd") if ($actor eq $dev);
     if ($actor =~ /$dev/) {fhem("set $dev $cmd")};
}

Tipp

Der Calendar Aufruf wird mit Level 3 geloggt, wenn man das nicht möchte hängt man an den Befehlsaufruf einfach noch ",1" an.
fhem("Befehl",1)

Weitere Infos:
Forum
Wiki

Montag, 7. Januar 2019

Kalender in FHEM - auf bestimmte Termine reagieren

Die Grundlage schaffen - ein Calendar Device

Für dieses Beispiel: ein Google Kalender. Als Grundlage brauchen wir die "Privatadresse" im iCal Format (Google Kalender Einstellungen/<Kalendername>/Kalendereinstellungen).
Diese URL wird einfach in die Calendar Definition eingesetzt, das Aktualisierungsintervall setze ich auf einen Tag. Man kann jederzeit ein reload des Kalenders durchführen. Man muss bedenken, dass vor allem viele Serientermine, eine nicht unerheblich Zeit beim reload beanspruchen. Das kann schnell mal mehrere Minuten dauern. In der Grundeinstellung erfolgt das blockierend. Je nach Kalender, kann also nach dem define die Oberfläche für ein paar Minuten "stehen"!
define TestKalender Calendar ical url https://calendar.google.com/calendar/ical/xxx/basic.ics 86400
Um zu testen, ob der Kalender richtig gelesen wird, kann man ihn jetzt einfach abfragen. Eine direkte Anzeige der Termine in Readings erfolgt nämlich nicht.

Abfragen machen

Die Abfrage der Termine ist nicht offensichtlich, es gibt aber einige Beispiele in der englischen Doku. Als Ausgangspunkt für mein Beispiel nehme ich mal die Weboberfläche. In der zweiten Auswahlbox in der get Zeile wählt man einfach events aus.
Als Ergebnis bekommt man in einer Box eine Liste der Kalendereinträge (events), ich habe heute (6.1.) drei Einträge drin. Wie man sieht, auch vergangene.
04.01.2019 08:00 4h Sprechstunde
06.01.2019 08:00 14h Heute frei
07.01.2019 08:00 11h Sprechstunde
In der leeren Box kann man weiter format und filter Angaben machen.

Das Ziel in diesem Beispiel soll sein, auf einen ganz bestimmten Eintrag im Kalender zur Startzeit des Termins etwas auszulösen: z.B. den Server an den Tagen wo Sprechstunde ist, kurz vor Arbeitsbeginn zu starten.

Event auswählen

Dazu erzeugt man am Besten einen Termin in naher Zukunft und schaut sich mit dem Eventmonitor die Events an:
2019-01-06 20:00:00 Calendar TestKalender changed: 79vs3fq7siulo1hskdn4gtht7kgooglecom start
2019-01-06 20:00:00 Calendar TestKalender start: 79vs3fq7siulo1hskdn4gtht7kgooglecom 
2019-01-06 20:00:00 Calendar TestKalender modeUpcoming: 7fcbh4r7snu7iqovask7l8oq9qgooglecom
2019-01-06 20:00:00 Calendar TestKalender modeAlarmOrStart: 44318rlssm81janveuga0olanpgooglecom;79vs3fq7siulo1hskdn4gtht7kgooglecom
2019-01-06 20:00:00 Calendar TestKalender modeChanged: 79vs3fq7siulo1hskdn4gtht7kgooglecom
2019-01-06 20:00:00 Calendar TestKalender modeStart: 44318rlssm81janveuga0olanpgooglecom;79vs3fq7siulo1hskdn4gtht7kgooglecom
2019-01-06 20:00:00 Calendar TestKalender modeStarted: 79vs3fq7siulo1hskdn4gtht7kgooglecom
2019-01-06 20:00:00 Calendar TestKalender triggered
2019-01-06 20:00:00 Calendar TestKalender nextWakeup: 2019-01-06 20:05:00
2019-01-06 20:05:00 Calendar TestKalender changed: 79vs3fq7siulo1hskdn4gtht7kgooglecom end
2019-01-06 20:05:00 Calendar TestKalender end: 79vs3fq7siulo1hskdn4gtht7kgooglecom 
2019-01-06 20:05:00 Calendar TestKalender modeAlarmOrStart: 44318rlssm81janveuga0olanpgooglecom
2019-01-06 20:05:00 Calendar TestKalender modeStart: 44318rlssm81janveuga0olanpgooglecom
2019-01-06 20:05:00 Calendar TestKalender modeStarted: 
2019-01-06 20:05:00 Calendar TestKalender modeEnd: 26aq76ljdgjfmo444466faml09googlecom;79vs3fq7siulo1hskdn4gtht7kgooglecom
2019-01-06 20:05:00 Calendar TestKalender modeEnded: 79vs3fq7siulo1hskdn4gtht7kgooglecom
2019-01-06 20:05:00 Calendar TestKalender triggered
2019-01-06 20:05:00 Calendar TestKalender nextWakeup: 2019-01-06 22:00:00
Man sieht jeweils 9 Events beim Start des Termines und 9 Events beim Ende. Allerdings keine Information über den "Lesbaren" Inhalt des Termines, diese kann man mittels der uid ($EVTPART1) auslesen. Es gibt zwei Events, jeweils den ersten und zweiten, die für einen trigger interessant sind.
TestKalender:changed:.*
TestKalender:changed:.*start
TestKalender:start:.*
Beim ersten regExp müsste/könnte man mit $EVTPART2 im Code abfragen ob es start oder end war. Bei den beiden anderen wird eindeutig auf start|end|alarm getriggert.

Exakte Abfrage auf einen Termin

Jetzt kann man im Code noch exakt abfragen, ob es sich um den richtigen Kalendereintrag handelt.
fhem('get '.$NAME.' events filter:uid=="'.$EVTPART1.'",field(summary)=~"(?i)sprechstunde" limit:count=1,from=0',1)
Die eigentliche Aktion ist damit recht simpel. Wenn die Abfrage des Events exakt genug ist, liefert sie nur bei Übereinstimmung ein Ergebnis. Damit sind alle notwendigen Komponenten komplett.
{fhem("set Server on") if defined fhem('get '.$NAME.' events filter:uid=="'.$EVTPART1.'",field(summary)=~"(?i)sprechstunde|notdienst" limit:count=1,from=0',1)}

Starte das Gerät zum Zeitpunkt

Ein notify, welches zu Beginn eines Kalenderevents, der den Begriff "Sprechstunde" in der Terminbeschreibung enthält, den Server startet:
define n_TestKalender notify TestKalender:changed:.*start {\
fhem("set Server on") if defined fhem('get '.$NAME.' events filter:uid=="'.$EVTPART1.'",field(summary)=~"(?i)sprechstunde" limit:count=1,from=0',1)\
}
Die Sache hat noch einen Schönheitsfehler: Die Sprechstunde beginnt zwar um 8:00 Uhr aber es wäre gut, wenn der Server  schon gestartet ist, wenn alle Mitarbeiter den Dienst beginnen. Dazu brauchen wir den Event nicht exakt zum Termin sondern vorher. Das kann das Calendar Modul erledigen. Mit diesem Attribute wird ein zusätzlicher alarm Event eine Stunde (3600 sec) vorm Termin in Abhängigkeit der Terminbeschreibung erzeugt.
attr TestKalender onCreateEvent { $e->{alarm}= $e->{start}-3600 if($e->{summary} =~ m/Sprechstunde/i)}

Starte das Gerät vor dem Zeitpunkt

Der Trigger im notify muss lediglich von start auf alarm geändert werden, der Ausführungsteil bleibt  identisch.
defmod n_TestKalender notify TestKalender:changed:.*alarm {}
Der Event für start und end bleibt erhalten, zu diesem Zeitpunkt kann man andere Aktionen ausführen.

Noch ein paar zusätzliche Tipps und Infos

Serientermine einer Serie (z.B. jeden Mittwoch 8:00) haben alle die gleiche UID. Bei einem Einzeltermin hätte man im notify über die uid den konkreten Zugriff auf genau den Termin, beim Serientermin erscheinen alle Termine der Serie, auch vergangene! Diese uid bleibt auch erhalten wenn man mal einen Termin der Serie modifiziert (Beschreibung, Zeit usw.)
Die Modi (alarm|start|end|upcoming) sind transient und geben quasi Auskunft über den aktuellen Status eines Termins (get <Kalender> events filter:mode=="<modus>").
  • upcoming - der Termin liegt in der Zukunft
  • end - der Termin ist abgelaufen und liegt in der Vergangenheit
  • start - der Termin ist gerade aktiv
  • alarm - die Alarmphase ist aktiv, also der Event alarm ist vorüber, der Event start noch nicht erreicht.
Achtung: will man auf end triggern und den Termin überprüfen (z.B. Inhalt von summary) dann darf  hideOlderThan nicht auf 0 stehen! Man kann sich leicht mit 1 oder 2 (in sec) behelfen. Nach dem end Event ist der Termin aus der Liste verschwunden und nicht mehr lesbar! 

Noch ein paar Codebeispiele

toDo

Tipp: Die Abfrage der Alarmzeit funktioniert z.B: mit
get TestKalender events filter:mode=="alarm" format:full limit:count=1,from=0
Will man die Tage bis zum nächsten Event wissen (hier einfach der nächste, man kann den Filter natürlich anders setzen). In einer verschachtelten zweiten Abfrage wird dann noch 1 in "morgen" und 0 in "heute" gewandelt.
{my $day = int((fhem('get '.$name.' events format:custom="$t1" limit:from=0,count=1',1) + 86399 - time)/86400);
$day?eval{$day>1?$day:"morgen"}:"heute"}
Will man z.B. die Geburtstage aus dem Google Kontakten in einen ical Kalender kopieren, habe ich hier ein Google Script gefunden. Direkt hat man leider dafür keine ical Adresse verfügbar.

Donnerstag, 22. Mai 2025

Meine Kontakte - mein Geburtstagskalender

irgendwann vor ca. einem Jahr begann es: in meiner "Umgebung" verschwanden die Geburtstage im Google Kalender. Offenbar kein Einzelfall, sondern von langer Hand geplant, wie der Artikel  bei Heise zeigt. Der Workaround im Artikel hat damals funktioniert, mittlerweile nicht mehr. Verstanden habe ich die ganze Sache gar nicht - vor allem warum es noch nie eine gute Idee gewesen sein soll, den Geburtstag beim Kontakt zu speichern - ich vermute ja: das ist die Rache von Google am kleinen Mann.

Interessant daran ist: nach einem knappen Jahr taucht der nächste Fall auf und es gibt eine Besonderheit: Mein Geburtstagskalender funktioniert ohne Zutun immer noch, aber die im Artikel gezeigten "verknüpften Dienste" sehen anders aus, bei mir fehlen die Kontakte und Wallet Dienste. Ich bin argwöhnisch und habe alle Haken entfernt, ohne einen Nachteil zu spüren!


Im Oktober 24 erschien ein Beitrag auf Caschys Blog, der bisher nachhaltig funktioniert. Allerdings ist die Anleitung dort etwas kurz geraten. Deswegen meine Ergänzung:

Donnerstag, 5. Januar 2017

Kalender auswerten

Am Abend vor einem Termin eine Ansage bekommen? Wie das mit FHEM geht will ich hier kurz zeigen.

Beispiel: Abholungen der Abfalltonnen

Ich habe den Abfallkalender einfach in einem neuen Googlekalender angelegt. Das ist schnell gemacht, man braucht nur drei Terminserien und muss ein paar Tage im Jahr modifizieren. Der von der Abfallwirtschaft angebotene ICAL zum download geht nur hart bis zum Jahresende, hat eine falsche Zeitzone und besteht nicht aus Serien- sondern Einzelterminen.

Anlegen eines Kalenders in FHEM

Für die weitere Arbeit brauchen wir die URL vom Kalender. Diese erhalten wir beim Googlekalender unter Einstellungen/Kalender/<Kalendername>/Privatadresse (der grüne Ical Button) oder Kalenderadresse wenn der Kalender öffentlich ist.

Ein define Befehl in FHEM reicht:
define AbfallKalender Calendar ical url <URL>

Diese Gerät liest jetzt erstmal mal nur den Kalender. Man "sieht" nicht viel, maximal das diese Modul irgendetwas tut. Mit get Befehlen können wir Termine aus dem Kalender abfragen.

Auswertung des Kalenders in FHEM

Für die Ermittlung der Termine für die Abfallentsorgung benutzen wir ein weiteres Modul -> Abfall. Da es sich um ein "Entwicklungsmodul" handelt müssen wir es zuerst in FHEM verfügbar machen. Man kann es gleich installieren, ohne komplettes Update:

update all https://raw.githubusercontent.com/uniqueck/fhem-abfall/master/controls_fhemabfall.txt
Damit es in Zukunft per Update kommt:
update add https://raw.githubusercontent.com/uniqueck/fhem-abfall/master/controls_fhemabfall.txt
Jetzt läuft das einzelne Update und wir müssen es abschließen:
save 
shutdown restart

Mit der folgenden Definiton in FHEM bekommen die heutigen, morgigen und nächsten Termine in entsprechenden Readings.
define Abfall ABFALL AbfallKalender

Hinweis Stand August 2017 
Sollte es mit der aktuelle Version des Moduls Probleme geben, diese hier verwenden.

Erinnerung per Ansage

Eine freundliche Ansage am Abend vor dem Termin und am Morgen des Termins weist uns auf den Abholtermin hin.
define di_AbholungAnsage1 DOIF ([?17:00 - 20:00] and [PIR1:"motion: on"] and [Abfall:next_tage] == 1) ( set MyTTS volume 30, set MyTTS tts Morgen wird [Abfall:next_text] abgeholt)
define di_AbholungAnsage2 DOIF ([?06:00 - 10:00] and [PIR1:"motion: on"] and [Abfall:now_text] ne "" and [Abfall:now_text] ne "0") ( set MyTTS volume 30, set MyTTS tts Heute wird [Abfall:now_text] abgeholt)
attr di_AbholungAnsage.* cmdpause 1800
Hinweis: Derzeit gibt es noch einen temporären Zustand wo nur now_text mit einer 0 gefüllt wird. Deswegen habe ich diesen Zustand extra abgefragt.

Feintuning

Das Standard Intervall zur Abfrage des Kalenders beträgt 1 h (3600 sec). Für diese Anwendung reicht eigentlich ein größeres Intervall (z.B. 4 h=14400). Mit einem zusätzlichen Parameter hinter der URL kann man dies verändern. Einfach die DEF editieren.
Die Ansage wird alle halbe Stunde in dem Zeitraum wiederholt. Das kann man beliebig anpassen.

Sonntag, 6. August 2023

nextcloud zu Hause - sicher mit nextcloudpi

Wie der Name sagt, wurde nextcloudpi ursprünglich für den Raspberry Pi entwickelt und ist eine Art Komplettlösung. Primär gibt es dafür ein Systemimage, ich habe das auf einem Pi3 ausprobiert und kann sagen: das wird schnell langsam. Vielleicht geht es auf einem Pi4, aber darunter (läuft ab Pi2) kann ich es nicht empfehlen.

Ich habe es auf einem Intel Celeron N5105 System mit 8 GB RAM installiert, da finde ich es ganz brauchbar. Man kann später sehr viel bei nextcloud dazu installieren - ich denke, da kann man jede beliebige Hardware ausreizen.

Mein Ziel ist eine eigene Cloud zu Hause, alle Bewohner können die Daten ihrer Smartphones, vorhandene Bildarchive usw. darauf speichern und von unterwegs will man natürlich mal ein paar Bilder zeigen oder auf Dokumente zugreifen.

Ich möchte die Setup Schritte hier notieren, da es viele Möglichkeiten zum "abbiegen" gibt.