Seite 1 von 3

Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 00:17
von PeterA
Hallo,
wer könnte mir bei der Erstellung folgender Rule behilflich sein.
Es soll folgendes passieren:
Wenn die Aussentemperatur größer/gleich 22° ist, soll der Befehl
LuefterStufe 0 an das Item gesendet werden.
Und wenn die Außentemperatur wieder auf 18° gefallen ist, soll die Anlage wieder auf Stufe 2 Anlaufen.
Diese rule möchte aber per "Schalter" aktivieren/deaktivieren können
Vielen Dank

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 02:39
von peter-pan
Hallo Peter,

du brauchst als erstes ein "virtuelles" Switch Item, das so aussieht:

Code: Alles auswählen

Switch      Dummy                                "Testschalter Dummy1 [%s]" 
Und die Regel könnte so aussehen:

Code: Alles auswählen

rule "Aussenluft manuell"
when
    Item Aussenluft changed
then
   if(Dummy.state != ON) return;  // wenn Schalter aus(nicht an) , keine Aktionen
    
   if(!(Aussenluft.state instanceof Number)) {
        logWarn("Aussenluft manuell","Aussenluft.state not a Number: {}",Aussenluft.state)  // numerisch ?
        return;
   }
   if ((Aussenluft.state >= 22) && (Luefterstufe != 0)) {
       LuefterStufe.sendCommand(0)
       logInfo("Aussenluft manuell","Luefterstufe ist jetzt: {} Aussenluft beträgt {}",Luefterstufe.state,Aussenluft.state )
       
   }
   else if ((Aussenluft.state <= 18) &&(Luefterstufe.state != 2)) {  
       LuefterStufe.sendCommand(2)
       logInfo("Aussenluft manuell","Luefterstufe ist jetzt: {} Aussenluft beträgt {}",Luefterstufe.state,Aussenluft.state)
       
   }
end
Eventuell solltest du noch den Schalter persisten, damit bei einem Neustart, der letzte Wert wieder gesetzt wird.


Gruss - Peter

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 10:35
von PeterA
Hi Peter,

wow danke für deinen Vorschlag zur Rule.
Könnte ich die "Grenzwerte" auch über eine Eingabe verändern ?
Ansonsten müsste ich ja ggf immer in der Rule ändern.
Und könnte ich die logInfo "Aussenluft Manuell" auch dann zb. im Habpanel anzeigen lassen ?

Viele Grüße

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 13:26
von peter-pan
Hi Peter,
ich kenne mich leider auch nicht besonders gut aus und bei Habpanel schon garnicht, das benutze ich nicht.
Ich probiere mal, ob man da was mit dem Setpoint-Widget in der Sitemap machen kann.
Aber hat @udo1toni eine Idee und kann dir weiterhelfen. Der kriegt so was hin, wenn es machbar ist.

Gruss Peter

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 14:59
von peter-pan
Also, als erstes brauchst du zwei zusätzliche Items:

Code: Alles auswählen

Number AussenGrenzMin_Set       "Aussentemperatur Grenzwert min [%.1f °C]"
Number AussenGrenzMax_Set       "Aussentemperatur Grenzwert max [%.1f °C]"
in deiner Sitemap ergänzt du, da wo du es haben möchtest:

Code: Alles auswählen

    Setpoint item=AussenGrenzMin_Set minValue=14.0 maxValue=20.0 step=0.5  //Selektion für Minimalwert
    Setpoint item=AussenGrenzMax_Set minValue=20.1 maxValue=25.0 step=0.5  //Selektion für Maximalwert
    Text item=Aussenluft
    Text item=Luefterstufe
    Default item=Dummy4  // manueller Schalter
 
Die Regel sieht dann so aus:

Code: Alles auswählen

rule "Aussenluft manuell1"
when
    Item Aussenluft changed
then
   if(Dummy4.state != ON) return;  // wenn Schalter aus(nicht an) , keine Aktionen
    
   if(!(Aussenluft.state instanceof Number)) {
        logWarn("Aussenluft manuell","Aussenluft.state not a Number: {}",Aussenluft.state)  // numerisch ?
        return;
   }
   if (Aussenluft.state >= AussenGrenzMax_Set.state && Luefterstufe != 0) {
       Luefterstufe.sendCommand(0)
       logInfo("Aussenluft manuell","Luefterstufe ist jetzt: {} Aussenluft beträgt {}",Luefterstufe.state,Aussenluft.state )
       
   }
   else if (Aussenluft.state <= AussenGrenzMin_Set.state && Luefterstufe.state != 2) {  
       Luefterstufe.sendCommand(2)
       logInfo("Aussenluft manuell","Luefterstufe ist jetzt: {} Aussenluft beträgt {}",Luefterstufe.state,Aussenluft.state)
       
   }
end
Das Ganze sieht dann vielleicht so aus:
luefter.jpg
...oder so ähnlich. In meinen Tests hat es funktioniert. Lediglich im Logger wird bei der Lüfterstufe immer der vorherige Wert angezeigt. In der Sitemap ist aber alles korrekt. Evtl. muss man mit "postUpdate" arbeiten, aber ich weiss nicht, wie sich das auf das Verhalten des Lüfterstatus auswirkt (oder nicht).

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 21:51
von PeterA
Hi peter-pan,

das funktioniert sehr gut soweit! Vielen Dank!
Nun ist mir folgendes aufgefallen:
Wenn die Rule über den Schalter "aktiv" ist und dann die Temperatur erreicht ist wird auch der Lüfter auf 0 geschaltet.
Aber das passiert dann bei jeder Veränderung der Temperatur..

Code: Alles auswählen

2019-02-17 21:41:43.972 [ome.event.ItemCommandEvent] - Item 'LuefterStufe' received command 0

==> /var/log/openhab2/openhab.log <==

2019-02-17 21:41:43.972 [INFO ] [home.model.script.Aussenluft manuell] - LuefterStufe ist jetzt: 0 Aussenluft beträgt 5.2

==> /var/log/openhab2/events.log <==

2019-02-17 21:41:43.980 [nt.ItemStatePredictedEvent] - LuefterStufe predicted to become 0

2019-02-17 21:41:44.090 [vent.ItemStateChangedEvent] - Abluftfeuchte changed from 50 to 49

2019-02-17 21:41:49.066 [vent.ItemStateChangedEvent] - Zuluft changed from 13.9 to 14.0

2019-02-17 21:41:49.178 [vent.ItemStateChangedEvent] - Aussenluft changed from 5.2 to 5.3

2019-02-17 21:41:49.193 [ome.event.ItemCommandEvent] - Item 'LuefterStufe' received command 0

==> /var/log/openhab2/openhab.log <==

2019-02-17 21:41:49.195 [INFO ] [home.model.script.Aussenluft manuell] - LuefterStufe ist jetzt: 0 Aussenluft beträgt 5.3

==> /var/log/openhab2/events.log <==

2019-02-17 21:41:49.200 [nt.ItemStatePredictedEvent] - LuefterStufe predicted to become 0

2019-02-17 21:41:49.300 [vent.ItemStateChangedEvent] - Abluftfeuchte changed from 49 to 50

2019-02-17 21:41:54.448 [vent.ItemStateChangedEvent] - Aussenluft changed from 5.3 to 5.4

2019-02-17 21:41:54.457 [ome.event.ItemCommandEvent] - Item 'LuefterStufe' received command 0

2019-02-17 21:41:54.461 [nt.ItemStatePredictedEvent] - LuefterStufe predicted to become 0

==> /var/log/openhab2/openhab.log <==

2019-02-17 21:41:54.470 [INFO ] [home.model.script.Aussenluft manuell] - LuefterStufe ist jetzt: 0 Aussenluft beträgt 5.4


Re: Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 23:30
von udo1toni
Innerhalb des if() muss es Luefterstufe.state != 0 heißen. ohne das .state ist das Item selbst gemeint, welches natürlich niemals 0 ist.

Der Code wird so funktionieren, aber da ich es nicht sein lassen kann... Es ist wichtig, zu verstehen, dass .state einen Status zurück gibt, keine Zahl. Auch wenn der Status eine Zahl ist, wird openHAB diese Zahl zunächst nur als Status betrachten. openHAB ist aber schlau genug, bei Bedarf ein TypeCasting durchzuführen. Wenn man das selbst beim Programmieren macht, fallen kleinere Fehler schneller auf. Die Rule sollte also am besten so aussehen:

Code: Alles auswählen

rule "Aussenluft manuell1"
when
    Item Aussenluft changed or
    Item AussenGrenzMax_Set changed or
    Item AussenGrenzMin_Set changed
then
   if(Dummy4.state != ON) return;  // wenn Schalter aus(nicht an) , keine Aktionen
    
   if(!(Aussenluft.state instanceof Number)) {
        logWarn("Aussenluft manuell","Aussenluft.state not a Number: {}",Aussenluft.state)  // numerisch ?
        return;
   }
   if ((Aussenluft.state as Number) >= (AussenGrenzMax_Set.state as Number) && (Luefterstufe.state as Number) != 0) {
       Luefterstufe.sendCommand(0)
       logInfo("Aussenluft manuell","Luefterstufe ist jetzt: {} Aussenluft beträgt {}",Luefterstufe.state,Aussenluft.state )
       
   }
   else if ((Aussenluft.state as Number) <= (AussenGrenzMin_Set.state as Number) && (Luefterstufe.state as Number) != 2) {  
       Luefterstufe.sendCommand(2)
       logInfo("Aussenluft manuell","Luefterstufe ist jetzt: {} Aussenluft beträgt {}",Luefterstufe.state,Aussenluft.state)
   }
end
Allerdings geht es gleich weiter mit dem Rumgekrittel. Wie verhinderst Du, dass jemand Min über Max definiert? Wie verhinderst Du, dass jemand Min = Max definiert?
Es wäre meiner Meinung besser, einen Grenzwert und die Hystere einstellbar zu machen. für die Hysterese kann man dann in der Sitemap beim Setpoint Widget eine untere Grenze von +1 und eine obere Grenze von (z.B.) +5 setzen. Genauso lässt sich die Grenztemperatur dann auch auf sinnvolle Werte beschränken.
Selbstverständlich ist es leicht möglich, sowohl Minimum als auch Maximum im Klartext anzuzeigen, auch wenn nur eine der beiden Temperaturen eingestellt wird und die andere über die Hysterese bestimmt wird.
Falls man tatsächlich Minimum und Maximum einstellen möchte, müsste man in der Rule Vorkehrungen treffen, z.B. dass das Maximum automatisch auf Minimum + 1 gesetzt wird, falls nach einer Änderung des Minimums das Minimum über oder gleich dem Maximum ist, genauso natürlich für den umgekehrten Fall.
Es bietet sich wegen der mehrfachen Nutzung der Werte an, diese in lokalen Konstanten zu speichern; dadurch bekommt die Rule etwas mehr Struktur:

Code: Alles auswählen

rule "Aussenluft manuell1"
when
    Item Aussenluft changed or
    Item AussenGrenzMax_Set changed or
    Item AussenGrenzHysterese_Set changed
then
    if(Dummy4.state != ON) return;  // wenn Schalter aus(nicht an) , keine Aktionen
    if(!(Aussenluft.state instanceof Number)) {
        logWarn("aussenluftManuell","Aussenluft.state not a Number: {}",Aussenluft.state)  // numerisch ?
        return;
    }
    val Number nTempOut = Aussenluft.state as Number
    if(!(AussenGrenzMax_Set.state instanceof Number)) {
        logWarn("aussenluftManuell","AussenGrenzMax_Set.state not a Number: {}",AussenGrenzMax_Set.state)  // numerisch ?
        return;
    }
    val Number nTempMax = AussenGrenzMax_Set.state as Number
    if(!(AussenGrenzHysterese_Set.state instanceof Number)) {
        logWarn("aussenluftManuell","AussenGrenzHysterese_Set.state not a Number: {}",AussenGrenzHysterese_Set.state)  // numerisch ?
        return;
    }
    val Number nTempMin = nTempMax - (AussenGrenzHysterese_Set.state as Number)
    if(!(Luefterstufe.state instanceof Number)) {
        logWarn("aussenluftManuell","Luefterstufe.state not a Number: {}",Luefterstufe.state)  // numerisch ?
        return;
    }
    val Number nStufe = Luefterstufe.state as Number
    var Number nStufeSoll = nStufe
    if (nTempOut >= nTempMax && nStufe != 0) nStufeSoll = 0
    if (nTempOut <= nTempMin && nStufe != 2) nStufeStoll = 2
    if(nStufe != nStufeSoll) {
       Luefterstufe.sendCommand(nStufeSoll)
       logInfo("aussenluftManuell","Luefterstufe geändert von {} auf {}. Aussenluft beträgt {}°C",nStufe,nStufeSoll,nTempOut)
    }
end
Wenn Maximum und Hysterese mit restoreOnStartup persistiert werden, kann die Prüfung auf instanceof Number natürlich entfallen. Bei der Außentemperatur sollte man immer prüfen, weil ein Sensor ja auch mal ausfallen kann. Bei der Luefterstufe habe ic hdas nur der Vollständigkeit halber getan.
Bei den Logzeilen habe ich den Kontext etwas geändert. Hintergrund ist: man kann das Loglevel für jeden Kontext getrennt einstellen. Wenn man im Kontext Leerzeichen verwendet, muss man dabei daran denken, den Kontext in Anführungszeichen zu setzen. Verzichtet man auf Leerzeichen, braucht man auch keine Anführungszeichen :)

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 17. Feb 2019 23:46
von PeterA
Oh Wow! Nicht schlecht :) und Vielen Dank!
Ich hab die rule jetzt schon mal getestet: Funktioniert!
Mir ist nur eines noch aufgefallen:
Nehmen wir mal an die Rule wird aktiv und die Anlage schaltet bei GrenzMax ab.
Ich deaktiviere aber zwischenzeitlich die Rule, dann sollte wieder der vorherige zustand der Lüfterstufe hergestellt werden.
Ist das machbar ? Es müsste ja quasi der Zustand VOR Aktivierung gemerkt werden ?

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 18. Feb 2019 09:30
von udo1toni
Klar, kann man alles machen. das Problem dabei ist, welcher vorherige Zustand? Am einfachsten wäre es vermutlich, das mit einer weiteren Rule abzudecken. Dabei fällt mir gerade auf, dass noch ein weiterer Trigger in der Rule fehlt, nämlich der des Schalters. Dabei reicht es, wenn der Trigger auf changed to ON erfolgt, die Rule macht ja nichts, falls der Schalter auf OFF wechselt.

Die zweite Rule sähe so aus:

Code: Alles auswählen

var Number nLuefter = -1

rule "Luefter Automatik"
when
    Item Dummy4 received command
then
    if(receivedCommand == ON && (Luefterstufe.state instanceof Number)) nLuefter = Luefterstufe.state as Number
    else if(receivedCommand == OFF && nLuefter > -1 ) Luefterstufe.sendCommand(nLuefter) 
end
Die Rule triggert auf received command und sollte somit vor der ersten Rule ausgeführt werden (die sollte ja auf changed to ON triggern).
Der korrekte Wert kann natürlich nur dann gesichert werden, wenn er auch zur Verfügung steht.
Genauso kann nur dann ein Wert zurückgeschrieben werden, wenn auch einer gespeichert wurde.

Es gibt noch eine weitere Variante, die allerdings erheblich aufwändiger ist. Sie setzt voraus, dass sowohl das Item Dummy4 als auch das Item Luefterstufe persistiert werden, und zwar nicht mit rrd4j oder mapdb, sondern z.B. mit jdbc. Dann kann man in einer Rule den letzten Zeitpunkt herausfinden, zu dem das Item Dummy4 von OFF nach ON gewechselt hat. Diesen Zeitpunkt kann man dann verwenden, um herauszufinden, welche Lüfterstufe gerade aktiv war.
Elegant ist das, weil es eventuell einen Neustart überleben kann (müsste man nochmal genauer anschauen) und man keine Variablen dafür benötigt.

Re: Unterstützung zur Erstellung einer Rule

Verfasst: 18. Feb 2019 10:42
von peter-pan
Na, siehst du, Udo hat meinen Fehler (mit dem .state) gleich entdeckt und das Ganze gleich in eine richtige Form gebracht. Der kann's halt. Deshalb lese ich seine Posts auch so gerne, auch im internationalen Forum. Da hab ich mir schon sehr viele Hilfen und Tipps geholt.