Kleiner Fehler im holiday-Modul

Begonnen von chicco, 01 November 2024, 19:51:58

Vorheriges Thema - Nächstes Thema

chicco

Hallo zusammen,

ich denke ich habe einen kleinen Fehler im holiday-Modul entdeckt, dürfte mit der Zeitumstellung zu tun haben.

Ich habe mir das Modul eingerichtet um mir eine Feiertags-Warnung einzurichten (ich stand vor Jahren mal an einem Feiertag vor verschlossenem Supermarkt, grrr).
Ab 10 Tagen vor einem Feiertag zeige ich mir in fhemweb den Feiertag in einem dummy-device an und 5 Tage vor dem Feiertag gibts eine Nachricht per Signal aufs Handy.
Heute ist Allerheiligen und ich habe festgestellt, dass die Signal-Nachricht nicht kam.

Jeden Tag um 00:00 Uhr wird per DOIF die Funktion setFeiertage() aufgerufen:
sub setFeiertage(;$) {
my ($i) = @_;

use Switch;

Log 1,("setFeiertage()");

my $now = time();
my $cnt = 0;
my $name;
my $myDevStateIcon = "";
my $myStateFormat = "";
my $tag = "";
my $date_offset;
my $date_offset_num;

for ($i=0;$i<10;$i++)
{
$name = fhem("get bw days $i");

if ($name ne "none")
{
switch ($i)
{
case 0 { $tag = "Heute"; }
case 1 { $tag = "Morgen"; }
case 2 { $tag = "Übermorgen"; }
else { $tag = "In $i Tagen"; }
}

if ($i == 5) {
# 5-Tage-Warnung per Signal verschicken
my $subject = "Feiertag " . lcfirst($tag) . ":\n" . $name;
fhem("set Signal send \@chicco $subject");
}

$date_offset_num = $now + ($i * 86400);
$date_offset = strftime('%A, %d.%m.%Y', localtime($date_offset_num));

$myDevStateIcon .= ($cnt == 0 ? "" : "<br />") . '<div class="ft_col1">' . $name . '</div><div class="ft_col2">' . $tag . ', ' . $date_offset . '</div>';
$myStateFormat  .= ($cnt == 0 ? "" : "&#10;;") . $tag . ($i < 2 ? '&#9;;&#9;;' : '&#9;;') . $name . ', ' . $date_offset;

$cnt++;
}
}

if ($myDevStateIcon ne "")
{
$myDevStateIcon = "<div>" . $myDevStateIcon . "</div>";
}

Log 1,("myDevStateIcon: $myDevStateIcon");
Log 1,("myStateFormat: $myStateFormat");

if ($myDevStateIcon eq "")
{
CommandSetReading(undef,'d_feiertag myDevStateIcon ')
}
else
{
fhem("setreading d_feiertag myDevStateIcon $myDevStateIcon");
}

if ($myStateFormat eq "")
{
CommandSetReading(undef,'d_feiertag myStateFormat ')
}
else
{
fhem("setreading d_feiertag myStateFormat $myStateFormat");
}
}

Alles was da mit myDevStateIcon und myStateFormat gemacht wird ist irrelevant.

Es geht um den Aufruf (holiday-Modul heißt hier "bw")
$name = fhem("get bw days $i");

So sehen die Logfiles vom letzten WE aus:
26.10. Samstag vor der Zeitumstellung, es ist falsch wenn der Samstag 7 Tage vor dem Feiertag ist, denn der Feiertag ist heute und heute ist Freitag
2024.10.26 00:00:00 1: setFeiertage()
2024.10.26 00:00:00 3: get bw days 0 : none
2024.10.26 00:00:00 3: get bw days 1 : none
2024.10.26 00:00:00 3: get bw days 2 : none
2024.10.26 00:00:00 3: get bw days 3 : none
2024.10.26 00:00:00 3: get bw days 4 : none
2024.10.26 00:00:00 3: get bw days 5 : none
2024.10.26 00:00:00 3: get bw days 6 : none
2024.10.26 00:00:00 3: get bw days 7 : Allerheiligen
2024.10.26 00:00:00 3: get bw days 8 : none
2024.10.26 00:00:00 3: get bw days 9 : none

27.10. Sonntag, 3 Std. vor der Zeitumstellung, auch noch falsch
2024.10.27 00:00:00 1: setFeiertage()
2024.10.27 00:00:00 3: get bw days 0 : none
2024.10.27 00:00:00 3: get bw days 1 : none
2024.10.27 00:00:00 3: get bw days 2 : none
2024.10.27 00:00:00 3: get bw days 3 : none
2024.10.27 00:00:00 3: get bw days 4 : none
2024.10.27 00:00:00 3: get bw days 5 : none
2024.10.27 00:00:00 3: get bw days 6 : Allerheiligen
2024.10.27 00:00:00 3: get bw days 7 : none
2024.10.27 00:00:00 3: get bw days 8 : none
2024.10.27 00:00:00 3: get bw days 9 : none

28.10. Montag nach der Zeitumstellung, ab hier ist es richtig, auch die restlichen Tage in dieser Woche
2024.10.28 00:00:00 1: setFeiertage()
2024.10.28 00:00:00 3: get bw days 0 : none
2024.10.28 00:00:00 3: get bw days 1 : none
2024.10.28 00:00:00 3: get bw days 2 : none
2024.10.28 00:00:00 3: get bw days 3 : none
2024.10.28 00:00:00 3: get bw days 4 : Allerheiligen
2024.10.28 00:00:00 3: get bw days 5 : none
2024.10.28 00:00:00 3: get bw days 6 : none
2024.10.28 00:00:00 3: get bw days 7 : none
2024.10.28 00:00:00 3: get bw days 8 : none
2024.10.28 00:00:00 3: get bw days 9 : none

Wie man sehen kann gibt es keinen Tag der 5 Tage vor dem Feiertag ist, deshalb kam keine Warnung aufs Handy.
Der Sprung von 6 auf 4 Tage ist genau da wo zwischendrin die Zeitumstellung war.

Ist jetzt nicht dramatisch, aber ich dachte ich melde es mal...

Gruß
chicco

chicco

... ich vermute mal, dass das Modul am Samtag um 0 Uhr aufgrund der Sommerzeit dachte es ist noch Freitag 23 Uhr und mir deshalb 7 Tage als (scheinbar korrekte) Rückgabe geliefert hat.
Wenn ich die Abfrage um 1 Uhr nachts (= 0 Uhr Winterzeit) gemacht hätte, hätte wahrscheinlich alles gepasst.

Dann sieht die Lösung vermutlich so aus, dass man im Modul prüfen muss ob Sommerzeit ist und dann die eine Stunde offset berücksichtigen.

Beta-User

Genau um 0:00 Uhr ist afair auch die interne Aktualisierung des Moduls noch nicht gelaufen.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

chicco

Aber warum funzt es dann in der Winterzeit wenn ich um 0 Uhr die Abfrage mache?

Beta-User

Sorry, du hast recht. Da du mit "get" arbeitest, wird die Datei bei jeder Anfrage neu eingelesen (siehe commandref). Das mit der späteren Aktualisierung würde nur ins Gewicht fallen, wenn man die Readings (state und tomorrow) abfragen würde. Die "stimmen" erst 5 Sek. später oder so... (vermutlich aber auch da dann nicht, wenn eine Zeitumstellung in die falsche Richtung dazwischen ist).

*Grübel* WeekdayTimer müßte intern auch eine ähnliche Abfrage machen - da wäre dann auch die Anzeige falsch... Der fragt intern allerdings mit Datum ab, könnte einen Unterschied machen. Na ja...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

xenos1984

Im Zweifelsfall hilft es, den Code selbst zu fragen. Zeile 326 in 95_holiday.pm:

my $t = time() + ($a[2] ? int($a[2]) : 0)*86400;
Das Modul berechnet bei einer get-Anfrage, welcher Tag in N * 86400 Sekunden vom Zeitpunkt der Anfrage ist. Und wenn man um Mitternacht fragt und innerhalb des Zeitraums die Uhr eine Stunde zurückgestellt wird, ist es dann eben nicht Mitternacht in N Tagen, sondern 23 Uhr am Tag davor.

betateilchen

Und grundsätzlich wäre es durchaus sinnvoll, eine solche Diskussion im passenden Unterforum zu holiday zu führen anstatt in der Wunschliste, wo das meines Erachtens komplett falsch platziert ist.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

chicco

#7
@xenos:
Richtig, deshalb brauchen wir einen offset von 3600 wenn der Zeitpunkt der Abfrage Sommerzeit ist und der abgefragte Zeitpunkt (+N Tage) Winterzeit ist.
Analog dazu brauchen wir einen offset von -3600 wenn der Zeitpunkt der Abfrage Winterzeit ist und der abgefragte Zeitpunkt Sommerzeit ist.

Ich wage mich mal an einen Patch, hinter die von xenos zitierte Zeile wird eingefügt:
    my $isdst_now = (localtime())[8];
    my $isdst_then = (localtime($t))[8];
    if ($isdst_now != $isdst_then) {
         $t += 3600 * ($isdst_now == 1 ? 1 : -1);
    }
Heute (Samstag) in 180 Tagen ist der 1. Mai, Tag der Arbeit.
Mit der ungepatchten Version bekomme ich mit
{ fhem("get bw days 180") }
als Rückgabe "Tag der Arbeit" -> richtig
Ab 23 Uhr bekomme ich "none" -> falsch

Mit der gepatchten Version bekomme ich auch nach 23 Uhr "Tag der Arbeit" -> richtig
Ab 0 Uhr bekomme ich "none" -> richtig

Das war der Test Winterzeit -> Sommerzeit.
Den Rückweg Sommer -> Winter kann man erst in einem halben Jahr testen wenn wieder Zeitumstellung ist, bin ich dann auch gerne bereit für. Aber jetzt möchte ich nicht an meinem live-System an der Uhr drehen.

@betateilchen:
Das hast du nicht Unrecht, aber nur wenn man das entsprechende Unterforum kennt. An der Anzahl meiner Beiträge kannst du sehen, dass ich mich hier im Forum nicht so gut auskenne, ich kenne nicht jede Unterforum-Ecke hier.
Ich hatte im Wiki beim holiday-Eintrag geschaut ob dort ein Link zum entsprechenden Forum/Thread ist weil ich das bei anderen Modulen hier und da so gesehen habe, aber da ist nix.
Dann wollte ich es im developer-Bereich posten, aber ich habe keine Berechtigung dort einen Thread zu erstellen.
Letztlich bin ich hier gelandet weil ich quasi den Wunsch bzw. den Vorschlag habe den Fehler zu fixen.
Wo hätte ich es sonst posten sollen wenn ich das entsprechende Unterforum nicht kenne?

Vielleicht wäre es eine Idee ein Unterforum "Bugreport" o.Ä. einzurichten, das direkt auf der Forums-Startseite sichtbar ist, neben all den anderen Unterforen. Dann hätten Leute wie ich, die einen Fehler melden wollen und nicht all die Unterforen/Threads kennen, direkt eine Anlaufstelle. Nur ein Vorschlag.

Gruß
chicco

Wzut

Zitatwenn ich das entsprechende Unterforum nicht kenne?
Dann hift ein Blick in die MAINTAINER.txt Datei :
FHEM/95_holiday.pm           rudolfkoenig         Sonstiges
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

Otto123

#9
Zitat von: chicco am 03 November 2024, 00:25:35Vielleicht wäre es eine Idee ein Unterforum "Bugreport" o.Ä. einzurichten, das direkt auf der Forums-Startseite sichtbar ist, neben all den anderen Unterforen. Dann hätten Leute wie ich, die einen Fehler melden wollen und nicht all die Unterforen/Threads kennen, direkt eine Anlaufstelle. Nur ein Vorschlag.
Naja jeder hat da andere Vorstellungen, aber sowas gibt es schon, Anfängerfreundlich im Anfängerboard  ;) 

Leider scheint es so zu sein, dass angepinnte Beiträge weggescrollt werden  :(

Und verschieben kann der Threadersteller seinen Thread - ganz unten links: Thema verschieben.
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

chicco

Jep, wenn ich in das Anfängerboard mal reingeschaut hätte, hätte ich den angepinnten Beitrag gesehen, hätte die maintainer.txt entdeckt und hätte die Info gefunden wo mein Beitrag hingehört, sorry.
Vermutlich habe ich nicht reingeschaut weil ich seit ca. 8 Jahren fhem nutze und mich nicht als Anfänger fühle? Keine Ahnung, nur ein Erklärungsversuch.
Der Titel "Anfängerfragen" klingt für mich nach "ich habe fhem grade frisch installiert, was nun?" - das ist hier eben nicht der Fall.
Zugegeben, im Bereich Forumsnutzung bin ich Anfänger.

Wie auch immer, Thread ist verschoben.
Patch-Vorschlag steht oben, dann kann Rudi sich das anschauen.

Gruß
chicco

Beta-User

Hatte nicht gesehen, dass das im falschen Bereich war...

Das Sommer-/Winterzeitthema ist immer wieder für "lustige" Effekte gut. Lösungsansätze siehe https://forum.fhem.de/index.php?topic=123847.0 (und die Anlässe dazu.)

Lange irgendwelche Variablen anzulegen, braucht man nicht, einfach die Differenz der $dst-Werte mit HOURSECONDS multiplizieren und das Ergebnis addieren reicht auch.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

chicco

Stimmt, das geht eleganter:
    $t += 3600 * ((localtime())[8] - (localtime($t))[8]);
Ich teste später um 23 Uhr...

Otto123

Zitat von: chicco am 03 November 2024, 19:07:08Zugegeben, im Bereich Forumsnutzung bin ich Anfänger.
Ohne immer wieder nachlegen zu wollen, was aber auch selten genutzt wird
help holidayin der FHEM Kommandozeile. Ohne groß zu suchen  :D
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

chicco

jep, weiß ich... seit vorhin, als ich mir den angepinnten Thread angeschaut habe ;)