diff --git a/fhem/FHEM/57_Calendar.pm b/fhem/FHEM/57_Calendar.pm
index 9aa6f4640..c8ab767e9 100644
--- a/fhem/FHEM/57_Calendar.pm
+++ b/fhem/FHEM/57_Calendar.pm
@@ -1683,11 +1683,15 @@ sub Calendar_Initialize($) {
$hash->{SetFn} = "Calendar_Set";
$hash->{AttrFn} = "Calendar_Attr";
$hash->{NotifyFn}= "Calendar_Notify";
- $hash->{AttrList}= "update:sync,async,none removevcalendar:0,1 " .
- "cutoffOlderThan hideOlderThan hideLaterThan onCreateEvent " .
- "ignoreCancelled:0,1 quirks " .
- "SSLVerify:0,1 defaultFormat defaultTimeFormat " .
- $readingFnAttributes;
+ $hash->{AttrList}= "update:none,onUrlChanged ".
+ "synchronousUpdate:0,1 ".
+ "removevcalendar:0,1 " .
+ "ignoreCancelled:0,1 ".
+ "SSLVerify:0,1 ".
+ "cutoffOlderThan hideOlderThan hideLaterThan ".
+ "onCreateEvent quirks ".
+ "defaultFormat defaultTimeFormat ".
+ $readingFnAttributes;
}
@@ -1711,11 +1715,14 @@ sub Calendar_Define($$) {
my $type = $a[3];
my $url = $a[4];
my $interval = 3600;
-
- $interval= $a[5] if($#a==5);
+ if($#a==5) {
+ $interval= $a[5] if ($a[5] > 0);
+ Log3 $hash,2,"Calendar $name: interval $a[5] not allowed. Using 3600 as default." if ($a[5] <= 0);
+ }
$hash->{".fhem"}{type}= $type;
$hash->{".fhem"}{url}= $url;
+ $hash->{".fhem"}{lasturl}= $url;
$hash->{".fhem"}{interval}= $interval;
$hash->{".fhem"}{lastid}= 0;
$hash->{".fhem"}{vevents}= {};
@@ -1768,9 +1775,17 @@ sub Calendar_Attr(@) {
return "$arg must be a perl command in curly brackets but you supplied $arg.";
}
} elsif($a[0] eq "update") {
- my @args= qw/none sync async/;
- return "Argument for update must be one of " . join(" ", @args) .
- " instead of $arg." unless($arg ~~ @args);
+ my @args= qw/sync async/;
+ if ($arg ~~ @args) { # inform about new attribute synchronousUpdate
+ Log3 $hash,2,"Calendar $name: Value '$arg' for attribute 'update' is deprecated.";
+ Log3 $hash,2,"Calendar $name: Please use new attribute 'synchronousUpdate' if really needed.";
+ Log3 $hash,2,"Calendar $name: Attribute 'update' deleted. Please use 'save config' to update your configuration.";
+ CommandDefine(undef,"delattr_$name at +00:00:01 deleteattr $name update");
+ return undef;
+ }
+ @args= qw/none onUrlChanged/;
+ return "Calendar $name: Argument for update must be one of " . join(" ", @args) .
+ " instead of $arg." unless($arg ~~ @args);
}
return undef;
@@ -2469,9 +2484,20 @@ sub Calendar_GetUpdate($$$;$) {
return;
}
+ my @ti = localtime;
+ my $url= ResolveDateWildcards($hash->{".fhem"}{url}, @ti);
+
+ if($url ne $hash->{".fhem"}{lasturl}) {
+ $hash->{".fhem"}{lasturl} = $url;
+ } elsif (!$force && (AttrVal($hash->{NAME},"update","") eq "onUrlChanged")) {
+ Log3 $hash,4,"Calendar $name: unchanged url and update set to unUrlChanged = nothing to do.";
+ Calendar_CheckTimes($hash, $t);
+ Calendar_RearmTimer($hash, $t);
+ return;
+ }
+
Log3 $hash, 4, "Calendar $name: Updating...";
my $type = $hash->{".fhem"}{type};
- my $url= $hash->{".fhem"}{url};
my $errmsg= "";
my $ics;
@@ -2590,10 +2616,10 @@ sub Calendar_ProcessUpdate($$$) {
} else {
$hash->{".fhem"}{iCalendar}= $ics; # the plain text iCalendar
$hash->{".fhem"}{removeall}= $removeall;
- if(AttrVal($name, "update", "sync") eq "async") {
- Calendar_AsynchronousUpdateCalendar($hash);
- } else {
+ if(AttrVal($name, "synchronousUpdate", 0) == 1) {
Calendar_SynchronousUpdateCalendar($hash);
+ } else {
+ Calendar_AsynchronousUpdateCalendar($hash);
}
}
@@ -3202,8 +3228,23 @@ sub CalendarEventsAsHtml($;$) {
If the URL
starts with https://, the perl module IO::Socket::SSL must be installed
- (use cpan -i IO::Socket::SSL).
-
+ (use cpan -i IO::Socket::SSL).
+
+ <URL> may contain %-wildcards of the
+ POSIX strftime function of the underlying OS (see your strftime manual).
+ Common used wildcards are:
+
%d day of month (01..31)%m month (01..12)%Y year (1970...)%w day of week (0..6); 0 represents Sunday%j day of year (001..366)%U week number of year with Sunday as first day of week (00..53)%W week number of year with Monday as first day of week (00..53)https:// and the perl module IO::Socket::SSL is not installed on your system, you can
@@ -3494,12 +3535,17 @@ sub CalendarEventsAsHtml($;$) {
command. The specification is explained there. Do not enclose
the <timeFormatSpec> in quotes.
- update sync|async|nonesync, the processing of
- the calendar is done in the foreground. Large calendars will block FHEM on slow
- systems. If this attribute is set to async, the processing is done in the
- background and FHEM will not block during updates. If this attribute is set to
- none, the calendar will not be updated at all.
+ synchronousUpdate 0|1+ +
update onUrlChanged|noneonUrlChanged, the processing is done only
+ if url to calendar has changed since last calendar update.none, the calendar will not be updated at all.
removevcalendar 0|1define <name> Calendar ical url <URL> [<interval>]define <name> Calendar ical file <FILENAME> [<interval>]https://, muss das Perl-Modul IO::Socket::SSL installiert sein
- (use cpan -i IO::Socket::SSL).https:// beginnen und das Perl-Modul IO::Socket::SSL ist nicht auf Deinem Systeme installiert,
- kannst Du in der URL https:// durch http:// ersetzen, falls keine automatische Umleitung auf die https:// URL erfolgt.
- Solltest Du unsicher sein, ob dies der Fall ist, überprüfe es bitte zuerst mit Deinem Browser.https://admin:admin@demo.nextcloud.com/wid0ohgh/remote.php/dav/calendars/admin/personal/?export.
-
-
-
- Der optionale Parameter interval bestimmt die Zeit in Sekunden zwischen den Updates. Default-Wert ist 3600 (1 Stunde).
-
- Beispiele:
-
- define MeinKalender Calendar ical url https://www.google.com/calendar/ical/john.doe%40example.com/private-foo4711/basic.ics - define DeinKalender Calendar ical url http://www.google.com/calendar/ical/jane.doe%40example.com/private-bar0815/basic.ics 86400 - define IrgendeinKalender Calendar ical file /home/johndoe/calendar.ics -- -
set <name> updateinterval Sekunden später.set <name> reloadupdate, jedoch werden zuerst alle Termine entfernt.get <name> updateset <name> updateget <name> reloadset <name> reloadget <name> <format> <filter> [<max>]| <format> | Inhalt |
|---|---|
| uid | UID des Termins |
| text | Benutzer-/Monitorfreundliche Textausgabe. |
| summary | Übersicht (Betreff, Titel) |
| location | Ort |
| categories | Kategorien |
| alarm | Alarmzeit |
| start | Startzeit |
| end | Endezeit |
| full | Vollständiger Status |
| debug | wie <full> mit zusätzlichen Informationen zur Fehlersuche |
| <filter> | Inhalt |
|---|---|
| mode=<regex> | alle Termine, deren Modus durch den regulären Ausdruck <regex> beschrieben werden. |
| <mode> | alle Termine mit Modus <mode>. |
| uid=<regex> | Alle Termine, deren UIDs durch den regulären Ausdruck <regex> beschrieben werden. |
| <uid> | Alle Termine mit der UID <uid> |
| <reading> | Alle Termine die im Reading <reading> aufgelistet werden (modeAlarm, modeAlarmed, modeStart, etc.) - - dieser Filter ist abgekündigt und steht in einer zukünftigen Version nicht mehr zur Verfügung, bitte mode=<regex> benutzen. |
| all | Alle Termine (vergangene, aktuelle und zukünftige) |
| next | Alle Termine, die noch nicht beendet sind. Bei Serienterminen der erste Termin. Benutzer-/Monitorfreundliche Textausgabe |
mode=<regex> und uid=<regex> sollten den Filtern
- <mode> und <uid> vorgezogen werden.<max> schränkt die Anzahl der zurückgegebenen Zeilen ein.hideOlderThan und
- hideLaterThan für die Seletion von Terminen in einem bestimmten Zeitfenster.
- Bitte berücksichtige, dass das globale ±400 Tageslimit gilt .get MyCalendar text nextget MyCalendar summary uid:435kjhk435googlecom 1get MyCalendar summary 435kjhk435googlecom 1get MyCalendar full allget MyCalendar text mode=alarm|startget MyCalendar text uid=.*6286.*get <name> find <regexp>get <name> vcalendarget <name> veventsupdate sync|async|nonesync gesetzt ist,
- findet die Verarbeitung des Kalenders im Vordergrund statt. Große Kalender werden FHEM
- auf langsamen Systemen blockieren. Wenn das Attribut auf async gesetzt ist,
- findet die Verarbeitung im Hintergrund statt, und FHEM wird während der Verarbeitung
- nicht blockieren. Wenn dieses Attribut auf none gesetzt ist, wird der
- Kalender überhaupt nicht aktualisiert.
- - -
removevcalendar 0|1get <name> vcalendar ist dann nicht mehr möglich.
- - -
hideOlderThan <timespec>hideLaterThan <timespec>
-
- Dieses Attribut grenzt die Liste der durch get <name> full|debug|text|summary|location|alarm|start|end ... gezeigten Termine ein.
-
- Die Zeit wird relativ zur aktuellen Zeit t angegeben.
- Wenn <hideOlderThan> gesetzt ist, werden Termine, die vor <t-hideOlderThan> enden, ingnoriert.
- Wenn <hideLaterThan> gesetzt ist, werden Termine, die nach <t+hideLaterThan> anfangen, ignoriert.
- - Bitte beachten, dass eine Aktion, die durch einen Wechsel in den Modus "end" ausgelöst wird, nicht auf den Termin - zugreifen kann, wenn hideOlderThan 0 ist, weil der Termin dann schon versteckt ist. Besser hideOlderThan auf 10 setzen.
-
-
- <timespec> muss einem der folgenden Formate entsprechen:
-
| Format | Beschreibung | Beispiel |
|---|---|---|
| SSS | Sekunden | 3600 |
| SSSs | Sekunden | 3600s |
| HH:MM | Stunden:Minuten | 02:30 |
| HH:MM:SS | Stunden:Minuten:Sekunden | 00:01:30 |
| D:HH:MM:SS | Tage:Stunden:Minuten:Sekunden | 122:10:00:00 |
| DDDd | Tage | 100d |
- -
cutoffOlderThan <timespec>- -
onCreateEvent <perl-code>- -
SSLVerify- -
ignoreCancelled- -
quirks <values><values> ist
- eine mit Kommas getrennte Liste der folgenden Schlüsselwörter:
- ignoreDtStamp: wenn gesetzt, dann zeigt
- ein verändertes DTSTAMP Attribut eines Termins nicht an, dass
- der Termin verändert wurde.- - -
-
- Termine werden erzeugt, wenn FHEM gestartet wird oder der betreffende Eintrag im Quell-Kalender verändert
- wurde oder der Kalender mit get <name> reload neu geladen wird. Es werden nur Termine
- innerhalb ±400 Tage um die Erzeugungs des Termins herum erzeugt. Ziehe in Betracht, den Kalender von Zeit zu Zeit
- neu zu laden, um zu vermeiden, dass die künftigen Termine ausgehen. Du kann so etwas wie define reloadCalendar at +*240:00:00 set MyCalendar reload dafür verwenden.
- - Manche dummen Kalender benutzen LAST-MODIFIED nicht. Das kann dazu führen, dass Veränderungen im - Quell-Kalender unbemerkt bleiben. Lade den Kalender neu, wenn Du dieses Problem hast.
- - Ein Termin wird durch seine UID identifiziert. Die UID wird vom Quellkalender bezogen. Um das Leben leichter zu machen, werden alle nicht-alphanumerischen Zeichen automatisch aus der UID entfernt.
- - Ein Termin kann sich in einem der folgenden Modi befinden: -
| upcoming | Weder die Alarmzeit noch die Startzeit des Kalendereintrags ist erreicht. |
| alarm | Die Alarmzeit ist überschritten, aber die Startzeit des Kalender-Ereignisses ist noch nicht erreicht. |
| start | Die Startzeit ist überschritten, aber die Ende-Zeit des Kalender-Ereignisses ist noch nicht erreicht. |
| end | Die Ende-Zeit des Kalender-Ereignisses wurde überschritten. |
-
- Ein Kalender-Device hat verschiedene Readings. Mit Ausnahme von calname stellt jedes Reading eine Semikolon-getrennte Liste von UIDs von Kalender-Ereignisse dar, welche bestimmte Zustände haben:
-
| calname | Name des Kalenders |
| modeAlarm | Ereignisse im Alarm-Modus |
| modeAlarmOrStart | Ereignisse im Alarm- oder Startmodus |
| modeAlarmed | Ereignisse, welche gerade in den Alarmmodus gewechselt haben |
| modeChanged | Ereignisse, welche gerade in irgendeiner Form ihren Modus gewechselt haben |
| modeEnd | Ereignisse im Endemodus |
| modeEnded | Ereignisse, welche gerade vom Start- in den Endemodus gewechselt haben |
| modeStart | Ereignisse im Startmodus |
| modeStarted | Ereignisse, welche gerade in den Startmodus gewechselt haben |
| modeUpcoming | Ereignisse im zukünftigen Modus |
- - Für Serientermine werden mehrere Termine mit der selben UID erzeugt. In diesem Fall - wird die UID nur im interessantesten gelesenen Modus-Reading angezeigt. - Der interessanteste Modus ist der erste zutreffende Modus aus der Liste der Modi start, alarm, upcoming, end.
- - Die UID eines Serientermins wird nicht angezeigt, solange sich der Termin im Modus: modeEnd oder modeEnded befindet - und die Serie nicht beendet ist. Die UID befindet sich in einem der anderen mode... Readings. - Hieraus ergibts sich, das FHEM-Events nicht auf einem mode... Reading basieren sollten. - Weiter unten im Text gibt es hierzu eine Empfehlung.
-
-
- triggered
-
- Man kann sich darauf verlassen, dass alle Readings des Kalenders in einem konsistenten und aktuellen
- Zustand befinden, wenn dieses Event empfangen wird.
- - Wenn ein Termin geändert wurde, werden zwei FHEM-Events erzeugt:
-
- changed: UID <mode>
- <mode>: UID
-
- <mode> ist der aktuelle Modus des Termins nach der änderung. Bitte beachten: Im FHEM-Event befindet sich ein Doppelpunkt gefolgt von einem Leerzeichen.
- - FHEM-Events sollten nur auf den vorgenannten Events basieren und nicht auf FHEM-Events, die durch ändern eines mode... Readings ausgelöst werden. -
-
-
- Ein Plug-In ist ein kleines Perl-Programm, dass Termine nebenher verändern kann.
- Das Perl-Programm arbeitet mit der Hash-Referenz $e.
- Die wichtigsten Elemente sind:
-
-
| code | description |
|---|---|
| $e->{start} | Startzeit des Termins, in Sekunden seit 1.1.1970 |
| $e->{end} | Endezeit des Termins, in Sekunden seit 1.1.1970 |
| $e->{alarm} | Alarmzeit des Termins, in Sekunden seit 1.1.1970 |
| $e->{summary} | die Zusammenfassung (Betreff, Titel) des Termins |
| $e->{location} | Der Ort des Termins |
attr MyCalendar onCreateEvent { $e->{alarm}= $e->{start}-86400 if($e->{summary} =~ /Tonne/);; }
- get MyCalendar full all
- 2767324dsfretfvds7dsfn3e4dsa234r234sdfds6bh874googlecom known alarm 31.05.2012 17:00:00 07.06.2012 16:30:00-07.06.2012 18:00:00 Erna for coffee
- 992hydf4y44awer5466lhfdsrgl7tin6b6mckf8glmhui4googlecom known upcoming 08.06.2012 00:00:00-09.06.2012 00:00:00 Vacation
- text 20 60 { fhem("get MyCalendar text next 2") }
- 07.06.12 16:30 Erna zum Kaffee
- 08.06.12 00:00 Urlaub
-
- get MyCalendar find .*Erna.*
- 2767324dsfretfvds7dsfn3e4dsa234r234sdfds6bh874googlecom
-
- define ErnaComes notify MyCalendar:start:.2767324dsfretfvds7dsfn3e4dsa234r234sdfds6bh874googlecom.* set MyLight on
-
- define LogErna notify MyCalendar:alarm:.2767324dsfretfvds7dsfn3e4dsa234r234sdfds6bh874googlecom.* { Log3 $NAME, 1, "ALARM name=$NAME event=$EVENT part1=$EVTPART0 part2=$EVTPART1" }
-
- define SwitchActorOn notify MyCalendar:start:.* {}
-
- Dann auf DEF klicken und im DEF-Editor folgendes zwischen die beiden geschweiften Klammern {} eingeben:
-
- my $reading="$EVTPART0";
- my $uid= "$EVTPART1";
- my $actor= fhem("get MyCalendar summary $uid");
- if(defined $actor) {
- fhem("set $actor on")
- }
-
- define SwitchActorOff notify MyCalendar:end:.* {}
-
- Dann auf DEF klicken und im DEF-Editor folgendes zwischen die beiden geschweiften Klammern {} eingeben:
-
- my $reading="$EVTPART0";
- my $uid= "$EVTPART1";
- my $actor= fhem("get MyCalendar summary $uid");
- if(defined $actor) {
- fhem("set $actor off")
- }
-
- define LogActors notify MyCalendar:(start|end).* {}
-
- Dann auf DEF klicken und im DEF-Editor folgendes zwischen die beiden geschweiften Klammern {} eingeben:
-
- my $reading= "$EVTPART0";
- my $uid= "$EVTPART1";
- my $actor= fhem("get MyCalendar summary $uid");
- Log 3 $NAME, 1, "Actor: $actor, Reading $reading";
- CalendarAsHtml(<name>,<options>) bereit.
- Diese gibt den HTML-Kode für eine Liste von Terminen zurück. <name> ist der Name des
- Kalendar-Device und <options> ist das, was Du hinter get <name> text ...
- schreiben würdest.
- define MyCalendarWeblink weblink htmlCode { CalendarAsHtml("MyCalendar","next 3") }
- -