Rule erstellen in Abhängigkeit

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

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

Re: Rule erstellen in Abhängigkeit

Beitrag von udo1toni »

Genau.

Beide von @peter-pan gezeigten Varianten sind sinnvoll. Im ersten Fall muss ich wissen, welches Wertesystem das Item liefert (gewöhnlich ist openHAB auf metrisch konfiguriert und entsprechend wird der Zahlenwert der Temperatur in °C entsprechen).
Im zweiten Fall kann ich explizit mit anderen Einheiten Rechenn, ich kann also z.B. so etwas schreiben:

Code: Alles auswählen

var nTemp1 = 7 | °C     // Temperatur in Grad Celsius angegeben
var nTemp2 = 40 | °F    // Temperatur in Grad Fahrenheit angegeben
var nTemp3 = 280 | K    // Temperatur in Kelvin angegeben

if(nTemp1 < nTemp2)
if(nTemp3 > nTemp1)
Ich kann also Messwerte miteinander vergleichen und muss mich nicht darum scheren, in welcher Einheit sie angeliefert werden. Natürlich müssen die Einheiten ineinander umgerechnet werden können, z.B. ein Vergleich von Geschwindigkeit und Druck geht natürlich schief.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Innocent
Beiträge: 238
Registriert: 29. Jul 2020 12:40
Answers: 0

Re: Rule erstellen in Abhängigkeit

Beitrag von Innocent »

Guten Morgen.

Hier das Item.

Code: Alles auswählen

Number:Temperature   localCurrentApparentTemperature        "aktuelle Temperatur [%.0f %unit%]"         <temperature>      (wetter)  { channel="openweathermap:weather-and-forecast:api:local:current#apparent-temperature" }
Habe mich wohl vertan und muß mir das nochmal anschauen :D

So sieht es aktuell Aus, funktioniert aber noch nicht...

Code: Alles auswählen

rule "Pool an wenn 25°C und mehr"
when
    Time cron"0 30 12 * * ? "

then
    if( (localCurrentApparentTemperature.state as Number).floatValue < 25 )  
        
        return;
       SpsDgk10RelayOutput.sendCommand(ON)

end
Openhab 2 auf RaspberryPi 4

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

Re: Rule erstellen in Abhängigkeit

Beitrag von udo1toni »

Also handelt es sich um ein UoM Number Item. UoM bedeutet Units of Measurement, die Einheit wird, wie oben beschrieben direkt im Messwert mitgeliefert.

Ein Test wäre sinnvoll :)

Code: Alles auswählen

rule "Pool an wenn 25°C und mehr"
when
    Time cron "0 30 12 * * ?"
then
    logInfo("pool", "Rule gestartet")
    if(!(localCurrentApparentTemperature.state instanceof Number)) {
        logWarn("pool", "Außentemperatur ungültig! ({})", localCurrentApparentTemperature.state)
        return;
    }
    val Number nTemp = (localCurrentApparentTemperature.state as Number).floatValue
    logInfo("pool", "Außentemperatur: {} °C", nTemp)
    if(nTemp < 25)
        return;

    SpsDgk10RelayOutput.sendCommand(ON)
end
Einen Fehler habe ich beim Ändern der Regel direkt gesehen, und zwar ein fehlendes Leerzeichen hinter "cron".
Ich bin mir nicht sicher, ob das Auswirkungen hat, das könntest Du aber zunächst testen.

Es wäre in dem Zusammenhang sinnvoll, 30 und 12 durch ein Sternchen zu ersetzen, so dass die Rule (zum Test) minütlich ausgelöst wird.
Damit Du sicher mitbekommst, dass die Rule auch tatsächlich läuft, ist es sinnvoll, zumindest die erste log Meldung direkt mit einzubauen, damit Du auch eine Rückmeldung für den Trigger siehst.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Innocent
Beiträge: 238
Registriert: 29. Jul 2020 12:40
Answers: 0

Re: Rule erstellen in Abhängigkeit

Beitrag von Innocent »

Rule funktioniert nun so, wie sie soll.

Vielene Dank !
Openhab 2 auf RaspberryPi 4

Innocent
Beiträge: 238
Registriert: 29. Jul 2020 12:40
Answers: 0

Re: Rule erstellen in Abhängigkeit

Beitrag von Innocent »

Guten Morgen.

Die Rule funktioniert leider noch nicht ganz.
Wenn ich beide if verwende wird trotzdem immer geschalten, wenn nur die erste Bedingung erfüllt ist.
Ich habe getestet, jede Bedingung einzeln zu verwenden, dann geht es.
Nur zusammen wie hier, geht es nicht.

Noch dazu würde ich die Rule gern per Switch an und ausschalten quasi...
Item dazu ist angelegt, als Switch.
Ich weiß nur nicht wo und wie diese Bedingung eingebracht werden muss.

Danke schonmal im Voraus ! :D

Code: Alles auswählen

rule "Pool an wenn 23°C und mehr"
when
    Time cron "0 30 12 * * ? "
    
then
    
   if( (localCurrentApparentTemperature.state as Number).floatValue < 23 )  
   if( (localCurrentCloudiness.state as Number).floatValue > 50 )    

        return;
    
       SpsDgk10RelayOutput.sendCommand(ON)

end

Openhab 2 auf RaspberryPi 4

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

Re: Rule erstellen in Abhängigkeit

Beitrag von udo1toni »

Warum schreibst Du eine vollkommen andere Regel und wunderst Dich dann, dass sie nicht wie vorgesehen funktioniert?

Du verwendest keine lokale Variable.
Das kann man machen, aber die oben vorgeschlagene Rule ist schon nicht ganz ohne Grund so definiert.

Jedes Item hat beim Systemstart den Wert NULL (ausnahmslos jedes Item). Jedes Item kann zu jedem Zeitpunkt den Zustand NULL annehmen, genauso wie den Zustand UNDEV (ausnahmslos).

Deshalb ist es best practice, sich davon zu überzeugen, dass ein Number Item auch einen gültigen Zahlenwert liefert, bevor man diesen Wert nach Number castet (... as Number).

Weiterhin schreibst Du eine Bedingung hin, ohne dazu zu schreiben, was denn passieren soll, wenn die Bedingung erfüllt ist (oder was passieren soll, wenn die Bedingung nicht erfüllt ist).
Möchtest Du, dass beide Bedingungen erfüllt sein müssen? Dann heißt das Zauberwort Bool'sche Algebra oder logische Verknüpfung.

Die DSL ist nicht Indentation aware, das heißt, Du kannst die Befehle auch in einer einzigen Zeile schreiben, das macht für den Interpreter keinen Unterschied. Der Code ist dadurch aber sehr schlecht lesbar. Die Umbrüche und Einrückungen sind also nur für das menschliche Auge gedacht.

Mit dem Design von oben, konsequent umgesetzt, wird die Rule deshalb wunderbar funktionieren.
Dein Code, anders formatiert:

Code: Alles auswählen

rule "Pool an wenn 23°C und mehr"
when
    Time cron "0 30 12 * * ?"
then
    if((localCurrentApparentTemperature.state as Number).floatValue < 23 )
        if((localCurrentCloudiness.state as Number).floatValue > 50 )    
            return;

   SpsDgk10RelayOutput.sendCommand(ON)
end
Die Rule wird genau das machen, was da steht: Starte täglich um 12:30:00 Uhr. Falls der als Zahl betrachtete Wert in localCurrentApparentTemperature unter 23 ist, prüfe ob der als Zahl betrachtete Wert in localCurrentCloudiness über 50 ist. Ist das der Fall, so beende die Rule.

Sende den Befehl ON an SpsDgk10RelayOutput.

Ich habe den letzten Befehl etwas abgerückt von den anderen Befehlen geschrieben, aber nur, um ihn optisch hervorzuheben. Dieser Befehl wird bei jedem vollständigen Ruledurchlauf ausgeführt.
Die Rule läuft vollständig durch, falls die Temperatur über 23 liegt.
Die Ruile läuft ebenfalls durch, falls die Temperatur unter 23 liegt, aber die Bewölkung unter 50 liegt.
Ich vermute, dass Du einen Abbruch sowohl bei zu niedriger Temperatur als auch bei Bewölkung haben möchtest. Dann musst Du lediglich ein return; einfügen.

Code: Alles auswählen

rule "Pool an wenn 23°C und mehr"
when
    Time cron "0 30 12 * * ?"
then
    if((localCurrentApparentTemperature.state as Number).floatValue < 23)
        return;

    if((localCurrentCloudiness.state as Number).floatValue > 50)
        return;

   SpsDgk10RelayOutput.sendCommand(ON)
end
Genauso kannst Du einen Schalter einbauen, der die Rule beendet, falls er nicht auf ON steht:

Code: Alles auswählen

rule "Pool an wenn 23°C und mehr"
when
    Time cron "0 30 12 * * ?"
then
    if(MeinSwitch.state != ON)
        return;

    if((localCurrentApparentTemperature.state as Number).floatValue < 23)
        return;

    if((localCurrentCloudiness.state as Number).floatValue > 50)
        return;

   SpsDgk10RelayOutput.sendCommand(ON)
end
Wieder sind die Leerzeilen nur zum besseren Verständnis des Codes gedacht. Man könnte das Ganze wie gesagt auch mit Bool'scher Algebra aufschreiben, aber die Zeile wird dann länglich, bzw. die Bedingung ist dann über mehrere Zeilen umgebrochen.

Code: Alles auswählen

rule "Pool an wenn 23°C und mehr"
when
    Time cron "0 30 12 * * ?"
then
    if(MeinSwitch.state != ON ||
       (localCurrentApparentTemperature.state as Number).floatValue < 23 ||
       (localCurrentCloudiness.state as Number).floatValue > 50
       )
        return;

   SpsDgk10RelayOutput.sendCommand(ON)
end
Und wieder stehen die Umbrüche und Leerzeichen (also mehr als eines hintereinander) nur aus optischen Gründen da, das hier funktioniert genauso:

Code: Alles auswählen

rule "Pool an wenn 23°C und mehr" when Time cron "0 30 12 * * ?" then if(MeinSwitch.state != ON || (localCurrentApparentTemperature.state as Number).floatValue < 23 || (localCurrentCloudiness.state as Number).floatValue > 50) return; SpsDgk10RelayOutput.sendCommand(ON) end
Es ist nur nicht mehr gut lesbar.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Innocent
Beiträge: 238
Registriert: 29. Jul 2020 12:40
Answers: 0

Re: Rule erstellen in Abhängigkeit

Beitrag von Innocent »

Vielen Dank für deine ausführliche Antwort.
Für mich ist es schwer zu verstehen, da ich es zu wenig betreibe.
Will es eben immer recht einfach gestalten.
Was macht die lokale Variable? 🤔

Sehe ich es richtig, daß deine drei letzten Codefenster alles das gleiche darstellen, nur anders aussehen?

Ja, du hast recht, es soll nur geschaltet werden wenn switch on, Temperatur über 23°C und Bewölkung unter 50%.

Wenn ich deinen ersten Post richtig gelesen, verstanden und umgesetzt hätte, wäre mir damals schon aufgefallen, daß mir in einer If Zeile das return fehlt...

Aber so ist es wenn man der Materie fremd ist.
Aber hier wird ja immer geholfen, sei es auch noch so banal.

Vielen lieben Dank dafür.

PS. : Wo, wie kann man das so lernen, wie du es drauf hast? 🤔

Grüße 😃
Openhab 2 auf RaspberryPi 4

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

Re: Rule erstellen in Abhängigkeit

Beitrag von udo1toni »

Immer gerne :)

Was die lokale Variable betrifft: Es geht nicht so sehr um die Variable, die hilft nur, den Code kompakt zu gestalten, wenn ein Wert mehrfach verwendet wird. Es sei denn, man muss mit Werten rechnen und die Variable ändert also im Laufe der Rule ihren Wert, dann ist eine Variable (fast) ohne Alternativen.
Der eigentliche Punkt ist die Überprüfung des Status auf einen gültigen Wert (instanceof Number), das sollte man eigentlich immer machen, wenn die Gefahr besteht, dass die Rule sonst Fehler produziert (NullPointer Exception)

Was die drei letzten Rules betrifft, so sollten sie tatsächlich funktionsidentisch sein. Aber es ist natürlich ein Unterschied, ob ich drei Mal eine einzelne Bedingung abfrage und bei Zutreffen der Bedingung die Rule abbreche, oder ob ich drei Bedingungen abfrage, diese mittels ODER verknüpfe und bei Zutreffen die Rule abbreche, auch wenn das Ergebnis das selbe ist.

Ansonsten hilft es sehr, viel zu üben :) ich bin zwar kein Informatiker, beschäftige mich aber seit etwa 1982 mit Computern (damals VC20, Ti94A, ZX81... später C64, Amiga (das war der erste eigene) und schließlich X86-PC (Ende der 90er, mit Win95B). Und ich habe mich halt immer mit Programmieren beschäftigt :)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten