Rule erstellen mit Werten von bis

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Locke
Beiträge: 251
Registriert: 14. Apr 2020 11:35
Answers: 3
Wohnort: bei Hamburg

Rule erstellen mit Werten von bis

Beitrag von Locke »

Hi,
versuche gerade eine Regel zu erstellen, die bei Luftfeuchtigkeit (zb. > 60) einen Schalter einschaltet und über Alexa eine Meldung "Achtung es könnte Regnen" ausgibt.
Ich teste es im moment mit einem Dimmer (als Luftfeuchtigkeit) und einem Test Schalter.

Ist der Wert > 80 und < 60 soll der Schalter ausschalten und keine Meldung mehr von Alexa kommen.
ich bekomme es nicht hin den Wert > 80 mit einzubinden.

Könnt ihr mir dabei unter die Arme greifen ?

Code: Alles auswählen

rule "Achtung Regen"
            when
                Item DummyTesttestRegel_DummyTesttest changed
                
            then
                if ((DummyTesttestRegel_DummyTesttest.state as Number).floatValue > 60)  {

                    DummySchalter_TestSchalter.sendCommand(ON) }
                    
                                            
                else   
                { 
                    DummySchalter_TestSchalter.sendCommand(OFF)
                
                }
end
Danke
von udo1toni » 30. Jul 2022 11:57
Ja, natürlich geht das, muss aber dann anders unterschieden werden. Da wir nun mehrere Zustände im Gedächtnis behalten müssen, brauchen wir ein Number Item (natürlich ginge auch String, aber Number scheint hier angebracht).

Code: Alles auswählen

rule "Achtung Regen"
when
    Item DummyTesttestRegel_DummyTesttest changed
then
    var Integer iSoll = 0                                                          // Variable Sollzustand Item
    var Number nHumidity = 0                                                       // Variable Luftfeuchte
    var Integer iWarn = 0                                                          // Variable für aktuellen Status
    var strText = ""                                                               // Variable für Meldung

    if(DummyTesttestRegel_DummyTesttest.state instanceof Number)                   // Falls Itemstatus eine Zahl enthält
        nHumidity = (DummyTesttestRegel_DummyTesttest.state as Number).floatValue  // Übernimm diese Zahl als Luftfeuchte

    if(Warnwert.state instanceof Number)                                           // Weiteres Number Item auf gültige Zahl prüfen
        iWarn = (Warnwert.state as Number).intValue                                // und gegebenenfalls in Variable schreiben

    if(nHumidity < 60)      // wird hier gebraucht, um nicht beide Grenzwerte angeben zu müssen
        iSoll = 0
    else if(nHumidity < 70) // zwischen 60 und 70
        iSoll = 1
    else if(nHumidity < 80) // zwischen 70 und 80
        iSoll = 2
//  else                    // wird nicht gebraucht, nur zur Erläuterung
//      iSoll = 0           // 

    if(iWarn != iSoll) {                                                           // Falls soll von ist abweicht
        Warnwert.postUpdate(iSoll)                                                 // setze Status passend
        // weitere Anweisungen, z.B.
        if(iSoll == 1)
            strText = "Luftfeuchte zwischen 60 und 70 %!"
        else if(iSoll == 2)
            strText = "Luftfeuchte zwischen 70 und 80 %!"
        if(strText != "")
            // Alexa Sparachausgabe mit strText als Text
    }
end
Der grundsätzliche Aufbau bleibt aber erhalten. Nur werden jetzt drei verschiedene Zustände betrachtet.
Um nicht bei jedem Vergleich beide Grenzwerte angeben zu müssen. betrachte ich den Wert über ein if...else if... in aufsteigender Reihenfolge. Trifft die erste Bedingung nicht zu, ist der Wert automatisch größer als... und dieser Grenzwert kann entfallen.

Es gibt für diese Variante übrigens eine sehr gemeine Abkürzung, die ich Dir fast ans Herz legen möchte. Sie ist sehr elegant und hat nur einen Nachteil, die einzelnen Bestandteile sind etwas weiter im System verstreut, man muss also wissen, was an den einzelnen Stellen passiert, um den Code nachvollziehen zu können.

Benötigte Dinge:
  • Ein Number Item für den Level (0,1,2). (nennen wir es HumWarn)
  • Der Scale Transformation Service muss installiert sein.
  • Eine Datei /etc/openhab/transform/hum.scale mit folgendem Inhalt:

    Code: Alles auswählen

    [..60]=0
    ]60..70]=1
    ]70..80]=2
    ]80..]=0

Das Item HumWarn wird direkt mit dem Channel verlinkt, der die Luftfeuchte in % liefert. Im Link selbst wird als Profile SCALE angegeben und als Parameter wird hum.scale angegeben.

Nun sieht die Rule so aus:

Code: Alles auswählen

rule "Achtung Regen"
when
    Item HumWarn changed
then
    var Integer iWarn = 0                              // Variable für aktuellen Status
    var strText = ""                                   // Variable für Meldung

    if(HumWarn.state instanceof Number)                // falls Status gültige Zahl
        iWarn = (HumWarn.state as Number).intValue     // in Variable schreiben

    if(iWarn == 1)                                     // passende Meldung wählen
        strText = "Luftfeuchte zwischen 60 und 70 %!"
    else if(iWarn == 2)
        strText = "Luftfeuchte zwischen 70 und 80 %!"

    if(strText != "") {
        // Alexa Sparachausgabe mit strText als Text
    }
end
Die Zuweisung des korrekten Zahlenwertes hat die Scale Transformation vorgenommen. Das funktioniert natürlich genauso auch mit nur zwei Werten, ist aber nicht so naheliegend :)
Man könnte so sogar den Meldungstext direkt in ein String Item speichern, allerdings hat die Sachen einen Haken, der mit dem Number Item einigermaßen gut zu umgehen ist:
Es gibt nämlich nun zwei unterschiedliche Zustände, welche beide eine Meldung auslösen. Der Messwert wird sich immer kontinuierlich durch den Wertebereich bewegen. Es wäre also sinnvoll, zumindest zu verhindern, dass eine Sprachmeldung für Level 1 ausgegeben wird, wenn wir von Level 2 kommen:

Code: Alles auswählen

rule "Achtung Regen"
when
    Item HumWarn changed
then
    var Integer iWarnNew = 0                              // Variable für aktuellen Status
    var Integer iWarnOld = 0                              // Variable für vorherigen Status
    var strText = ""                                      // Variable für Meldung

    if(newState instanceof Number)                        // falls Status gültige Zahl
        iWarnNew = (newState as Number).intValue          // in Variable schreiben
    if(previousState instanceof Number)                   // falls Status gültige Zahl
        iWarnOld = (previousState as Number).intValue     // in Variable schreiben

    if(iWarnNew == 1)                                    // passende Meldung wählen
        strText = "Luftfeuchte zwischen 60 und 70 %!"
    else if(iWarnNew == 2)
        strText = "Luftfeuchte zwischen 70 und 80 %!"

    if(strText != "" && iWarnOld < iWarnNew) {
        // Alexa Sparachausgabe mit strText als Text
    }
end
Diese Prüfung ist natürlich bei der Ausgangsrule ebenso vonnöten, das ist mir aber gerade erst eingefallen... :)

previousState ist - genau wie newState - eine implizite Variable, die exakt dann zur Verfügung steht, wenn eine Rule auf changed getriggert hat. Sie enthält dann den Wert, den der Status des triggernden Items vor der Änderung hatte. newState enthält entsprechend den aktuellen Status.
Man kann beliebig viele Items mit einem Channel verlinken, mit den Transformations im Profile wird diese Option auch sehr sinnvoll - man sieht ja am obigen Beispiel, wie viel Code eingespart wird, ohne Verlust der Möglichkeit, die Luftfeuchte separat als diskreten Wert anzuzeigen.
Und sollte man mehrere gleichartige Items haben (meinetwegen Raumtemperaturen, die sich alle im gleichen Fenster bewegen sollen, sonst soll die Meldung "zu warm" oder "zu kalt" ausgegeben werden), so kann man die selbe scale Datei bei mehreren Transformations angeben.

Wenn man sicherstellt, dass die Items jederzeit einen gültigen Zahlenwert liefern (z.B. indem man das Item HumWarn mit mapdb persistiert und dort everyChange,restoreOnStartup angibt), kann man auch auf die Prüfung für newState verzichten und die Rule noch weiter einkürzen:

Code: Alles auswählen

rule "Achtung Regen"
when
    Item HumWarn changed
then
    if(!(previousState instanceof Number))                // kein gültiger Zahlenwert?
        return;                                           // dann wurde das System gerade neu gestartet, also Abbruch

    var strText = ""                                      // Variable für Meldung

    if((newState as Number) == 1)                         // passende Meldung wählen
        strText = "Luftfeuchte zwischen 60 und 70 %!"
    else if((newState as Number) == 2)
        strText = "Luftfeuchte zwischen 70 und 80 %!"

    if(strText != "" && newState < previousState) {
        // Alexa Sparachausgabe mit strText als Text
    }
end
Falls previousState keine Zahl liefert, muss das System gerade neu gestartet worden sein. Man kann die Rule dann einfach abbrechen, da mit hoher Wahrscheinlichkeit keine Sprachausgabe erwünscht ist. Unter diesen Umständen kann man sich den Umweg über die Variable natürlich genauso gut sparen. :)
Gehe zur vollständigen Antwort
thnx
____Sven_________________________________________________________________________________________
System 1, Raspberry Pi 4, 4GB RAM, openHAB 2.5.10 / System 2, Raspberry Pi 4, 2GB RAM, openHAB 3.3.0 /
System 3, Raspberry Pi 4, 2GB RAM, openHAB 4.0.2 / System 4 (Testsystem), Raspberry Pi 4, 2GB RAM, openHAB 4.1.1 / System 5, (als NAS) Raspberry PI 4, 4 GB RAM, openmediavault 6.8.0-1 (Shaitan)

Benutzeravatar
KellerK1nd
Beiträge: 432
Registriert: 17. Jun 2019 16:45
Answers: 1
Wohnort: Griesheim

Re: Rule erstellen mit Werten von bis

Beitrag von KellerK1nd »

Code: Alles auswählen

var Timer nTimer01=null																									//Timer am Anfang der Datei definieren

rule "Achtung Regen"
when
	Item DummyTesttestRegel_DummyTesttest changed
then
	var Number nLuftfeuchte = (DummyTesttestRegel_DummyTesttest.state as Number).floatValue								//Das Item als Variable setzen

	if((nLuftfeuchte > 60 && nLuftfeuchte < 80) && DummySchalter_TestSchalter.state == OFF){							//Luftfeuchte ist über 60% und kleiner 80% und der Eventschalter ist aus
		nTimer01.cancel																									//laufenden Timer abbrechen
		DummySchalter_TestSchalter.sendCommand(ON)																		//Eventschalter einschalten
	}
	else if(nLuftfeuchte > 80 || nLuftfeuchte < 60 && DummySchalter_TestSchalter.state == ON && nTimer01===null){		//Luftfeuchte ist größer 80% oder kleiner 60% und der Eventschalter ist an und es läuft kein TImer
		nTimer01 = createTimer(now.plusMinutes(10),[|																	//Timer starten
			DummySchalter_TestSchalter.sendCommand(OFF)																	//Eventschalter ausschalten
			nTimer01=null
		])
	}
end
Das wäre jetzt mal mein Entwurf auf die schnelle. Ich habe einen Timer eingebaut um ein Flattern des Schalters in den Grenzbereichen zu vermeiden. Vermutlich schreibt Udo das ganze kürzer und effizienter. :D
Betriebssystem: Proxmox 7.3-4
openHAB Container: debian11 LXC
openHAB Version: 3.4
Hardware: HomeServer Eigenbau mit einem Intel i5 9600K
Smarthome-Equipment:
- Rasperrymatic
- deConz
- HUE
- Shellys
- Mosquitto
- AVM Fritz!Box

Locke
Beiträge: 251
Registriert: 14. Apr 2020 11:35
Answers: 3
Wohnort: bei Hamburg

Re: Rule erstellen mit Werten von bis

Beitrag von Locke »

KellerK1nd hat geschrieben: 29. Jul 2022 15:34 Das wäre jetzt mal mein Entwurf auf die schnelle.
Hi Kellerk1nd,
super ich danke Dir, wäre ich nie drauf gekommen (mache halt zu wenig wenig mit den Regeln) :roll: .
Beim Testen funktioniert es leider nicht richtig.
Wenn ich den Timer kpl. rausnehme läuft es. Ich habe im Netz gefunden das wohl "Leerzeichen" bei nTimer01 == null sein sollten.
Damit geht es zur hälfte (Timer habe ich auf now.plusSeconds(5) zum testen gesetzt), der Schalter geht bei > 80 nach 5 sekunden auf OFF, sowie auch bei < 60.
Wenn ich jetzt auf zb. 70 gehe schaltet der Schalter nicht auf ON, irgendwie hängt es bei "nTimer01.cancel". Entferne ich "nTimer01.cancel" läuft es.
Habe es schon mit "nTimer01.cancel();" probiert, läuft dann auch nicht.
Hast Du eine Idee woran es liegt ?

Wäre es möglich noch einen Wert hinzuzufügen zb. > 70 um eine zweite Meldung (als Erinnerung) über Alexa auszugeben, also nicht nur zwischen > 60 und < 80, sondern auch bei > 70 ?

Code: Alles auswählen

var Timer nTimer01 = null																									//Timer am Anfang der Datei definieren

rule "Achtung Regen"
when
	Item DummyTesttestRegel_DummyTesttest changed
then
	var Number nLuftfeuchte = (DummyTesttestRegel_DummyTesttest.state as Number).floatValue								//Das Item als Variable setzen

	if((nLuftfeuchte > 60 && nLuftfeuchte < 80) && DummySchalter_TestSchalter.state == OFF){							//Luftfeuchte ist über 60% und kleiner 80% und der Eventschalter ist aus
		nTimer01.cancel();																								//laufenden Timer abbrechen
		DummySchalter_TestSchalter.sendCommand(ON)																		//Eventschalter einschalten
	}
	else if(nLuftfeuchte > 80 || nLuftfeuchte < 60 && DummySchalter_TestSchalter.state == ON && nTimer01 === null){		//Luftfeuchte ist größer 80% oder kleiner 60% und der Eventschalter ist an und es läuft kein TImer
		nTimer01 = createTimer(now.plusSeconds(5),[|																	//Timer starten
			DummySchalter_TestSchalter.sendCommand(OFF)																	//Eventschalter ausschalten
			nTimer01 = null
		])
	}
end
thnx
____Sven_________________________________________________________________________________________
System 1, Raspberry Pi 4, 4GB RAM, openHAB 2.5.10 / System 2, Raspberry Pi 4, 2GB RAM, openHAB 3.3.0 /
System 3, Raspberry Pi 4, 2GB RAM, openHAB 4.0.2 / System 4 (Testsystem), Raspberry Pi 4, 2GB RAM, openHAB 4.1.1 / System 5, (als NAS) Raspberry PI 4, 4 GB RAM, openmediavault 6.8.0-1 (Shaitan)

Benutzeravatar
KellerK1nd
Beiträge: 432
Registriert: 17. Jun 2019 16:45
Answers: 1
Wohnort: Griesheim

Re: Rule erstellen mit Werten von bis

Beitrag von KellerK1nd »

Code: Alles auswählen

rule "Achtung Regen"
when
	Item DummyTesttestRegel_DummyTesttest changed
then
	var Number nLuftfeuchte = (DummyTesttestRegel_DummyTesttest.state as Number).floatValue								//Das Item als Variable setzen

	if((nLuftfeuchte > 60 && nLuftfeuchte < 80) && DummySchalter_TestSchalter.state == OFF){							//Luftfeuchte ist über 60% und kleiner 80% und der Eventschalter ist aus
		nTimer01?.cancel																									//laufenden Timer abbrechen
		DummySchalter_TestSchalter.sendCommand(ON)																		//Eventschalter einschalten
	}
	else if(nLuftfeuchte > 80 || nLuftfeuchte < 60 && DummySchalter_TestSchalter.state == ON && nTimer01===null){		//Luftfeuchte ist größer 80% oder kleiner 60% und der Eventschalter ist an und es läuft kein TImer
		nTimer01 = createTimer(now.plusMinutes(10),[|																	//Timer starten
			DummySchalter_TestSchalter.sendCommand(OFF)																	//Eventschalter ausschalten
			nTimer01=null
		])
	}
end
Ich hatte einen Fehler im Abbruch des Timers drin (nTimer01?.cancel), das Fragezeichen fehlte.

Ich hätte noch eine Idee, allerdings fehlt es mir da an Know-How. Man könnte über eine Boolean-Variable zwei Stadi setzen, einmal den Zustand zwischen 60 und 80% (true) und den Status vor 60 und nach 80% (false).
Betriebssystem: Proxmox 7.3-4
openHAB Container: debian11 LXC
openHAB Version: 3.4
Hardware: HomeServer Eigenbau mit einem Intel i5 9600K
Smarthome-Equipment:
- Rasperrymatic
- deConz
- HUE
- Shellys
- Mosquitto
- AVM Fritz!Box

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

Re: Rule erstellen mit Werten von bis

Beitrag von udo1toni »

Also, das erste ist mal, ein Wert kann niemals größer als 80 UND kleiner als 60 sein. Semantisch mag ein Mensch die nötige Transferleistung erbringen, der PC ist aber suuuper pingelig und leider nicht in der Lage, diese Ungenauigkeit richtig zu interpretieren.

Eine mögliche Rule:

Code: Alles auswählen

rule "Achtung Regen"
when
    Item DummyTesttestRegel_DummyTesttest changed
then
    var soll = OFF                                                                 // Variable Sollzustand Item
    var Number nHumidity = 0                                                       // Variable Luftfeuchte

    if(DummyTesttestRegel_DummyTesttest.state instanceof Number)                   // Falls Itemstatus eine Zahl enthält
        nHumidity = (DummyTesttestRegel_DummyTesttest.state as Number).floatValue  // Übernimm diese Zahl als Luftfeuchte

    if(nHumidity > 60 && nHumidity < 80)                                           // Falls Luftfeuchte zwischen 60 und 80
        soll = ON                                                                  // Setze soll auf ON

    if(DummySchalter_TestSchalter.state != soll) {                                 // Falls soll von ist abweicht
        DummySchalter_TestSchalter.postUpdate(soll.toString)                       // setze Status passend
        // weitere Anweisungen, z.B.
        if(soll == ON) {
            // Alexa Sprachausgabe
        }
    }
end
Der Aufbau der Rule sollte einigermaßen klar sein. Ich verwende hier Variablen, statt direkt mit den Status zu arbeiten, das hat verschiedene Gründe.
Erst mal die Variable soll, die steht anfangs auf OFF. Dann die Variable nHumidity, die ist anfangs 0.
Nun prüft die Rule, ob der Status der Luftfeuchte vom Typ Number ist. Ist das der Fall, so wird die Variable nHumidity mit eben diesem Status gefüllt.
Erst jetzt, nachdem sicher ist, dass wir auf jeden Fall ein vernünftiges Ergebnis bei unserem Vergleich bekommen, prüft die Rule, ob nHumidity zwischen 60 und 80 liegt. Ist das der Fall, so wird soll auf ON gesetzt.

Abschließend prüft die Rule, ob der aktuelle Status des Switch von soll abweicht. Nur in diesem Fall wird der Switch geschaltet (und bei Bedarf können hier auch noch andere Befehle untergebracht werden, wie im Beispiel).

Warum so kompliziert? Nun, ein Number Item (und im Grunde jeder andere Itemtyp ebenfalls) kann immer auch die Status NULL und UNDEV enthalten, welche im Fall eines Castings nach Number dann eine NullPointer Exception auslösen.
Warum der Umweg über soll? Weil man damit potenziell Code sparen kann. Hier gibt es nur zwei Bedingungen (größer 60 und kleiner 80) und nur zwei mögliche Zustände, aber man kann beliebig viele mögliche Zustände und Befehle haben. So wie gezeigt, gibt es nur eine Stelle im Code, an der geprüft wird, ob es überhaupt notwendig ist, den Befehl zu senden. Nur bei einem Wechsel des Zustands wird das Item auch umgeschaltet; nur unter dieser Bedingung spricht Alexa, falls der neue Zustand ON ist.
Da die Luftfeuchte ein träger Messwert ist, kann man vermutlich auf einen Timer zur Unterdrückung von Mehrfachmeldungen gänzlich verzichten.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Locke
Beiträge: 251
Registriert: 14. Apr 2020 11:35
Answers: 3
Wohnort: bei Hamburg

Re: Rule erstellen mit Werten von bis

Beitrag von Locke »

Moin Udo,
Moin Kellerk1nd,
danke für eure Hilfe. Ich teste gerade die von Udo.
Kann man noch einen dritten Wert einsetzen, als Erinnerung zb. wenn der Wert über 70 geht, so das Alexa nochmal eine Meldung gibt ?
Ich bekomme es nicht eingebaut.
Da der Schalter bei < 60 ja schon ON ist, kommt ja dann keine Meldung mehr von Alexa. Die Regierung hier :roll: hätte gern eine zweite Meldung falls sie die erste versäumt um rechtzeitig die Wäsche reinzuholen.

Sonst alles super :D

Danke euch

PS.: Udo schläfst Du auch mal ?
thnx
____Sven_________________________________________________________________________________________
System 1, Raspberry Pi 4, 4GB RAM, openHAB 2.5.10 / System 2, Raspberry Pi 4, 2GB RAM, openHAB 3.3.0 /
System 3, Raspberry Pi 4, 2GB RAM, openHAB 4.0.2 / System 4 (Testsystem), Raspberry Pi 4, 2GB RAM, openHAB 4.1.1 / System 5, (als NAS) Raspberry PI 4, 4 GB RAM, openmediavault 6.8.0-1 (Shaitan)

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

Re: Rule erstellen mit Werten von bis

Beitrag von udo1toni »

Ja, natürlich geht das, muss aber dann anders unterschieden werden. Da wir nun mehrere Zustände im Gedächtnis behalten müssen, brauchen wir ein Number Item (natürlich ginge auch String, aber Number scheint hier angebracht).

Code: Alles auswählen

rule "Achtung Regen"
when
    Item DummyTesttestRegel_DummyTesttest changed
then
    var Integer iSoll = 0                                                          // Variable Sollzustand Item
    var Number nHumidity = 0                                                       // Variable Luftfeuchte
    var Integer iWarn = 0                                                          // Variable für aktuellen Status
    var strText = ""                                                               // Variable für Meldung

    if(DummyTesttestRegel_DummyTesttest.state instanceof Number)                   // Falls Itemstatus eine Zahl enthält
        nHumidity = (DummyTesttestRegel_DummyTesttest.state as Number).floatValue  // Übernimm diese Zahl als Luftfeuchte

    if(Warnwert.state instanceof Number)                                           // Weiteres Number Item auf gültige Zahl prüfen
        iWarn = (Warnwert.state as Number).intValue                                // und gegebenenfalls in Variable schreiben

    if(nHumidity < 60)      // wird hier gebraucht, um nicht beide Grenzwerte angeben zu müssen
        iSoll = 0
    else if(nHumidity < 70) // zwischen 60 und 70
        iSoll = 1
    else if(nHumidity < 80) // zwischen 70 und 80
        iSoll = 2
//  else                    // wird nicht gebraucht, nur zur Erläuterung
//      iSoll = 0           // 

    if(iWarn != iSoll) {                                                           // Falls soll von ist abweicht
        Warnwert.postUpdate(iSoll)                                                 // setze Status passend
        // weitere Anweisungen, z.B.
        if(iSoll == 1)
            strText = "Luftfeuchte zwischen 60 und 70 %!"
        else if(iSoll == 2)
            strText = "Luftfeuchte zwischen 70 und 80 %!"
        if(strText != "")
            // Alexa Sparachausgabe mit strText als Text
    }
end
Der grundsätzliche Aufbau bleibt aber erhalten. Nur werden jetzt drei verschiedene Zustände betrachtet.
Um nicht bei jedem Vergleich beide Grenzwerte angeben zu müssen. betrachte ich den Wert über ein if...else if... in aufsteigender Reihenfolge. Trifft die erste Bedingung nicht zu, ist der Wert automatisch größer als... und dieser Grenzwert kann entfallen.

Es gibt für diese Variante übrigens eine sehr gemeine Abkürzung, die ich Dir fast ans Herz legen möchte. Sie ist sehr elegant und hat nur einen Nachteil, die einzelnen Bestandteile sind etwas weiter im System verstreut, man muss also wissen, was an den einzelnen Stellen passiert, um den Code nachvollziehen zu können.

Benötigte Dinge:
  • Ein Number Item für den Level (0,1,2). (nennen wir es HumWarn)
  • Der Scale Transformation Service muss installiert sein.
  • Eine Datei /etc/openhab/transform/hum.scale mit folgendem Inhalt:

    Code: Alles auswählen

    [..60]=0
    ]60..70]=1
    ]70..80]=2
    ]80..]=0

Das Item HumWarn wird direkt mit dem Channel verlinkt, der die Luftfeuchte in % liefert. Im Link selbst wird als Profile SCALE angegeben und als Parameter wird hum.scale angegeben.

Nun sieht die Rule so aus:

Code: Alles auswählen

rule "Achtung Regen"
when
    Item HumWarn changed
then
    var Integer iWarn = 0                              // Variable für aktuellen Status
    var strText = ""                                   // Variable für Meldung

    if(HumWarn.state instanceof Number)                // falls Status gültige Zahl
        iWarn = (HumWarn.state as Number).intValue     // in Variable schreiben

    if(iWarn == 1)                                     // passende Meldung wählen
        strText = "Luftfeuchte zwischen 60 und 70 %!"
    else if(iWarn == 2)
        strText = "Luftfeuchte zwischen 70 und 80 %!"

    if(strText != "") {
        // Alexa Sparachausgabe mit strText als Text
    }
end
Die Zuweisung des korrekten Zahlenwertes hat die Scale Transformation vorgenommen. Das funktioniert natürlich genauso auch mit nur zwei Werten, ist aber nicht so naheliegend :)
Man könnte so sogar den Meldungstext direkt in ein String Item speichern, allerdings hat die Sachen einen Haken, der mit dem Number Item einigermaßen gut zu umgehen ist:
Es gibt nämlich nun zwei unterschiedliche Zustände, welche beide eine Meldung auslösen. Der Messwert wird sich immer kontinuierlich durch den Wertebereich bewegen. Es wäre also sinnvoll, zumindest zu verhindern, dass eine Sprachmeldung für Level 1 ausgegeben wird, wenn wir von Level 2 kommen:

Code: Alles auswählen

rule "Achtung Regen"
when
    Item HumWarn changed
then
    var Integer iWarnNew = 0                              // Variable für aktuellen Status
    var Integer iWarnOld = 0                              // Variable für vorherigen Status
    var strText = ""                                      // Variable für Meldung

    if(newState instanceof Number)                        // falls Status gültige Zahl
        iWarnNew = (newState as Number).intValue          // in Variable schreiben
    if(previousState instanceof Number)                   // falls Status gültige Zahl
        iWarnOld = (previousState as Number).intValue     // in Variable schreiben

    if(iWarnNew == 1)                                    // passende Meldung wählen
        strText = "Luftfeuchte zwischen 60 und 70 %!"
    else if(iWarnNew == 2)
        strText = "Luftfeuchte zwischen 70 und 80 %!"

    if(strText != "" && iWarnOld < iWarnNew) {
        // Alexa Sparachausgabe mit strText als Text
    }
end
Diese Prüfung ist natürlich bei der Ausgangsrule ebenso vonnöten, das ist mir aber gerade erst eingefallen... :)

previousState ist - genau wie newState - eine implizite Variable, die exakt dann zur Verfügung steht, wenn eine Rule auf changed getriggert hat. Sie enthält dann den Wert, den der Status des triggernden Items vor der Änderung hatte. newState enthält entsprechend den aktuellen Status.
Man kann beliebig viele Items mit einem Channel verlinken, mit den Transformations im Profile wird diese Option auch sehr sinnvoll - man sieht ja am obigen Beispiel, wie viel Code eingespart wird, ohne Verlust der Möglichkeit, die Luftfeuchte separat als diskreten Wert anzuzeigen.
Und sollte man mehrere gleichartige Items haben (meinetwegen Raumtemperaturen, die sich alle im gleichen Fenster bewegen sollen, sonst soll die Meldung "zu warm" oder "zu kalt" ausgegeben werden), so kann man die selbe scale Datei bei mehreren Transformations angeben.

Wenn man sicherstellt, dass die Items jederzeit einen gültigen Zahlenwert liefern (z.B. indem man das Item HumWarn mit mapdb persistiert und dort everyChange,restoreOnStartup angibt), kann man auch auf die Prüfung für newState verzichten und die Rule noch weiter einkürzen:

Code: Alles auswählen

rule "Achtung Regen"
when
    Item HumWarn changed
then
    if(!(previousState instanceof Number))                // kein gültiger Zahlenwert?
        return;                                           // dann wurde das System gerade neu gestartet, also Abbruch

    var strText = ""                                      // Variable für Meldung

    if((newState as Number) == 1)                         // passende Meldung wählen
        strText = "Luftfeuchte zwischen 60 und 70 %!"
    else if((newState as Number) == 2)
        strText = "Luftfeuchte zwischen 70 und 80 %!"

    if(strText != "" && newState < previousState) {
        // Alexa Sparachausgabe mit strText als Text
    }
end
Falls previousState keine Zahl liefert, muss das System gerade neu gestartet worden sein. Man kann die Rule dann einfach abbrechen, da mit hoher Wahrscheinlichkeit keine Sprachausgabe erwünscht ist. Unter diesen Umständen kann man sich den Umweg über die Variable natürlich genauso gut sparen. :)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Locke
Beiträge: 251
Registriert: 14. Apr 2020 11:35
Answers: 3
Wohnort: bei Hamburg

Re: Rule erstellen mit Werten von bis

Beitrag von Locke »

udo1toni hat geschrieben: 30. Jul 2022 11:57 Ja, natürlich geht das, muss aber dann anders unterschieden werden.
omg :shock:
Ich werde mich später mal daran setzen und versuchen es umzusetzen, jetzt muss erstmal für's WE eingekauft werden, sonst gibt es Ärger :oops: mit der Regierung hier :lol:

Danke Dir für die ausführliche Anleitung, bin immer wieder sprachlos wie Du/Ihr es anscheinend aus den Ärmel schüttelt.
thnx
____Sven_________________________________________________________________________________________
System 1, Raspberry Pi 4, 4GB RAM, openHAB 2.5.10 / System 2, Raspberry Pi 4, 2GB RAM, openHAB 3.3.0 /
System 3, Raspberry Pi 4, 2GB RAM, openHAB 4.0.2 / System 4 (Testsystem), Raspberry Pi 4, 2GB RAM, openHAB 4.1.1 / System 5, (als NAS) Raspberry PI 4, 4 GB RAM, openmediavault 6.8.0-1 (Shaitan)

Locke
Beiträge: 251
Registriert: 14. Apr 2020 11:35
Answers: 3
Wohnort: bei Hamburg

Re: Rule erstellen mit Werten von bis

Beitrag von Locke »

udo1toni hat geschrieben: 30. Jul 2022 11:57

Code: Alles auswählen

rule "Achtung Regen"
when
    Item HumWarn changed
then
    var Integer iWarnNew = 0				  // Variable für aktuellen Status
    var Integer iWarnOld = 0                              // Variable für vorherigen Status
    var strText = ""                                      // Variable für Meldung

    if(newState instanceof Number)                        // falls Status gültige Zahl
        iWarnNew = (newState as Number).intValue          // in Variable schreiben
    if(previousState instanceof Number)                   // falls Status gültige Zahl
        iWarnOld = (previousState as Number).intValue     // in Variable schreiben

    if(iWarn == 1)                                        // passende Meldung wählen
        strText = "Luftfeuchte zwischen 60 und 70 %!"
    else if(iWarn == 2)
        strText = "Luftfeuchte zwischen 70 und 80 %!"

    if(strText != "" && iWarnOld < iWarnNew) {
        // Alexa Sparachausgabe mit strText als Text
    }
end
Diese Prüfung ist natürlich bei der Ausgangsrule ebenso vonnöten, das ist mir aber gerade erst eingefallen... :)
Hi Udo,
die Rule "ohne Prüfung läuft super, wenn ich allerdings die mit Prüfung nehme, mault VCS bei diesem Abschnitt.
"iWarn is undefined"
Ich denke es muss " var Integer iWarn = 0 " mit angegeben werden

Code: Alles auswählen

    
    var Integer iWarnNew = 0				  // Variable für aktuellen Status
    var Integer iWarnNew = 0                              // Variable für aktuellen Status
    var Integer iWarnOld = 0                              // Variable für vorherigen Status
    var strText = "" 
Werde mich jetzt mal an Deiner dritten Variante probieren, gebe dann Rückmeldung.
thnx
____Sven_________________________________________________________________________________________
System 1, Raspberry Pi 4, 4GB RAM, openHAB 2.5.10 / System 2, Raspberry Pi 4, 2GB RAM, openHAB 3.3.0 /
System 3, Raspberry Pi 4, 2GB RAM, openHAB 4.0.2 / System 4 (Testsystem), Raspberry Pi 4, 2GB RAM, openHAB 4.1.1 / System 5, (als NAS) Raspberry PI 4, 4 GB RAM, openmediavault 6.8.0-1 (Shaitan)

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

Re: Rule erstellen mit Werten von bis

Beitrag von udo1toni »

Nein, ich hatte ja den Namen auf iWarnNew geändert, weil in der letzten Rule previousState mit dazu kam. Ich dachte eigentlich, alle Bezüge angepasst zu haben, aber irgendwas rutscht halt immer durch...

Ich passe es oben an.

Allerdings muss ich noch mal fragen (nur sicherheitshalber) ob Du auch SCALE im Profile eingerichtet hast.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten