Seite 1 von 1

Datum-Zeit-Vergleich klappt nicht mehr

Verfasst: 21. Jan 2025 10:18
von peter-pan
Ich habe einen Datumsvergleich in einer Regel und bekomme die Fehlermeldung:

Code: Alles auswählen

2025-01-21 09:47:00.395 [ERROR] [.handler.AbstractScriptModuleHandler] - Script execution of rule with UID 'homematic-13' failed: An error occurred during the script execution: Could not invoke method: java.time.chrono.ChronoZonedDateTime.isBefore(java.time.chrono.ChronoZonedDateTime) on instance: 2025-01-21T09:47:00.394674056+01:00[Europe/Berlin] in homematic
Der Grund ist dieser Codeschnipsel:

Code: Alles auswählen

      if(now.isAfter((Sunset_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()).toInstant.toEpochMilli)) { 
          logInfo("homematic-Haustür 4a", "now {} ist nach {} ", now, Sunset_Time.state as DateTimeType)
      }
Weiss jemand die Lösung :oops: :?: ?

Re: Datum-Zeit-Vergleich klappt nicht mehr

Verfasst: 21. Jan 2025 12:28
von udo1toni
Mein Vorschlag wäre, den Bandwurm erst mal in möglichst kleine Häppchen zu zerlegen.
Bist Du sicher, dass Du den Wert als EpochMilli benötigst? Bei mir funktioniert dieser Code tadellos:

Code: Alles auswählen

rule "Datumsvergleich"
when
    Time cron "0 * * * * ?"
then
    val dtt = Lokale_Sonnendaten_Startzeit.state as DateTimeType
    val zdt = dtt.getZonedDateTime(ZoneId.systemDefault())
    if(now.isAfter(zdt))
      logInfo("compdate","früher als jetzt")
    if(now.isBefore(zdt))
      logInfo("compdate","später als jetzt")
    logInfo("compdate","now {} LSD_Start {}",now,dtt)
end
Liefert als Ausgabe:

Code: Alles auswählen

12:26:00.575	INFO	org.openhab.core.model.script.compdate	später als jetzt
12:26:00.575	INFO	org.openhab.core.model.script.compdate	now 2025-01-21T12:26:00.575614353+01:00[Europe/Berlin] LSD_Start 2025-01-21T17:02:00.000+0100

Re: Datum-Zeit-Vergleich klappt nicht mehr

Verfasst: 21. Jan 2025 15:37
von peter-pan
Also erst mal vielen Dank, dass du dir den Bandwurm angeschaut hast.
Ich hatte mir mal eine Regel gebastelt, die ein bestimmtes Licht einschalten sollte, wenn wir abends nach hause kommen (so ungefähr :oops: ) und es bereits dunkel ist.

Die Regel:

Code: Alles auswählen

rule "Haustuer Status Wechsel"
    when
//      Item Dummy_4 changed to ON or
      Item HmIP_SWDO_I_E754_1STATE changed to "OPEN"  //String-Item
    then
       logInfo("homematic-Haustür 1"," Status Haustür - Triggering Item Name: {}", triggeringItemName)
       logInfo("homematic-Haustür Sonnenuntergang", "ist  {} ", (Sunset_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()))
       logInfo("homematic-Haustür Sonnenaufgang", "ist  {} ", (Sunrise_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()))

//-------------  Keine Aktion, wenn die Haustüre geschlossen wird (wird nur benötigt, wenn Trigger "changed" ohne "to OPEN" )-----------------------    
      if (HmIP_SWDO_I_E754_1STATE.state  == "CLOSED") {
        logInfo("homematic-Haustür 2"," CLOSED Status Haustür - Abbruch {}", HmIP_SWDO_I_E754_1STATE.state)
        return;
      }
      if (Pow_02.state == ON) {
        logInfo("homematic-Haustür 3", " Stehlampe bereits an {}",Pow_02.state.toString)
        return;
      }

//      if(now.isAfter((Sunset_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()).toInstant.toEpochMilli)) { // https://community.openhab.org/t/solved-datetimetype-is-deprecated/37296/31
//          logInfo("homematic-Haustür 4a", "now {} ist nach {} ", now, Sunset_Time.state as DateTimeType)
//      }
//      if(now.isAfter((Sunset_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()))) { // https://community.openhab.org/t/solved-datetimetype-is-deprecated/37296/31   --- Test zoned DateTime 30.4.21
//          logInfo("homematic-Haustür 4c", "now {} ist nach {} ", now, Sunset_Time.state as DateTimeType)
//      }
//       if(Instant.now().isAfter((Sunset_Time.state as DateTimeType).getInstant())) { // https://community.openhab.org/t/solved-datetimetype-is-deprecated/37296/31   --- Test zoned DateTime 30.4.21
//           logInfo("homematic-Haustür 4d", "now {} ist nach {} ", now, Sunset_Time.state as DateTimeType)
// // stopped for the moment(temporarely)          Pow_02.sendCommand(ON)
//           return;
//       }

//      if(now.isBefore((Sunrise_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()).toInstant.toEpochMilli)) { // https://community.openhab.org/t/solved-datetimetype-is-deprecated/37296/31
//          logInfo("homematic-Haustür 5", "now {} ist vor {} ", now, Sunrise_Time.state as DateTimeType)
//      }    
//      if(now.isBefore((Sunrise_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()))) { // https://community.openhab.org/t/solved-datetimetype-is-deprecated/37296/31   --- Test zoned DateTime 30.4.21
//          logInfo("homematic-Haustür 5", "now {} ist vor {} ", now, Sunrise_Time.state as DateTimeType)
//      }
      if(Instant.now().isBefore((Sunrise_Time.state as DateTimeType).getInstant())) { // https://community.openhab.org/t/solved-datetimetype-is-deprecated/37296/31   --- Test zoned DateTime 30.4.21

          logInfo("homematic-Haustür 5", "now {} ist vor {} ", now, Sunrise_Time.state as DateTimeType)
//          Pow_02.sendCommand(ON)   // Schaltung momentan deaktiviert
          return;
      }
//       soll nicht mehr ausgegeben werden 
       logInfo("homematic-Haustür 6", "nix passiert")
end
//===============================================================================
Wie du siehst, ist das meiste auskommentiert, weil das nicht (mehr) funktioniert hat. Ich hab dann mal versucht mit dem Schnipsel

Code: Alles auswählen

.getZonedDateTime(ZoneId.systemDefault())
, den ich von dir in einem anderen Post gefunden habe, das "zonedDateTime" zu ersetzen, aber das ist wohl doch nicht so einfach :oops: .
udo1toni hat geschrieben: 21. Jan 2025 12:28 Bist Du sicher, dass Du den Wert als EpochMilli benötigst? Bei mir funktioniert dieser Code tadellos:
Welchen Code meinst du ? Deinen oder meinen Schnipsel ?
Wie gesagt, ich bekomme bei allen "IF's" die gleiche Fehlermeldung. Ich weiss auch nicht mehr, ob ich das mit dem "EpochMilli" überhaupt brauche. Wie gesagt ich habe da nur ein paar Alternativen getestet.

Jetzt probier ich mal deine Version. Die ganze DateTime-Geschichte übersteigt irgendwie meinen Horizont bzw. ich baue auch manchmal irgend etwas in eine Rule zum Testen ein und vergesse dann die Ergebnisse auch wieder raus zu löschen (das Alter :roll: )

Danke erstmal

Re: Datum-Zeit-Vergleich klappt nicht mehr

Verfasst: 21. Jan 2025 21:43
von udo1toni
peter-pan hat geschrieben: 21. Jan 2025 15:37 Welchen Code meinst du ? Deinen oder meinen Schnipsel ?
Schon den meinigen :) deshalb habe ich ihn ja eingefügt.
Erfahrungsgemäß ist es oftmals nicht gut, zu viel Code stehen zu lassen, damit wird die Rule nur unübersichtlich und man übersieht vielleicht am Ende einen Fehler, der sich durch das Auskommentieren eingeschlichen hat.

So sollte die Rule sauber laufen:

Code: Alles auswählen

rule "Haustuer Status Wechsel"
 when
    Item Dummy_4 changed to ON or                                                                   // Für Tests
    Item HmIP_SWDO_I_E754_1STATE changed to "OPEN"                                                  // String-Item
 then
    val sunSet  = (Sunset_Time.state  as DateTimeType).getZonedDateTime(ZoneId.systemDefault())     // https://community.openhab.org/t/solved-datetimetype-is-deprecated/37296/31
    val sunRise = (Sunrise_Time.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault())

    logInfo("homematic.doorEntry","Rule durch {} ausgelöst", triggeringItemName)
    logInfo("homematic.doorEntry","Sonnenuntergang um {}", sunSet)
    logInfo("homematic.doorEntry","  Sonnenaufgang um {}", sunRise)
    logInfo("homematic.doorEntry","     aktuelle Zeit {}")

    if(HmIP_SWDO_I_E754_1STATE.state.toString != "OPEN") {                                          // Türkontakt meldet NICHT OPEN 
        logInfo("homematic.doorEntry","Status Haustür {} - Abbruch", HmIP_SWDO_I_E754_1STATE.state)
        return;
    }
    if(Pow_02.state == ON) {                                                                        // Stehleuchte bereits eingeschaltet 
        logInfo("homematic.doorEntry","Stehlampe ist an - Abbruch")
        return;
    }
    if(now.isAfter(sunSet)) { 
        logInfo("homematic.doorEntry","Es ist nach Sonnenuntergang")
       /* Schaltbefehl zu Testzwecken deakiviert
        Pow_02.sendCommand(ON)                                                                      // Licht einschalten
       */
        return;
    }
    if(now.isBefore(sunRise)) { 
        logInfo("homematic.doorEntry","Es ist vor Sonnenaufgang")
       /* Schaltbefehl zu Testzwecken deakiviert
        Pow_02.sendCommand(ON)                                                                      // Licht einschalten
       */
        return;
    }
     logInfo("homematic.doorEntry","Nix passiert")                                                  // wird tagsüber bei ausgeschalteter Leuchte ausgegeben
 end
Natürlich ist der Itemname HmIP_SWDO_I_E754_1STATE nicht so wirklich elegant ;) aber sei's drum.
Der Vergleich != "OPEN" ist nur drin, damit die Ausgabe des Status überhaupt eine Berechtigung hat ;) im Grunde könnte der Code auch entfallen, wie Dein Kommentar ja auch anmerkt.
Zu logInfo() und den anderen Log-Befehlen habe ich ja schon häufiger was geschrieben... der erste String ist der letzte Teil des Loggernamens. Von der Karaf Konsole aus reicht ein

Code: Alles auswählen

log:set WARN org.openhab.core.model.script.homematic.doorEntry
um alle logInfo-Befehle für diese Rule zu deaktivieren. Deshalb ist es wichtig, diesen ersten String innerhalb einer Rule identisch zu setzen. Leerzeichen und Sonderzeichen sollte man nicht verwenden, auch wenn der Logger das klaglos erträgt - ob dann der set-Befehl sauber funktioniert steht auf einem anderen Blatt. Die Namenskonventionen in openHAB fordern CamelCase mit kleingeschriebenem Wortanfang.
Der Punkt nach homematic hilft übrigens, wenn Du weitere Rules hast, in denen Du ebenfalls "homematic." als ersten Teilstring einsetzt. Dann kannst Du nämlich z.B. mittels

Code: Alles auswählen

log:set OFF org.openhab.core.model.script.homematic
jegliches Logging dieser Zeilen abschalten, jedoch mit dem Befehl von oben dennoch das Logging für doorEntry wieder einschalten - Die Einstellungen werden vererbt, solange kein eigener Eintrag existiert. Mittels

Code: Alles auswählen

log:set DEFAULT org.openhab.core.model.script.homematic.doorEntry
kann man die Einstellung auch gezielt erben lassen.
/* ... */ markiert alles zwischen den Sternchen als Kommentar. Vorteil: die Einrückungen des Codes bleiben so erhalten.
Zum grundsätzlichen Code: isAfter() und isBefore() sollten für now() zur Verfügung stehen - wie gesagt habe ich das heute Mittag bei mir erfolgreich ausprobiert (OH4.3.2 - ging aber auch schon mit früheren Versionen).
Der Vergleichswert muss vom Typ ZonedDateTime sein - die deprecated Meldung bezieht sich nur auf die Version ZonedDateTime() ohne Angabe der Zeitzone. Bisher hat openHAB dann ZoneId.systemDefault() automatisch gesetzt - das ist der Teil, der in der nächsten(?) Version nicht mehr funktionieren wird. Dabei geht es um Konsistenz über alle Module von openHAB - das Verhalten soll schlicht an jeder Stelle gleich sein.
Ansonsten wird die letzte Zeile natürlich sehr wohl ausgeführt, und zwar zwischen Sonnenauf- und -untergang, sofern die Rule getriggert wird und die Stehleuchte gerade aus ist (oder anders ausgedrückt: wenn alle vorgehenden Bedingungen nicht erfüllt sind). :D

Re: Datum-Zeit-Vergleich klappt nicht mehr

Verfasst: 22. Jan 2025 13:37
von peter-pan
Super, Danke nochmal. Ich werde den Code komplett übernehmen, so wie du ihn gepostet hast 👍 .
udo1toni hat geschrieben: 21. Jan 2025 21:43 Natürlich ist der Itemname HmIP_SWDO_I_E754_1STATE nicht so wirklich elegant ;) aber sei's drum.
Ja, mit den Homematic-Item-Namen ist das so eine Sache. Ich habe ungefähr 25 Tür-Fenstersensoren von HM und da ist mir damals einfach nichts besseres eingefallen und das habe ich dann einfach so fortgeführt. Es ist sozusagen ein Schlüssel:

Code: Alles auswählen

HmIP = Homematic IP (im Gegensatz zu Hm - ohne IP)
SWDO-I = Sensor-Typ
E754 = Ende der Serial-No
1STATE = Channel + Parameter Homematic -> Thing-Channel
udo1toni hat geschrieben: 21. Jan 2025 21:43 Der Vergleich != "OPEN" ist nur drin, damit die Ausgabe des Status überhaupt eine Berechtigung hat ;) im Grunde könnte der Code auch entfallen, wie Dein Kommentar ja auch anmerkt.
Den Vergleich habe ich eingebaut um die Regel unter anderem auch mit dem Dummy-Item testen zu können ("return;" auskommentiert) und nicht immer an die Haustür zu springen zu müssen um die Regel auszulösen (Pure Faulheit ;) )

Dein Vorschlag zum Log-Setting über die Karaf-Console schau ich mir noch mal genauer an.
Ich habe das "grundsätzliche" Logging in der Konsole "aktiviert", auch weil das die SG-Karte geschont hat (mir ist noch keine SD-Karte abgeschmiert) und weil ich die Status-Änderungen der Items im Normalbetrieb nicht brauche. Mit SSD ist das zwar kein Thema mehr aber die vielen Log-Statements sind m.E. im Normalbetrieb nicht unbedingt nötig. Deshalb habe ich auch kaum Logs im Logger, ausser die Rule-Logs.

Code: Alles auswählen

openhab.event                                      │ WARN
Die vielen Logs am Anfang der Regel waren übrigens nur zum Test um sunrise und sunset sichtbar zu machen.

udo1toni hat geschrieben: 21. Jan 2025 21:43 Ansonsten wird die letzte Zeile natürlich sehr wohl ausgeführt, und zwar zwischen Sonnenauf- und -untergang, sofern die Rule getriggert wird und die Stehleuchte gerade aus ist (oder anders ausgedrückt: wenn alle vorgehenden Bedingungen nicht erfüllt sind). :D
Das war die Absicht. Wenn die Tür aufgemacht wird und alles "normal" ist, ist nix passiert (mal abgesehen davon, dass die Tür aufgemacht wurde). Das ist sozusagen das Überlebenszeichen der Regel (meine etwas "verquere Denke" :D )

Danke auch nochmal für die Erklärungen zu ZonedDateTime. Ich hoffe ich hab's jetzt so einigermassen verinnerlicht (wenn nicht, musst du halt wieder helfen :oops: )