Vergleiche zwei Informationen in einer Rule

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Benutzeravatar
Joe
Beiträge: 200
Registriert: 10. Okt 2018 12:22
Wohnort: bei Mannheim

Vergleiche zwei Informationen in einer Rule

Beitrag von Joe »

Hi zusammen,
ich komme gerade mit einer Rule nicht weiter und benötig bitte Hilfe.

Die Rule sollte folgendes tun:
Wenn sicher der die Werte aus den ITEMS Azimuth und Bewoelkung ändern
der Wert aus dem ITEM "Cloud" großer als der Wert aus dem ITEM "Bewoelkung" ist UND Azimuth zwischen 271.8 und 287.6 ist DANN schalte das ITEM "Wolke" ein und Studio_1_Pro auf 100.
Wenn die Geschichte nach dem "IF" nicht stimmt dann ITEM "Wolke" auf OFF schalten.

Code: Alles auswählen

rule "Wolkenalarm Nacht"
  when
    Item Azimuth changed or
    Item Bewoelkung changed
  then
    if (((Clouds.state as Number) > (Bewoelkung.state as Number)) && ((Azimuth.state > 271.8) || (Azimuth.state < 287.6))){ 
      Wolke.sendCommand(ON) 
      Studio_1_Pro.sendCommand(100)
    } else {
      Wolke.sendCommand(OFF)
    } 
end
Ich möchte eigentlich nur das wenn sich der Azimuth Wert innerhalb eines Bereichs bewegt. Die "(Clouds.state as Number) > (Bewoelkung.state as Number)" nicht ausgeführt wird. Das ganze kann auch innerhalb eines Zeitfensters fixiert werden z.B. zwischen 22 und 6 Uhr.

03chris
Beiträge: 28
Registriert: 4. Feb 2018 17:10
Answers: 1

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von 03chris »

Hallo Joe,
bei ((Azimuth.state > 271.8) || (Azimuth.state < 287.6)) ist jeder beliebiger Wert "wahr". Ersetze || gegen && um innerhalb des Bereiches zu bleiben.

Benutzeravatar
udo1toni
Beiträge: 13858
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von udo1toni »

Bei Bool'scher Algebra muss man immer genau aufpassen:

Wert innerhalb der Grenzbereichs --->> Untergrenze < Wert UND Wert < Obergrenze
Wert außerhalb der Grenzbereichs --->> Wert < Untergrenze ODER Obergrenze < Wert

Manchmal ist es auch hilfreich, die einzelnen Bedingungen hierarchisch zu sortieren, also zuerst mal als verschachtelte if-Anweisungen aufzuschreiben.

Code: Alles auswählen

if((Clouds.state as Number) > (Bewoelkung.state as Number))
    if(Azimuth.state > 271.8)
      if(Azimuth.state < 287.6){ 
Alle drei Bedingungen müssen erfüllt sein, also kommt jeweils ein UND dazwischen.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Benutzeravatar
Joe
Beiträge: 200
Registriert: 10. Okt 2018 12:22
Wohnort: bei Mannheim

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von Joe »

Hi Udo,
das mit den beiden IF ist super aber es funktioniert nicht 100% richtig.
Habe gerade etwas mit den { } gespielt, leider funzt das auch nicht :-(

Code: Alles auswählen

        // Prüfung nach der Windstärke 
        if ((Clouds.state as Number) > (Bewoelkung.state as Number)) 
            if(Azimuth.state > 237.0) {
              if(Azimuth.state < 238.0) 
                Wolke.sendCommand(ON) //Wolkenalarm an
                Studio_1_Pro.sendCommand(100)
        } else {
          Wolke.sendCommand(OFF) //Wolkenalarm aus

wenn ich die Regel wieder in den vorherigen Zustand zurückstelle, macht sie das was sie soll nur eben ohne die Geschichte das die Regel nicht reagieren soll, wenn es eben Nacht ist und die Bewölkung ebne über z.B. 40 % liegen.
In dem Fall würden Nachts die Rollläden hochgefahren werden was dann upps nicht so gut wäre.

Code: Alles auswählen

        
        // Prüfung nach der Windstärke 
        if ((Clouds.state as Number) > (Bewoelkung.state as Number))  {
                Wolke.sendCommand(ON) //Wolkenalarm an
                Studio_1_Pro.sendCommand(100)
        } else {
          Wolke.sendCommand(OFF) //Wolkenalarm aus
Hast Du noch eine Idee wie ich das anpassen könnte? Gerne auch mit Cron?
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Benutzeravatar
udo1toni
Beiträge: 13858
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von udo1toni »

Es ging mir nicht darum, das Programm umzustellen :) sondern einen Weg zu zeigen, wie man die Bool'sche Logik aufbauen kann.

Die korrekte Zeile lautet natürlich

Code: Alles auswählen

if((Azimuth.state as Number) > 271.8 && (Azimuth.state as Number) < 287.6 && (Clouds.state as Number) > (Bewoelkung.state as Number)){ 
Wobei die Reihenfolge der einzelnen Bedingungen irrelevant ist.
Logisch betrachtet gibt es eine Voraussetzung, die "linear" verläuft (Sonnenstand zwischen Grenzwerten) und eine andere Voraussetzung, die variabel ist (Bewölkungsgrenzwert überschritten).
Deshalb habe ich die Reihenfolge der Vergleiche verdreht, aber das ist echt nur Geschmacksache.
Wenn man ganz sauber arbeiten will, muss man vor der Verwendung des Castings auf Gültigkeit prüfen:

Code: Alles auswählen

if(!(Azimuth.state instanceof Number)) return;
if(!(Clouds.state instanceof Number)) return;
if(!(Bewoelkung.state instanceof Number)) return;
var boolean bInBorders = false
if((Azimuth.state as Number) > 271.8 && (Azimuth.state as Number) < 287.6) bInBorders = true
if(bInBorders && (Clouds.state as Number) > (Bewoelkung.state as Number)){ 
    // bla
} else {
    // blie
}
Die Logikfunktionen aufzuteilen, lohnt sich eigentlich nur, wenn man die Werte mehrfach in unterschiedlicher Konstellation benötigt.
Das Abfangen ungültiger Werte (... instanceof ...) ist immer dann sinnvoll, wenn man nicht sicher weiß, ob die Werte gültig sind, das ist vor allem bei Regeln wichtig, die mit System started triggern (eventuell wurde der letzte Wert noch nicht durch die Persistence wiederhergestellt), oder auch in Fällen, wo Sensoren evtl. unzuverlässig arbeiten.
Manchmal möchte man vielleicht einen Default Wert setzen, falls kein gültiger Wert vorliegt. Dann sollte man immer im Hinterkopf haben, dass openHAB multithreaded und asynchron arbeitet. sendCommand() und postUpdate() starten jeweils ein Unterprogramm, welches sich um den Job kümmert, die Rule wartet aber nicht auf die Ausführung sondern macht einfach weiter. Beispiel:

Code: Alles auswählen

if(!(Azimuth.state instanceof Number)) Azimuth.postUpdate(15)
if((Azimuth.state as Number) > 14) logInfo("test","Azimuth größer 14")
Wenn Azimuth keinen gültigen Wert hat, wird die Rule vermutlich mit einer Nullpointer Exception abbrechen. Zwar wird umgehend ein gültiger Zahlenwert nach Azimuth geschrieben, jedoch wird auch unmittelbar im Anschluss eben jener Wert gelesen. Durch das asynchrone Modell weiß man aber nicht, ob der Schreibvorgang bereits beendet wurde. Sicher funktioniert das nur, wenn man stattdessen Variablen verwendet:

Code: Alles auswählen

var Number nAzimuth = 15
if(Azimuth.state instanceof Number) nAzimuth = Azimuth.state as Number
if(nAzimuth > 14) logInfo("test","Azimuth größer 14")
Da wir hier mit einer Variablen arbeiten, können wir sicher sein, dass diese zum Zeitpunkt des Vergleichs auch mit einem gültigen Wert gefüllt ist.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Benutzeravatar
Joe
Beiträge: 200
Registriert: 10. Okt 2018 12:22
Wohnort: bei Mannheim

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von Joe »

Hi Udo,
danke Du hast es super erklärt.
Ich muss allerdings gestehen, dass ich nicht alles zu 100% verstanden habe :?

Code: Alles auswählen

if((Azimuth.state as Number) > 258.0 && (Azimuth.state as Number) < 264.0 && (Clouds.state as Number) > (Bewoelkung.state as Number)){ 
Was mir jedoch schon etwas geholfen hat, ist die Formel von Dir.
Die Reaktion war wie folgt:
Azimuth steht aktuel bei 263.7 ° Wolkenalarm ist an, weil der Wert aus dem Item Bewoelkung kleiner als der Wert aus dem Item Clouds ist. --> soweit ok
Azimuth steht aktuel bei 264,1 ° Wolkenalarm ist aus, obwohl der Wert aus dem Item Bewoelkung kleiner als der Wert aus dem Item Clouds ist. Aber der Azimuth < als 264.0 ist --> soweit ok
Was aber nicht funktioniert ist die Angabe eines Bereichs vom Azimuth "Azimuth.state as Number) > 258.0" diese Angabe wird überhaupt nicht berücksichtigt. Dachte dann ich hätte im Kopf einen Zahlendreher und habe die ersten Wert auf "Azimuth.state as Number) > 265.0" gestellt und gewartet ob der Wolkenalarm wieder angeht. Er geht nicht mehr an. Was habe verstehe ich jetzt nicht oder was habe ich in der Formel falsch gemacht?

Benutzeravatar
Joe
Beiträge: 200
Registriert: 10. Okt 2018 12:22
Wohnort: bei Mannheim

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von Joe »

Hi Udo,
habe das ganze jetzt doch über die Zeit gesteuert, dass mit dem Azimuth war mir zuviel hin und her.
shit habe allerdings gerade festgestellt, dass es ein kleines Problem gibt wenn die Zeit über 0:00 Uhr geht sprich auf den zweiten Tag.
Kannst Du mir bitte sagen, wie ich meine Formal anpassen muss, dass es von Tag 0 (22:59 Uhr) bis Tag 1 (7:01 Uhr) geht.

Code: Alles auswählen

    var Number zeitraum = now.getMinuteOfDay
    if(zeitraum > 22*60+59 && zeitraum < 07*60+01)
Muss ich hier "now.getMinuteOfMonth" oder noch größer "now.getMinuteOfYear" eingeben?

Danke
Joe

Benutzeravatar
udo1toni
Beiträge: 13858
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von udo1toni »

Bool'sche Algebra...

Code: Alles auswählen

if(now.getMinuteOfDay < 7*60 + 1 || now.getMinuteOfDay > 22*60 + 58 )
:)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Benutzeravatar
Joe
Beiträge: 200
Registriert: 10. Okt 2018 12:22
Wohnort: bei Mannheim

Re: Vergleiche zwei Informationen in einer Rule

Beitrag von Joe »

Ich falle immer wieder darauf rein... :? Shit Danke jetzt funzt die Kiste :D

Antworten