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:
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.
