diff --git a/fhem/CHANGED b/fhem/CHANGED index 8bf6b2392..4e27034a5 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - bugfix: 57_SSCal: fix problem recurring MONTHLY appointment by day - bugfix: 96_Snapcast: prevent crash in case of external group commands - feature: 70_ESCVP21net: added undocumented settings (IMGPROC, IRIS, LIRIS) - feature: 30_HUEBridge, 31_HUEDevice: support for Hue tap dial switch diff --git a/fhem/FHEM/57_SSCal.pm b/fhem/FHEM/57_SSCal.pm index d9994d1f2..f86c60356 100644 --- a/fhem/FHEM/57_SSCal.pm +++ b/fhem/FHEM/57_SSCal.pm @@ -3,7 +3,7 @@ ######################################################################################################################### # 57_SSCal.pm # -# (c) 2019 - 2021 by Heiko Maaz +# (c) 2019 - 2022 by Heiko Maaz # e-mail: Heiko dot Maaz at t-online dot de # # This Module integrate the Synology Calendar into FHEM @@ -140,6 +140,8 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "2.4.10" => "16.07.2022 fix problem recurring MONTHLY appointment by day, ". + "forum: https://forum.fhem.de/index.php/topic,106963.msg1228098.html#msg1228098 ", "2.4.9" => "11.07.2021 set adaption of AUTH for DSM7 compatibility ", "2.4.8" => "16.12.2020 accep umlauts in calendar name ", "2.4.7" => "08.12.2020 fix handle code recognition in createAtDevices as single line ", @@ -1561,30 +1563,31 @@ return; # Extrahiert empfangene Kalendertermine (Events) ############################################################################################# sub extractEventlist { ## no critic 'complexity' - my ($name) = @_; - my $hash = $defs{$name}; - my $data = delete $hash->{eventlist}; # zentrales Eventhash löschen ! - my $am = AttrVal($name, "asyncMode", 0); + my $name = shift; + + my $hash = $defs{$name}; + my $data = delete $hash->{eventlist}; # zentrales Eventhash löschen ! + my $am = AttrVal($name, "asyncMode", 0); my ($tz,$bdate,$btime,$bts,$edate,$etime,$ets,$ci,$bi,$ei,$startEndDiff,$excl,$es,$em,$eh); my ($nbdate,$nbtime,$nbts,$nedate,$netime,$nets); my @row_array; - my (undef,$tstart,$tend) = timeEdge($name); # Sollstart- und Sollendezeit der Kalenderereignisse ermitteln - my $datetimestart = FmtDateTime($tstart); - my $datetimeend = FmtDateTime($tend); - - my $n = 0; # Zusatz f. lfd. Nr. zur Unterscheidung exakt zeitgleicher Events + my (undef,$tstart,$tend) = timeEdge ($name); # Sollstart- und Sollendezeit der Kalenderereignisse ermitteln + my $datetimestart = FmtDateTime ($tstart); + my $datetimeend = FmtDateTime ($tend); + my $n = 0; # Zusatz f. lfd. Nr. zur Unterscheidung exakt zeitgleicher Events + for my $key (keys %{$data->{data}}) { my $i = 0; while ($data->{data}{$key}[$i]) { - my $ignore = 0; - my $done = 0; - my $next = 0; + my $ignore = 0; + my $done = 0; + my $next = 0; ($nbdate,$nedate) = ("",""); - - my $uid = $data->{data}{$key}[$i]{ical_uid}; # UID des Events + my $uid = $data->{data}{$key}[$i]{ical_uid}; # UID des Events + extractIcal ($name,$data->{data}{$key}[$i]); # VCALENDAR Extrakt in {HELPER}{VCALENDAR} importieren my $isallday = $data->{data}{$key}[$i]{is_all_day}; @@ -1597,9 +1600,9 @@ sub extractEventlist { ## no critic 'complexi my ($eyear, $emonth, $emday) = $edate =~ /(\d{4})-(\d{2})-(\d{2})/x; $netime = $etime; - # Bugfix API - wenn is_all_day und an erster Stelle im 'data' Ergebnis des API-Calls ist Endedate/time nicht korrekt ! - if($isallday && ($bdate ne $edate) && $netime =~ /^00:59:59$/x) { + if($isallday && ($bdate ne $edate) && $netime =~ /^00:59:59$/x) { # Bugfix API - wenn is_all_day und an erster Stelle im 'data' Ergebnis des API-Calls ist Endedate/time nicht korrekt ! ($es, $em, $eh, $emday, $emonth, $eyear, undef, undef, undef) = localtime($ets-=3600); + $eyear = sprintf("%02d", $eyear+=1900); $emonth = sprintf("%02d", $emonth+=1); $emday = sprintf("%02d", $emday); @@ -1610,18 +1613,20 @@ sub extractEventlist { ## no critic 'complexi ($ei,undef,$edate,$etime,$ets,undef) = explodeDateTime ($hash, $eyear.$emonth.$emday."T".$netime, 0, 0, 0); } - $startEndDiff = $ets - $bts; # Differenz Event Ende / Start in Sekunden + $startEndDiff = $ets - $bts; # Differenz Event Ende / Start in Sekunden - if(!$data->{data}{$key}[$i]{is_repeat_evt}) { # einmaliger Event + if(!$data->{data}{$key}[$i]{is_repeat_evt}) { # einmaliger Event Log3($name, 5, "$name - Single event Begin: $bdate, End: $edate"); if($ets < $tstart || $bts > $tend) { Log3($name, 4, "$name - Ignore single event -> $data->{data}{$key}[$i]{summary} start: $bdate $btime, end: $edate $etime"); + $ignore = 1; $done = 0; } elsif ($excl) { Log3($name, 4, "$name - Ignored by Ical compare -> $data->{data}{$key}[$i]{summary} start: $bdate $btime, end: $edate $etime"); + $ignore = 1; $done = 0; } @@ -1643,35 +1648,36 @@ sub extractEventlist { ## no critic 'complexi $done = 1; } } - elsif ($data->{data}{$key}[$i]{is_repeat_evt}) { # Event ist wiederholend + elsif ($data->{data}{$key}[$i]{is_repeat_evt}) { # Event ist wiederholend Log3($name, 5, "$name - Recurring event Begin: $bdate, End: $edate"); my ($freq,$count,$interval,$until,$uets,$bymonthday,$byday); my $rr = $data->{data}{$key}[$i]{evt_repeat_setting}{repeat_rule}; # Format: FREQ=YEARLY;COUNT=1;INTERVAL=2;BYMONTHDAY=15;BYMONTH=10;UNTIL=2020-12-31T00:00:00 - my @para = split(";", $rr); + my @para = split ";", $rr; for my $par (@para) { - my ($p1,$p2) = split("=", $par); + my ($p1,$p2) = split "=", $par; + if ($p1 eq "FREQ") { $freq = $p2; } - if ($p1 eq "COUNT") { # Event endet automatisch nach x Wiederholungen + if ($p1 eq "COUNT") { # Event endet automatisch nach x Wiederholungen $count = $p2; } - if ($p1 eq "INTERVAL") { # Wiederholungsintervall + if ($p1 eq "INTERVAL") { # Wiederholungsintervall $interval = $p2; } - if ($p1 eq "UNTIL") { # festes Intervallende angegeben + if ($p1 eq "UNTIL") { # festes Intervallende angegeben $until = $p2; $until =~ s/[-:]//gx; $uets = (explodeDateTime ($hash, $until, 0, 0, 0))[4]; } - if ($p1 eq "BYMONTHDAY") { # Wiederholungseigenschaft -> Tag des Monats z.B. 13 (Tag 13) + if ($p1 eq "BYMONTHDAY") { # Wiederholungseigenschaft -> Tag des Monats z.B. 13 (Tag 13) $bymonthday = $p2; } - if ($p1 eq "BYDAY") { # Wiederholungseigenschaft -> Wochentag z.B. 2WE,-1SU,4FR (kann auch Liste bei WEEKLY sein) + if ($p1 eq "BYDAY") { # Wiederholungseigenschaft -> Wochentag z.B. 2WE,-1SU,4FR (kann auch Liste bei WEEKLY sein) $byday = $p2; } } @@ -1699,7 +1705,7 @@ sub extractEventlist { ## no critic 'complexi $nbtime =~ s/://gx; $netime =~ s/://gx; - my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; + my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; ($bi,undef,$nbdate,$nbtime,$nbts,$excl) = explodeDateTime ($hash, $byear.$bmonth.$bmday."T".$nbtime, 0, $uid, $dtstart); # Beginn des Wiederholungsevents ($ei,undef,$nedate,$netime,$nets,undef) = explodeDateTime ($hash, $eyear.$emonth.$emday."T".$netime, 0, $uid, $dtstart); # Ende des Wiederholungsevents @@ -1742,12 +1748,12 @@ sub extractEventlist { ## no critic 'complexi $bmonth += $interval if($ci>=0); $byear += int( $bmonth/13); $bmonth %= 12 if($bmonth>12); - $bmonth = sprintf("%02d", $bmonth); + $bmonth = sprintf("%02d", $bmonth); $emonth += $interval if($ci>=0); $eyear += int( $emonth/13); $emonth %= 12 if($emonth>12); - $emonth = sprintf("%02d", $emonth); + $emonth = sprintf("%02d", $emonth); $nbtime =~ s/://gx; $netime =~ s/://gx; @@ -1791,12 +1797,13 @@ sub extractEventlist { ## no critic 'complexi if ($byday) { # Wiederholungseigenschaft -> Wochentag z.B. 2WE,-1SU,4FR (kann auch Liste bei WEEKLY sein) my ($nbhh,$nbmm,$nbss,$nehh,$nemm,$ness,$numOfRatedDay,$rDaysToAddOrSub,$rNewTime); - my @ByDays = split(",", $byday); # Array der Wiederholungstage + my @ByDays = split ",", $byday; # Array der Wiederholungstage for my $rByDay (@ByDays) { my $rByDayLength = length($rByDay); # die Länge des Strings my $rDayStr; # Tag auf den das Datum gesetzt werden soll my $rDayInterval; # z.B. 2 = 2nd Tag des Monats oder -1 = letzter Tag des Monats + if ($rByDayLength > 2) { $rDayStr = substr($rByDay, -2); $rDayInterval = int(substr($rByDay, 0, $rByDayLength - 2)); @@ -1806,7 +1813,7 @@ sub extractEventlist { ## no critic 'complexi $rDayInterval = 1; } - my $numOfAppointmentDay = _weekdayNumber ($rByDay); # liefert Nr des Wochentages: SU = 0 ... SA = 6 + my $numOfAppointmentDay = _weekdayNumber ($rDayStr); # liefert Nr des Wochentages: SU = 0 ... SA = 6 for ($ci=-1; $ci<($count); $ci++) { if ($rDayInterval > 0) { # Angabe "jeder x Wochentag" ist positiv (-2 wäre z.B. vom Ende des Monats zu zähelen) @@ -1815,8 +1822,9 @@ sub extractEventlist { ## no critic 'complexi $bmonth %= 12 if($bmonth>12); $bmonth = sprintf("%02d", $bmonth); - ($nbhh,$nbmm,$nbss) = split(":", $nbtime); + ($nbhh,$nbmm,$nbss) = split ":", $nbtime; my $firstOfNextMonth = fhemTimeLocal($nbss, $nbmm, $nbhh, 1, $bmonth-1, $byear-1900); + ($nbss, $nbmm, $nbhh, $bmday, $bmonth, $byear, $numOfRatedDay, undef, undef) = localtime($firstOfNextMonth); # den 1. des Monats sowie die dazu gehörige Nr. des Wochentages if ($numOfRatedDay <= $numOfAppointmentDay) { # Nr Wochentag des 1. des Monats <= als Wiederholungstag @@ -1825,7 +1833,8 @@ sub extractEventlist { ## no critic 'complexi else { $rDaysToAddOrSub = 7 - $numOfRatedDay + $numOfAppointmentDay; } - $rDaysToAddOrSub += (7 * ($rDayInterval - 1)); # addiere Tagesintervall, z.B. 4th Freitag ... + + $rDaysToAddOrSub += (7 * ($rDayInterval - 1)); # addiere Tagesintervall, z.B. 4th Freitag ... $rNewTime = plusNSeconds($firstOfNextMonth, 86400*$rDaysToAddOrSub, 1); ($nbss,$nbmm,$nbhh,$bmday,$bmonth,$byear,$ness,$nemm,$nehh,$emday,$emonth,$eyear) = DTfromStartandDiff ($rNewTime,$startEndDiff); @@ -1841,7 +1850,7 @@ sub extractEventlist { ## no critic 'complexi $nbtime = $nbhh.$nbmm.$nbss; $netime = $nehh.$nemm.$ness; - my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; + my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; ($bi,undef,$nbdate,$nbtime,$nbts,$excl) = explodeDateTime ($hash, $byear.$bmonth.$bmday."T".$nbtime, 0, $uid, $dtstart); # Beginn des Wiederholungsevents ($ei,undef,$nedate,$netime,$nets,undef) = explodeDateTime ($hash, $eyear.$emonth.$emday."T".$netime, 0, $uid, $dtstart); # Ende des Wiederholungsevents @@ -1884,10 +1893,10 @@ sub extractEventlist { ## no critic 'complexi if ($byday) { # Wiederholungseigenschaft -> Wochentag z.B. 2WE,-1SU,4FR (kann auch Liste bei WEEKLY sein) my ($nbhh,$nbmm,$nbss,$nehh,$nemm,$ness,$rNewTime); my ($numOfRatedDay,$rDaysToAddOrSub); - my @ByDays = split(",", $byday); # Array der Wiederholungstage + my @ByDays = split ",", $byday; # Array der Wiederholungstage my $btsstart = $bts; - $ci = -1; + $ci = -1; while ($ci<$count) { $rNewTime = $btsstart; @@ -1899,7 +1908,7 @@ sub extractEventlist { ## no critic 'complexi ($nbss, $nbmm, $nbhh, $bmday, $bmonth, $byear, $numOfRatedDay, undef, undef) = localtime($rNewTime); - ($nbhh,$nbmm,$nbss) = split(":", $nbtime); + ($nbhh,$nbmm,$nbss) = split ":", $nbtime; if ($numOfRatedDay <= $numOfAppointmentDay) { # Nr nächster Wochentag <= Planwochentag $rDaysToAddOrSub = $numOfAppointmentDay - $numOfRatedDay; @@ -1914,7 +1923,7 @@ sub extractEventlist { ## no critic 'complexi $nbtime = $nbhh.$nbmm.$nbss; $netime = $nehh.$nemm.$ness; - my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; + my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; ($bi,undef,$nbdate,$nbtime,$nbts,$excl) = explodeDateTime ($hash, $byear.$bmonth.$bmday."T".$nbtime, 0, $uid, $dtstart); # Beginn des Wiederholungsevents ($ei,undef,$nedate,$netime,$nets,undef) = explodeDateTime ($hash, $eyear.$emonth.$emday."T".$netime, 0, $uid, $dtstart); # Ende des Wiederholungsevents @@ -1964,7 +1973,7 @@ sub extractEventlist { ## no critic 'complexi $nbtime = $nbhh.$nbmm.$nbss; $netime = $nehh.$nemm.$ness; - my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; + my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; ($bi,undef,$nbdate,$nbtime,$nbts,$excl) = explodeDateTime ($hash, $byear.$bmonth.$bmday."T".$nbtime, 0, $uid, $dtstart); # Beginn des Wiederholungsevents ($ei,undef,$nedate,$netime,$nets,undef) = explodeDateTime ($hash, $eyear.$emonth.$emday."T".$netime, 0, $uid, $dtstart); # Ende des Wiederholungsevents @@ -2013,7 +2022,7 @@ sub extractEventlist { ## no critic 'complexi $nbtime = $nbhh.$nbmm.$nbss; $netime = $nehh.$nemm.$ness; - my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; + my $dtstart = $byear.$bmonth.$bmday."T".$nbtime; ($bi,undef,$nbdate,$nbtime,$nbts,$excl) = explodeDateTime ($hash, $byear.$bmonth.$bmday."T".$nbtime, 0, $uid, $dtstart); # Beginn des Wiederholungsevents ($ei,undef,$nedate,$netime,$nets,undef) = explodeDateTime ($hash, $eyear.$emonth.$emday."T".$netime, 0, $uid, $dtstart); # Ende des Wiederholungsevents