Seite 1 von 1

Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 2. Jan 2023 17:06
von Lux73
Moin,

ich habe hier eine Rule:

Code: Alles auswählen

rule "Switch Frost aussen"
when
  Item Sensor_Aussen_Temperatur changed
then
  if ((Sensor_Aussen_Temperatur.state as Number) < 0 && Switch_Frost.state == OFF) {
    logInfo("myLog", "Switch Frost ein! "+triggeringItemName.toString+ " ist unter 0°C gefallen!")
    if (Switch_Frost.state != ON) Switch_Frost.sendCommand(ON)
  } else {
    logInfo("myLog", "Switch Frost aus! "+triggeringItemName.toString+ " ist über 0°C gestiegen!")
    if (Switch_Frost.state != OFF) Switch_Frost.sendCommand(OFF)
  }
end
ich verstehe aktuell nicht warum diese jetzt IMMER triggert wenn die A-Temp sich ändert?!?

eigtl. war ich der Meinung das in der ersten if Schleife BEIDE aktionen in die else Schleife mit einfließen

aktuell funktioniert das ganze aber nur wenn ich in die else Schleife

Code: Alles auswählen

} else if (Switch_Frost.state == ON) {
mit einbaue?!?

M.e. nach müsste die erstgenannte Rule doch nur tiggern wenn

Code: Alles auswählen

A-Temp unter Null Grad UND Switch_Frost == OFF
ist oder halt

Code: Alles auswählen

A-Temp über Null Grad UND Switch_Frost == ON
vielleicht kann mich jemand aufklären ob das verhalten so normal ist oder wo (mein grundsätzlicher) Denkfehler liegt diesbzgl... :mrgreen:

hoffe ich hab mein "Problem" gut genug beschrieben ^^

Re: Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 2. Jan 2023 17:37
von udo1toni
Du bringst da etwas durcheinander.
Trigger sind die Elemente zwischen when und then.

Das heißt, die Rule triggert jedes Mal, wenn sich der Status des Items Sensor_Aussen_Temperatur geändert hat.

Die Bedingung lautet, dass der Status als Zahl kleiner 0 sein muss und gleichzeitig der Status des Switch ist. Das bedeutet im Umkehrschluss, dass es ausreicht, dass eine der beiden Bedingungen nicht erfüllt ist, um in den else-Zweig zu springen.

Du willst vermutlich eher sowas:

Code: Alles auswählen

rule "Switch Frost aussen"
when
    Item Sensor_Aussen_Temperatur changed
then
    if((Sensor_Aussen_Temperatur.state as Number) < 0)
        if(Switch_Frost.state != ON) {
            Switch_Frost.sendCommand(ON)
            logInfo("frost", "Switch Frost ein! {} ist unter 0°C gefallen!",triggeringItemName)
        }
    else 
        if(Switch_Frost.state != OFF) {
            Switch_Frost.sendCommand(OFF)
            logInfo("frost", "Switch Frost aus! {} ist über 0°C gestiegen!",triggeringItemName)
        }
end
triggeringItemName ist automatisch vom Typ String. Die Substitution (die n-ten geschweiften Klammern werden durch den n+2-ten Parameter ersetzt) ist besser lesbar als die Verkettung der einzelnen Strings.

Die Rule triggert dennoch bei jeder Änderung, nur die Meldung wird nur ausgegeben, wenn die Schaltstellung durch die Rule geändert wird.

Re: Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 2. Jan 2023 17:43
von KellerK1nd
Die erste Frage, wie ist dein Item genau definiert? Mit Einheit oder nur als Nummer?

Als zweites, liefert das Item immer einen Zahlenwert? Du schreibst was von Null und nicht 0, das verwirrt mich.

Prinzipiell sollte es so funktionieren:

Code: Alles auswählen

rule "Switch Frost aussen"
when
  Item Sensor_Aussen_Temperatur changed
then
  if(!(Sensor_Aussen_Temperatur.state instanceof Numbers){
  	logWarn("Temperatursensor.Aussen", "Item liefert keinen gültigen Zahlenwert (Rückgabewert: {}).", Sensor_Aussen_Temperatur.state)
        return;
        
  var Boolean nTemp = if((Sensor_Aussen_Temperatur.state as Number).floatValue < 0) true else false
        
  if (nTemp == true) {
    logInfo("myLog", "Switch Frost ein! "+triggeringItemName.toString+ " ist unter 0°C gefallen!")
    if (Switch_Frost.state == OFF) Switch_Frost.sendCommand(ON)
  } 
  else if(nTemp == false){
    logInfo("myLog", "Switch Frost aus! "+triggeringItemName.toString+ " ist über 0°C gestiegen!")
    if(Switch_Frost.state == ON) Switch_Frost.sendCommand(OFF)
  }
end

Re: Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 2. Jan 2023 18:06
von Lux73
udo1toni hat geschrieben: 2. Jan 2023 17:37 Das bedeutet im Umkehrschluss, dass es ausreicht, dass eine der beiden Bedingungen nicht erfüllt ist, um in den else-Zweig zu springen.
okay soweit verstanden - owohl ich da vorher Meinung war das dies ein
erfordert anstatt einem
dann habe ich das falsch interpretiert bzw. mir falsch eingeprägt

btw. Rule getriggert war nicht richtig ausgedrückt: sondern eher das die Rule so jedesmal ungewünscht in "else" Zweig springt ^^

ich versuche meine Rules so einfach wie möglich aufzubauen - Danke für eure Beispiele :D

dennoch denke ich kann ich dann auch so Verfahren:

Code: Alles auswählen

rule "Switch Frost aussen"
when
	Item Sensor_Aussen_Temperatur changed
then
	if (((Sensor_Aussen_Temperatur.state as Number) < 0) && (Switch_Frost.state == OFF)) {
		logInfo("myLog", "Switch Frost ein! "+triggeringItemName.toString+ " ist unter 0°C gefallen!")
		if (Switch_Frost.state != ON) Switch_Frost.sendCommand(ON)
	} else if (Switch_Frost.state == ON) {
		logInfo("myLog", "Switch Frost aus! "+triggeringItemName.toString+ " ist über 0°C gestiegen!")
		if (Switch_Frost.state != OFF) Switch_Frost.sendCommand(OFF)
	}
end
mit der weiteren If Abfrage im else Zweig wird die Rule nur "ausgeführt" (also auch der LogFile Eintrag geschrieben) wenn der Switch jeweils nicht passend war

@Kellerkind

Code: Alles auswählen

Sensor_Aussen_Temperatur
ist als

Code: Alles auswählen

Number:Temperature
definiert

daher meine Definition "as Number" um nicht noch

Code: Alles auswählen

|"°C"
anhängen zu müssen ;-)

btw. ich mache jetzt schon über 3 Jahre mit OpenHAB rum und war der Meinung das ich solche "Basics" eigtl. schon fett verstanden hatte :shock: :mrgreen:

nochmals Vielen Dank für die beiden Beispiele!! werde mir die später nochmals genau ansehen und schauen was ich davon adaptieren kann :idea:

Re: Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 2. Jan 2023 18:13
von Lux73
KellerK1nd hat geschrieben: 2. Jan 2023 17:43 Die erste Frage, wie ist dein Item genau definiert? Mit Einheit oder nur als Nummer?

Als zweites, liefert das Item immer einen Zahlenwert? Du schreibst was von Null und nicht 0, das verwirrt mich.
Frage eins: definiert als Number:Temerature - ist eine Temperatursensor welcher immer die Aussentemperatur erfasst xx.xx°C

Frage zwei: Null nicht 0 ? ich bin verwirrt :shock: - was meinst du genau?

ich habe die Rule mit einem cron laufen gehabt alle 5 Minuten - bin aber auf einen Post hier im Forum gestoßen welche meinte dies nicht zu machen und dabei auch @udo1toni erwähnte :lol:

deshalb hab ich die Rule jetzt entsprechend umgebaut und bin dann aber auf die im Eingangspost erwähnten Probleme gestoßen

Re: Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 2. Jan 2023 19:15
von udo1toni
Lux73 hat geschrieben: 2. Jan 2023 18:06 dennoch denke ich kann ich dann auch so Verfahren:
Nein? Deine Rule prüft, ob Temperatur < 0 UND Switch OFF (Fall 1)
ODER (das heißt, falls Fall 1 nicht zutrifft) ob Switch ON

Das bedeutet: Temperatur ist unter 0 und Schalter OFF -> Schalter wird auf ON gewechselt.
Nächste Messung: Temperatur immer noch unter 0, aber Schalter nicht OFF -> Fall 1 trifft nicht zu, also Prüfung, ob Schalter ON -> trifft zu, also Schalter OFF.

Das ist NICHT das, was Du erreichen willst.

Abgesehen davon ist Deine Rule nicht "möglichst einfach". Und die Rule ist nicht failsafe.

Mit Absicherung gegen Fehler sieht die Rule so aus:

Code: Alles auswählen

rule "Switch Frost aussen"
when
    Item Sensor_Aussen_Temperatur changed
then
    if(!(newState instanceof Number)) {
        logWarn("frost", "Außentemperatursensor liefert ungültigen Wert ({}), Abbruch!",newState)
        return;
    }
    var soll = ON
    if((newState as Number).floatVaue > 0)
        soll = OFF

    if(Switch_Frost.state != soll) {
        Switch_Frost.sendCommand(soll.toString)
        logInfo("frost","Frostwächter wurde {}geschaltet!", if(soll != ON) "aus" else "ein")
    }
end
Zunächst prüft die Rule (abweichend von Deiner Rule), ob der Sensor überhaupt einen gültigen Wert liefert (im Sinne von: da kommt eine Zahl). Im Fehlerfall wird die Rule abgebrochen, natürlich mit Meldung.

Danach wird zunächst die Sollstellung ermittelt (ergibt sich aus der Temperatur)
Anschließend wird ein Schaltbefehl ausgeführt, falls das Soll vom Ist abweicht.
Die Meldung beinhaltet keine Nennung der Temperatur, denn die Information ist irrelevant. Relevant ist lediglich, ob ein Schaltvorgang stattgefunden hat.

Durch die Verwendung der Variablen ist die Rule so simpel, wie sie eben sein kann.
Durch die Verwendung der Substitution ist die Meldung auch im Source Code gut verständlich. Als Meldungstext wird entweder
"Frostwächter wurde eingeschaltet!" oder "Frostwächter wurde ausgeschaltet!" ausgegeben. Das ist in meinen Augen hübscher als z.B.
"Frostwächter wurde auf ON geschaltet!" bzw. "Frostwächter wurde auf OFF geschaltet!", was natürlich genauso ginge und dann keinen ternären Operator bräuchte, aber ganz ehrlich: der Code ist simpel und übersichtlich.

Wenn die Temperatur unbedingt genannt werden soll, könnte man auch diese Logmeldung ausgeben:

Code: Alles auswählen

logInfo("frost","Temperatur {}°C, Frostwächter wurde {}geschaltet!",String.format("%.1f",(newState as Number).floatValue), if(soll != ON) "aus" else "ein")
womit dann die Meldung um die Temperatur mit einer Nachkommastelle ergänzt wird. Dafür ist die Zeile aber schon wieder etwas komplizierter ;)

Beachte bitte auch, dass der Name des Loggers hier frost lautet. Damit wird es nun möglich, in der Karaf Konsole einfach

Code: Alles auswählen

log:set WARN org.openhab.core.model.script.frost
zu tippen und die Meldungen auf die Warnmeldungen zu beschränken, und zwar nur für diese Rule, unabhängig von anderen Rules (solange sie nicht ebenfalls frost als Loggernamen verwenden).

Re: Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 3. Jan 2023 18:06
von Lux73
Hallo Udo,

oh weh... :shock:

ich sehe schon, möglichst einfach ist wohl nicht ^^ - zumindest nicht mit meiner bescheidenen Kenntnis

Werde deine Rule am WE mal genau durchforsten und versuchen zu verstehen was da genau passiert :mrgreen:

Vielen Dank dafür! Ich muss bestimmt nochmal "doof" nachfragen ;)

schönen Abend dir noch

Grüße
Michael

Re: Verständnisfrage if else bei zwei AND zusammengehörigen if Konditionen

Verfasst: 3. Jan 2023 19:27
von udo1toni
Lux73 hat geschrieben: 3. Jan 2023 18:06 ich sehe schon, möglichst einfach ist wohl nicht
Doch, sicher. Nur heißt "möglichst einfach" nicht "alles mögliche irgendwie zusammenknäulen und dann geht das schon", sondern, ganz genau zu prüfen, was in welcher Situation passiert, wie eine Aufgabe möglichst einfach erledigt werden kann, im Sinne von "zuverlässig", so, dass man es auch nachvollziehen kann.
In Deinem Fall hast Du zwei Bool'sche Elemente, die Du verknüpfst. Dabei ergeben sich halt vier Möglichkeiten. Zwei davon sollen keine Auswirkungen haben, zwei weitere sollen eine Aktion zur Folge haben, allerdings unterschiedlicher Art. Es gibt bei "entweder oder" nur zwei Möglichkeiten, Du bräuchtest aber drei. Dementsprechend ist der Ansatz schon von Beginn an nicht "einfach".

Aber wenn Du Dir mal den Part mit der Prüfung auf Gültigkeit des Messwerts weg denkst, wirst Du schnell erkennen, dass die Lösung mit einer Variablen wirklich einfach ist - selbst im Vergleich zum ursprünglichen Code.
Und der Code dürfte auch schneller ausgeführt werden, denn newState ist - im Gegensatz zu Sensor_Aussen_Temperatur - schon ins RAM geladen, mundgerecht für die DSL, weil implizite Variable. Die Lokale Variable soll ist ebenfalls super schnell und anschließend wird nur an einer Stelle überhaupt auf den Status von Switch_Frost zugegriffen, und das für einen einfachen Vergleich mit der lokalen Variablen.
Allerdings spielt das im täglichen Leben keine Rolle, ob wir nun von 1.3 ms oder 1.5 ms sprechen (nein, ich hab das nicht gemessen), das geht weit im Grundrauschen des Systems unter.