Seite 1 von 2

OH3 rule Differenz zwischen zwei Daten

Verfasst: 14. Mär 2022 17:50
von udi
Hallo zusammen,

ich möchte eine textbasierte rule anlegen. Für die Bedindung (when) brauche ich die Differenz zweier Daten. Wenn diese kleiner 2 ist, erfolgt die Aktion.
Leider komme ich mit Java und den Daten überhaupt nicht zurecht :roll:

Ein Datum soll heute sein und das zweite Datm habe ich als DateTime in einem Item.

Ich würde mich freuen, wenn ihr mir einen Ansatz zeigen könnten :mrgreen:

VG

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 14. Mär 2022 19:09
von udo1toni
So geht das nicht :)

Rules (egal, ob nun über UI oder Text definiert) sind grundsätzlich Event-gesteuert. Das heißt, es tritt ein Ereignis auf, woraufhin die Rule ausgeführt wird. Es gibt viele verschiedene Ereignisse, angefangen bei System Ereignissen (Start des Systems) über bestimmte Zeitpunkte (Mittag) oder auch Cron Definitionen bis hin zu itemspezifischen Ereignissen. Hier stehen drei verschiedene Trigger zur Verfügung, received command, received update und changed. Bei jedem dieser Ereignisse kann man weitere Einschränkungen angeben (welches Command, Welcher Wert wurde empfangen, Die Änderung fand von welchem und/oder zu welchem Wert statt). Nicht möglich sind hier aber Vergleiche oder Berechnungen, denn dies sind keine Ereignisse, sondern Zustände.

Es ist nun die Frage, welche Aktion Du ausführst. Nehmen wir an, Du schaltest ein Licht an. Dann sieht Deine Rule dafür so aus:

Code: Alles auswählen

rule "Licht bei Differenz unter 2"
when 
    Item MeinItem1 changed or
    Item MeinItem2 changed
then
    if(!(MeinItem1.state instanceof Number))
        return;
    if(!(MeinItem2.state instanceof Number))
        return;

    val Number nWert1 = (MeinItem1.state as Number).floatValue
    val Number nWert2 = (MeinItem2.state as Number).floatValue
    val nDiff = nWert1 - nWert2
    if(nDiff < 2 && Licht.state != ON)
        Licht.sendCommand(ON)
end
Die Rule löst aus, wenn sich einer von zwei Item Status ändert.
Die Rule prüft, ob in beiden Status ein gültiger Zahlenwert vorliegt. Ist das nicht der Fall, bricht die Rule ab.
Wurde die Rule nicht abgebrochen, werden die beiden Status aus den Items ausgelesen und zwei lokalen Konstanten zugewiesen.
Anschließend wird die Differenz der beiden Konstanten einer dritten lokalen Konstanten zugewiesen.
danach prüft die Rule, ob die Differenz unter 2 ist und das Licht nicht eingeschaltet ist. Trifft beides zu, so wird das Licht eingeschaltet.

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 12:16
von udi
Hallo Udo,

ich bin scheinbar komplett auf dem Holzweg :(

Ich mache es mal konkret. Ich denke das hilft ein ganzes Stück weiter. Ich habe einen Eventkalender für die Müllentsorgung. Um eine passende Bediengune für die rule zu haben, habe ich ein Item mit der aktellen Zeit angelegt und diese per StateDescription auf Tagesebene eingestellt (also Dienstag 15.03.2021 aktuell). Ich könnte diese Item als also Bedingung verwenden. Richtig?

Code: Alles auswählen

rule "Einnerung Mülltonne"
when 
        Item Heute changed
then
        val Differenz = Duration.between(itemRegistry.getItem('Heute').getState(),itemRegistry.getItem('event3_name').getState()).toDays()    
        if (Differenz < 2) scriptExecution.callScript('Script zum Versand einer Nachricht');
}

Die rule würde auslösen, sobald sich das Item ändert, sprich das Datum. Also jede Nacht um 0:00 Uhr. Dann wird die Differenz der beiden Daten errechnet als ganze Tage. Wenn diese kleiner 2 ist, also 1 Tag, wird der Script zum Versand einer Nachricht angestoßen.

Wäre das so erstmal von der logischen Abfolge her richtig? Ist es überhaupt möglich so eine Differenz zwischen 2 Tagen zu erreichnen oder müssen die Werte vorher in einen String konvertiert werden?

Vielen Dank Udo!

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 13:40
von int5749
udi hat geschrieben: 15. Mär 2022 12:16 Ich mache es mal konkret. Ich denke das hilft ein ganzes Stück weiter.
Dies ist immer gut ;-)


Evtl. ein anderer Ansatz: Ich habe dies über 4 Rules gelöst. Zum einen wird geprüft ob und welcher Müll heute oder morgen abgeholt wird und dann entsprechend informiert.

Code: Alles auswählen

/* Abfallkalender */
rule "Abfallkalender heute"
when
   Item ABFALL_ICAL_heute changed
then
   //Prüfen ob heute Abfall abgeholt wird
	if (ABFALL_ICAL_heute.state != "false" && ABFALL_ICAL_heute.state != "Uninitialized"){
      postUpdate(ABFALL_AKTIV_heute,ON)
      postUpdate(ABFALL_NAME_heute,ABFALL_ICAL_heute.state)
   } else {
      postUpdate(ABFALL_AKTIV_heute,OFF)
      postUpdate(ABFALL_NAME_heute,"false")
   }
end

rule "Abfallkalender morgen"
when
   Item ABFALL_ICAL_morgen changed
then
   //Prüfen ob morgen Abfall abgeholt wird
	if (ABFALL_ICAL_morgen.state != "false" && ABFALL_ICAL_morgen.state != "Uninitialized"){
      postUpdate(ABFALL_AKTIV_morgen,ON)
      postUpdate(ABFALL_NAME_morgen,ABFALL_ICAL_morgen.state)
   } else {
      postUpdate(ABFALL_AKTIV_morgen,OFF)
      postUpdate(ABFALL_NAME_morgen,"false")
   }
end

rule "Abfallerinnerung heute"
when
	Time cron "0 45 06 ? * * *" 
then
	val actions = getActions("pushover", "pushover:pushover-account:account")
	if (ABFALL_AKTIV_heute.state == ON){
		actions.sendMessageToDevice("ME", "An den " + ABFALL_NAME_heute.state + " denken.", "Notification")
	}
end

rule "Abfallerinnerung morgen"
when
	Time cron "0 30 18 ? * * *" 
then
	val actions = getActions("pushover", "pushover:pushover-account:account")
	if (ABFALL_AKTIV_morgen.state == ON){
		actions.sendMessageToDevice("ME", "Morgen den " + ABFALL_NAME_morgen.state + " rausstellen.", "Notification")
	}
end
Dies basiert auf anderen Items (stelle ich bei Bedarf zur Verfügung) aber evtl. kannst Du davon etwas für Dich anpassen?

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 15:23
von rfu
Die rule würde auslösen, sobald sich das Item ändert, sprich das Datum. Also jede Nacht um 0:00 Uhr. Dann wird die Differenz der beiden Daten errechnet als ganze Tage.
Also wenn Du die Prüfung einfach nur einmal am Tag machen möchtest, dann kannst Du die Bedingung auch per cron expression starten, d.h. ohne extra ein Item für "Heute" zu definieren: https://www.openhab.org/docs/configurat ... d-triggers...

rfu

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 15:50
von peter-pan
...hier noch ein Beispiel einer DSL-Rule, das den Unterschied, zwischen einem bestimmten Item-Datum und "Jetzt" berechnet.

Code: Alles auswählen

rule "Datumvergleich mit jetzt"
  when
   Item Dummy_4 changed to ON
  then
   logInfo("test","------------------------------------------------------")
   var vSpringStartMet = (Spring_Start_Met.state as DateTimeType).getZonedDateTime.getDayOfYear()
   logInfo("test","Met Frühling ist an Tag: {}", vSpringStartMet)
   var vDayOfYear = LocalDate.now.getDayOfYear()
   logInfo("test","Heute ist Tag: {}", vDayOfYear)
   var vDiff = vSpringStartMet - vDayOfYear
   logInfo("test","Differenz ist : {}", vDiff)
// oder kurz
   vDiff = (Spring_Start_Met.state as DateTimeType).getZonedDateTime.getDayOfYear() - LocalDate.now.getDayOfYear()
   logInfo("test","Differenz ist : {}", vDiff)
   logInfo("test","------------------------------------------------------")
end
Als Trigger habe ich einfach einen Dummy-Switch benutzt. Für die Berechnung brauchst du eigentlich nur die Zeile die nach dem // oder kurz steht.

Was davor kommt ist eigentlich nur die Auflösung zum besseren Verständnis.

Hast du deine Regel schon mal ausprobiert ? Irgendwie scheint das nicht DSL zu sein, oder das ist eine neuere Version, die ich nicht kenne. Man kann auch mit der Item-Registry arbeiten, aber die muss man dann vor der (den) Rule(s) definieren.

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 17:26
von udo1toni
Wie meine Vorredner das schon erläutert haben, wird man so etwas eher über eine Time cron Expression auslösen.
Wenn Datum und Uhrzeit (auch wenn die Zeit keine Rolle spielen soll, ist dieser Anteil immer vorhanden) aus einem DateTime Item kommen, musst Du dieses vor einem Vergleich nach JavaTime umrechnen lassen.
now() oder LocalDate.now() liefert das aktuelle Datum und die aktuelle Zeit (LocalDate mit Information über die Zeitzone). Solange es nur um den Tag geht, wäre .getDayOfYear() sicherlich sinnvoll (das müsste Integer oder Long sein, aber auf jeden Fall ohne Nachkommastellen)

Code: Alles auswählen

rule "Einnerung Mülltonne"
when 
    Time cron "15 15 7 ? * 1-6" // Montag bis Samstag um 07:15:15 Uhr
then
    if(!(event3_name.state instanceof DateTimeType)) {
        logInfo("muell","Kein gültiges Datum! ({})",event3_name.state)
        return;
    }
    val Integer iDiff = (event3_name.state as DateTimeType).getZonedDateTime.getDayOfYear() - LocalDate.now.getDayOfYear()

    if(iDiff == 1) {       // Ereignis morgen?
        // sende Nachricht
    }
end
Je nachdem, wie Du eine Nachricht versenden willst, sieht der Code da natürlich unterschiedlich aus.

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 17:57
von udi
int5749 hat geschrieben: 15. Mär 2022 13:40
udi hat geschrieben: 15. Mär 2022 12:16 Ich mache es mal konkret. Ich denke das hilft ein ganzes Stück weiter.
Dies ist immer gut ;-)


Evtl. ein anderer Ansatz: Ich habe dies über 4 Rules gelöst. Zum einen wird geprüft ob und welcher Müll heute oder morgen abgeholt wird und dann entsprechend informiert.

Code: Alles auswählen

/* Abfallkalender */
rule "Abfallkalender heute"
when
   Item ABFALL_ICAL_heute changed
then
   //Prüfen ob heute Abfall abgeholt wird
	if (ABFALL_ICAL_heute.state != "false" && ABFALL_ICAL_heute.state != "Uninitialized"){
      postUpdate(ABFALL_AKTIV_heute,ON)
      postUpdate(ABFALL_NAME_heute,ABFALL_ICAL_heute.state)
   } else {
      postUpdate(ABFALL_AKTIV_heute,OFF)
      postUpdate(ABFALL_NAME_heute,"false")
   }
end

rule "Abfallkalender morgen"
when
   Item ABFALL_ICAL_morgen changed
then
   //Prüfen ob morgen Abfall abgeholt wird
	if (ABFALL_ICAL_morgen.state != "false" && ABFALL_ICAL_morgen.state != "Uninitialized"){
      postUpdate(ABFALL_AKTIV_morgen,ON)
      postUpdate(ABFALL_NAME_morgen,ABFALL_ICAL_morgen.state)
   } else {
      postUpdate(ABFALL_AKTIV_morgen,OFF)
      postUpdate(ABFALL_NAME_morgen,"false")
   }
end

rule "Abfallerinnerung heute"
when
	Time cron "0 45 06 ? * * *" 
then
	val actions = getActions("pushover", "pushover:pushover-account:account")
	if (ABFALL_AKTIV_heute.state == ON){
		actions.sendMessageToDevice("ME", "An den " + ABFALL_NAME_heute.state + " denken.", "Notification")
	}
end

rule "Abfallerinnerung morgen"
when
	Time cron "0 30 18 ? * * *" 
then
	val actions = getActions("pushover", "pushover:pushover-account:account")
	if (ABFALL_AKTIV_morgen.state == ON){
		actions.sendMessageToDevice("ME", "Morgen den " + ABFALL_NAME_morgen.state + " rausstellen.", "Notification")
	}
end
Dies basiert auf anderen Items (stelle ich bei Bedarf zur Verfügung) aber evtl. kannst Du davon etwas für Dich anpassen?
Dankefür den Ansatz. Funktioniert bei mir leider nicht wirklich. Mein Müllkalender ist mit einem speziellen Widget verknüpft. Das benötigt die Ereignisse nicht nach Datum sondern hat je Ereignis einen eigene Filter. D.h. einen Filter für Restmüll, einen für Papier, einen für Bio,usw. Und in jedem Filter gibt es nur 1 Datum, also das direkt nächste.

Lassen sie deine Regeln dafür "verbiegen"?

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 17:59
von udi
rfu hat geschrieben: 15. Mär 2022 15:23
Die rule würde auslösen, sobald sich das Item ändert, sprich das Datum. Also jede Nacht um 0:00 Uhr. Dann wird die Differenz der beiden Daten errechnet als ganze Tage.
Also wenn Du die Prüfung einfach nur einmal am Tag machen möchtest, dann kannst Du die Bedingung auch per cron expression starten, d.h. ohne extra ein Item für "Heute" zu definieren: https://www.openhab.org/docs/configurat ... d-triggers...

rfu
Wenn ich Udo richtig verstanden habe, brauche ich doch aber einen "Auslöser", sprich ein Event. Ist dafür auch ein cron möglich? :shock:

Re: OH3 rule Differenz zwischen zwei Daten

Verfasst: 15. Mär 2022 20:51
von int5749
udi hat geschrieben: 15. Mär 2022 17:59 Wenn ich Udo richtig verstanden habe, brauche ich doch aber einen "Auslöser", sprich ein Event. Ist dafür auch ein cron möglich? :shock:
Ja, siehe meine Rules, 2 davon werden auch über Cron getriggert