Seite 1 von 1

Rule when mit Cron und Item

Verfasst: 13. Feb 2022 19:02
von Joe
Hallo zusammen,
ich muss meine Rule von zwei Punkten abhängig machen und weiß nicht wie ich das hinbekomme.

Code: Alles auswählen

rule "Helligkeit_Beleuchtung"
  when
    Time cron "* * 17-23 ? * SUN,FRI,SAT *" or
    Item mcu2_L changed 
  then
    if(mcu2_B_Beleuchtung.state == OFF && (mcu2_L.state as Number) <= (mcu2_B_max.state as Number)) {
          mcu2_B_Beleuchtung.sendCommand(ON) 
   }
    
so funktioniert es leider nicht, da ich das "&&" nur beim if einsetzen kann.
Die Regel muss folgende Punkte prüfen bevor sie die Bedingung ausführt:
- Ist es aktuell Fr. bis So. und befinden wir uns in dem Zeitfenster zwischen 17 & 23 Uhr.
Wenn ja dann
- prüfe ob sich das Item mcu2_L geändert hat
Es gibt sicher eine ganz einfach Lösung die mir aber leider nicht bekannt ist.
Könnte mir bitte jemand den richtigen Code zeigen?

Danke
Joe

Re: Rule when mit Cron und Item

Verfasst: 13. Feb 2022 19:48
von udo1toni
Ja, das ist ganz einfach. Deine Rule muss das nur andersrum machen, als Du es beschreibst. :)

Ich möchte aber an dieser Stelle anhand des Beispiels nochmal darauf hinweisen, dass die Rule Engine Regeln immer eventbasiert ausführt. Ein Zeitfenster ist kein Event. Ein Zeitfenster hat einen Zustand (innerhalb des Zeitfensters oder außerhalb des Zeitfensters) und beim Wechsel des Zustands können wir von Events sprechen, das wären dann aber zwei Zeitpunkte und keine Zeiträume.
Es ist nicht zielführend, eine Rule zu schreiben, welche dann halt innerhalb des Zeitraums sekündlich ausgeführt wird (das ist mit Deinem Code so... * vorne).
Stattdessen lässt Du Deine Rule auf die Helligkeitsänderung und die beiden Grenzzeitpunkte triggern. Innerhalb des Codes prüfst Du dann, ob die Rahmenbedingungen stimmen und steuerst entsprechend. Das sieht so aus:

Code: Alles auswählen

rule "Helligkeit_Beleuchtung"
when
    Item mcu2_L changed or
    Time cron "0 0 17 * * 5-7" or
    Time cron "1 0 23 * * 5-7"
then
    var nGrenze  = 3                                                             // Default Wert, falls Item keine Zahl liefert
    if(mcu2_B_max.state instanceof Number)                                       // falls Item Zahl liefert
        nGrenze  = (mcu2_B_max.state as Number).floatValue                       // nimm diese

    var nAktuell = 2                                                             // Default Wert, falls Item keine Zahl liefert
    if(mcu2_L.state instanceof Number)                                           // falls Item Zahl liefert
        var nAktuell = (mcu2_L.state as Number).floatValue                       // nimm diese

    var swSoll = OFF                                                             // Default Sollzustand OFF
    if(nGrenze > nAktuell && now.getHour > 16 && now.getHour < 23 && now.getDayOfWeek.getValue > 4)  // Falls Bedingungen für ON erfüllt
        swLicht = ON                                                             // Setze Sollzustnad ON

    if(mcu2_B_Beleuchtung.state != swSoll)                                       // Falls Soll von Ist abweicht
        mcu2_B_Beleuchtung.sendCommand(swSoll.toString)                          // Sende Schaltbefehl
end
Die Bedingungen im Einzelnen:
  • gesetzter Grenzwert muss über aktueller Helligkeit liegen
  • Die aktuelle Stunde muss größer 16 sein (also ab 17:00:00 Uhr bis 23:59:59 Uhr der Fall)
  • Der aktuelle Wochentag als Zahl muss größer 4 sein (Montag = 1, Sonntag = 7)
Man sollte niemals davon ausgehen, dass ein Number Item immer eine Zahl als Status hält, es gibt mindestens noch die Status NULL und UNDEV, welche beide keine gültige Zahl darstellen und somit bei .state as Number eine null-Pointer Exception auslösen. Das .floatValue stellt sicher, dass keine der Variablen im Anschluss eventuell eine Einheit mitführt (Units of Measurement).

Im Allgemeinen wird es nicht auf das sekundengenaue Ein- und Ausschalten ankommen, sondern nur, dass dies bei Helligkeitsänderungen innerhalb des Zeitfensters automatisch geschieht. Es könnte aber sein, dass es im Zeitfenster gar keine Helligkeitsänderungen mehr gibt, weil es schon stockdunkel ist, deshalb die beiden zusätzlichen Trigger zu Beginn und zum Ende des Zeitfensters.

Die Rule schaltet das Licht nicht nur ein, sondern auch aus.

EDIT: Typo und Anpassungen an der Rule

Re: Rule when mit Cron und Item

Verfasst: 14. Feb 2022 07:00
von Joe
Hi Udo,
vielen Dank für Deine Erklärung und den Code.
So ganz habe ich das jedoch mit dem cron nicht verstanden. Ich glaube jedoch es liegt daran, dass man meine Frage an dieser Stelle falsch verstehen kann.
Es darf nur täglich zwischen 17-23 Uhr die Möglichkeit bestehen, dass die Bedingung wahr sein darf. Das jedoch noch an den Tagen Fr, Sa und So.
Der Wert aus mcu_L ist ein Wert, der von der Wetterstation kommt (Lux) auf der OH Oberfläche kann ich den Wert mcu2_B_max selber festlegen.
Das blöde aktuell ist eben, dass wenn der Wert "mcu_B_max" täglich erreicht wird (was passiert), geht die Beleuchtung "mcu_B_Beleuchtung" an.
Danke und sorry wenn ich es nicht richtig beschrieben hatte.
Joe

Re: Rule when mit Cron und Item

Verfasst: 14. Feb 2022 15:55
von udo1toni
zwischen 17 und 23 Uhr hieße, es muss eine Stunde früher nicht mehr geschaltet werden, das ist kein Thema. von Freitag bis Sonntag passt schon. Was meinst Du mit "das Blöde"? Die Idee ist doch gerade, dass das Licht von 17 Uhr bis 23 Uhr an ist, so es draußen dunkler als die eingestellte Helligkeit ist.

Oder fehlt da evtl. noch eine weitere Bedingung, wie z.B. ein Bewegungsmelder?

wegen der veränderten Zeit, ändere diese Zeile:

Code: Alles auswählen

    if(nGrenze > nAktuell && now.getHour > 16 && now.getDayOfWeek.getValue > 4)  // Falls Bedingungen für ON erfüllt
in diese:

Code: Alles auswählen

    if(nGrenze > nAktuell && now.getHour > 16 && now.getHour < 23 && now.getDayOfWeek.getValue > 4)  // Falls Bedingungen für ON erfüllt
.getHour liefert die Stunde auf einer Digitaluhr mit 24-Stunden-Anzeige, also 0 - 23 als Integer Wert. Die Bedingungen && now.getHour > 16 && now.getHour < 23 bedeuten also "Zwischen 17:00:00 Uhr und 22:59:59 Uhr"

Re: Rule when mit Cron und Item

Verfasst: 16. Feb 2022 07:13
von Joe
Udo ich komme mit dem "var nGrenze = 100" und dem "var nAktuell = 99" nicht ganz zurecht und bräuchte bitte nochmal Deine Hilfe.

Code: Alles auswählen

    if(mcu2_B_Beleuchtung.state == OFF && (mcu2_L.state as Number) <= (mcu2_B_max.state as Number)) {
          mcu2_B_Beleuchtung.sendCommand(ON) 
Da es sich hier um die Lux-Zahl geht die immer in größeren Schritte andere Werte liefert, hatte ich in meiner Formel einfach definiert, wenn die gelieferte Lux-Zahl den Wert aus meiner in der Oberfläche eingegeben Wert "mcu2_B_max" unterschreitet oder erreicht dann schalte das Licht "mcu2_B_Beleuchtung" ein.
Jetzt weiß ich allerdings nicht wie ich mit Deinen beiden oben angegebenen Variablen umgehen soll.
Aktuell geht das Licht im Garten an, wenn die gelieferte LUX-Zahl <= 2 ist, es gibt keinen Lux Wert wann das Licht wieder aus geht, dass sollte dann die Cron Geschichte liefern..bis eben 23 Uhr..naja so war mein Plan :-)

Re: Rule when mit Cron und Item

Verfasst: 16. Feb 2022 10:45
von udo1toni
Gar nicht. Nimm die Rule exakt so, wie sie da steht. da musst Du nichts dran ändern.

Der Punkt ist, wir benötigen den Status eines (zweier) Items. Diesen Status brauchen wir aber als Zahlenwert. Dazu verwenden wir ein Type Casting nach Number (as Number). Nun ist es aber so, dass ein Itemstatus auch NULL oder UNDEV sein kann, beide Werte sind reguläre Zustände eines Items, aber keine gültige Zahl. Wenn ich nun auf ein Item, welches einen dieser Zustände hat, einfach ein as Number los lasse, knallt es (null-Pointer Exception).
Um dies zu vermeiden, setze ich eine Variable auf einen Default Wert. Anschließend prüfe ich, ob der Inhalt des Status vom Typ Number ist (instanceof Number). Nur wenn das der Fall ist, übertrage ich den Wert in die Variable.
Wenn alles normal läuft, befinden sich also exakt die von Dir benötigten Zahlenwerte in den Variablen, nur im Fehlerfall (gewöhnlich nur beim Systemstart für kurze Zeit) werden die Default Werte genutzt. Du kannst ohne Probleme auch 3 als Default Grenzwert und 2 als Default Istwert annehmen.

Ähnlich funktioniert die Sache mit dem Schaltbefehl an das Item. Es wird zunächst ein Sollzustand OFF definiert. Anschließend wird überprüft, ob die Bedingungen zum Einschalten erfüllt sind: Grenzwert liegt über aktuellem Wert (könnte man auch andersrum hinschreiben... aktueller Wert liegt unter dem Grenzwert), Die Stunde (gemeint ist der Stundenanteil auf einer Digitaluhr! also eine Integerzahl 0 - 23) ist größer als 16, die Stunde ist kleiner als 23 (ab 23 Uhr soll nicht mehr eingeschaltet werden) und der Wochentag als Zahl ist größer 4 (1 = Montag, 7 = Sonntag). Sind alle Bedingungen erfüllt, wird der Sollzustand auf ON geändert.
Abschließend wird geprüft, ob der Ist-Zustand dem Sollzustand entspricht. Ist das nicht der Fall, so wird der Schaltbefehl gesendet.

Gerade der letzte Teil ist nicht ganz unwichtig. Du willst nicht alle paar Sekunden im log einen Schaltbefehl ON bzw. OFF sehen, nur weil die Helligkeit sich geändert (und damit die Rule getriggert) hat, aber das Licht ändert den Status gar nicht, weil es schon vorher passend geschaltet wurde.