Warum hältst Du so krampfhaft an Variablen fest? Aber meinetwegen...
Globale Variablen (so wie Du sie suchst) gehen nur über Textdateien. Du musst die Rules in Dateien anlegen, die sich im Verzeichnis $OPENHAB_CONF/rules/ befinden müssen. Keine Unterverzeichnisse, Dateiname enthält bitte keine Sonderzeichen und endet mit
.rules
Alle Dateien, die auf global definierte Variablen zugreifen sollen müssen sich in der selben Datei befinden.
Beispiel:
Du hast eine Gruppe gSolltemperatur, in der sich alle Items befinden, an die Du eine Solltemperatur senden möchtest.
Code:
Code: Alles auswählen
// Globale Variablen und Konstanen müssen vor der ersten Rule definiert werden!
val HashMap<String,Number> sollMorgen = new HashMap [ "Wohnzimmer" -> 20 ,
"Bibliothek" -> 18 ,
"RSTHeizkorperthermostat1Schlafzimmer" -> 20 ,
"RSTSpielzimmerDaddelbar" -> 18 ,
"RST_HeizkorperthermostatKuecheNeu" -> 18 ,
"RSTHeizkorperthermostatToiletteToilette" -> 9 ,
"RSTHeizkorperthermostat1Bad" -> 18 ]
rule "Werte Schreiben"
when
Item VariableActuatorMorgens_Status changed to ON
then
if(VariableActuatorWeggehen_Status.state == ON) // falls abwesend
return; // Rule abbrechen
VariableActuatorAbends_Status.postUpdate(OFF) // Status der anderen Items setzen
VariableActuatorNachmittags_Status.postUpdate(OFF)
gSolltemperatur.members.forEach[i| // für jeden Gruppenangehörigen
val myWert = sollMorgen.get(i.name.split("_").get(0)) // den passenden Wert auslesen
i.sendCommand(myWert) // schreiben
Thread.sleep(500) // Pause einlegen
]
gSolltemperatur.members.forEach[i| // und noch ein zweites Mal
val myWert = sollMorgen.get(i.name.split("_").get(0))
i.sendCommand(myWert)
Thread.sleep(500)
]
end
Da VariableActuatorAbends_Status und VariableActuatorNachmittags_Status mutmaßlich nicht an Livisi Channel gebunden sind, braucht es hier vermutlich weder ein sendCommand() noch ein Thread.sleep()
Es wäre sinnvoll, zunächst die Itemnamen zu vereinfachen. Ein typisches Schema wäre Raum_Funktion, wobei Raum eventuell auch noch einen Zähler enthalten kann, wenn mehrere gleichartige Geräte innerhalb des selben Raums vorhanden sind (also z.B. mehrere Heizkörperthermostate, die individuell angesteuert werden müssen)
Da das zweimalige Schreiben aller Werte vergleichsweise umständlich ist, habe ich oben der Einfachheit halber ebenfalls auf Redundanz gesetzt

aber Du siehst, dass es sich nur um vier doppelte Zeilen handelt.
Der Punkt ist aber, die selbe (!) Rule kann sich zusätzlich noch um alle anderen Temperaturen kümmern.
Ein Punkt dabei wäre, statt einzelner Switch Items für den Zustand Morgens, Abends, Nachmittags lieber ein String oder Number Item zu verwenden, damit sparst Du noch weiteren Code. Entweder Morgens oder Abends oder Nachmittags, keiner der Zustände kann zeitgleich auftreten, also braucht es auch nur ein Item dafür, z.B. Tageszeit (ein weiterer Tipp wäre, unnötige Informationen ebenfalls zu vermeiden, also z.B. auf Begriffe wie Variable und Status zu verzichten. Und die Tageszeit ist vermutlich auch keine Eigenschaft eines Aktuators.
In einer ersten Optimierung ergäbe sich also:
Code: Alles auswählen
// Globale Variablen und Konstanen müssen vor der ersten Rule definiert werden!
val HashMap<String,Number> sollMorgen = new HashMap [ "Wohnzimmer" -> 20 ,
"Bibliothek" -> 18 ,
"Schlafzimmer" -> 20 ,
"Daddelbar" -> 18 ,
"Kueche" -> 18 ,
"Toilette" -> 9 ,
"Bad" -> 18 ]
val HashMap<String,Number> sollAbend = new HashMap [ "Wohnzimmer" -> 20 ,
"Bibliothek" -> 18 ,
"Schlafzimmer" -> 20 ,
"Daddelbar" -> 18 ,
"Kueche" -> 18 ,
"Toilette" -> 9 ,
"Bad" -> 18 ]
val HashMap<String,Number> sollMittag = new HashMap [ "Wohnzimmer" -> 20 ,
"Bibliothek" -> 18 ,
"Schlafzimmer" -> 20 ,
"Daddelbar" -> 18 ,
"Kueche" -> 18 ,
"Toilette" -> 9 ,
"Bad" -> 18 ]
rule "Werte Schreiben"
when
Item Tageszeit changed
then
if(Abwesend.state == ON) // falls abwesend
return; // Rule abbrechen
switch(newState) {
case "Morgens" : {
gSolltemperatur.members.forEach[i| // für jeden Gruppenangehörigen
val myWert = sollMorgen.get(i.name.split("_").get(0)) // den passenden Wert auslesen
i.sendCommand(myWert) // schreiben
Thread.sleep(500) // Pause einlegen
]
gSolltemperatur.members.forEach[i| // und noch ein zweites Mal
val myWert = sollMorgen.get(i.name.split("_").get(0))
i.sendCommand(myWert)
Thread.sleep(500)
]
}
case "Mittags" : {
gSolltemperatur.members.forEach[i| // für jeden Gruppenangehörigen
val myWert = sollMittag.get(i.name.split("_").get(0)) // den passenden Wert auslesen
i.sendCommand(myWert) // schreiben
Thread.sleep(500) // Pause einlegen
]
gSolltemperatur.members.forEach[i| // und noch ein zweites Mal
val myWert = sollMittag.get(i.name.split("_").get(0))
i.sendCommand(myWert)
Thread.sleep(500)
]
}
case "Abends" : {
gSolltemperatur.members.forEach[i| // für jeden Gruppenangehörigen
val myWert = sollAbend.get(i.name.split("_").get(0)) // den passenden Wert auslesen
i.sendCommand(myWert) // schreiben
Thread.sleep(500) // Pause einlegen
]
gSolltemperatur.members.forEach[i| // und noch ein zweites Mal
val myWert = sollAbend.get(i.name.split("_").get(0))
i.sendCommand(myWert)
Thread.sleep(500)
]
}
end
Nun Stelle Dir aber bitte vor, Du hast weitere (ungebundene) Items für die verschiedenen Temperaturen (pro Raum, versteht sich), und zwar folgenderrmaßen:
gSolltemperatur ist die übergeordnete Gruppe (alle nachfolgenden Items befinden sich in dieser Gruppe) pro Raum mehrere Items in der Form
Wohnzimmer_Solltemperatur, Wohnzimmer_SollMorgen, Wohnzimmer_SollMittag, Wohnzimmer_SollAbend, Wohnzimmer_SollSchatten
Nun die Rule dazu:
Code: Alles auswählen
rule "Werte Schreiben"
when
Item Tageszeit changed
then
if(Abwesend.state == ON) // falls abwesend
return; // Rule abbrechen
var strQuelle = "SollWeg"
switch(newState) {
case "Morgens" : strQuelle = "SollMorgen"
case "Mittags" : strQuelle = "SollMittag"
case "Abends" : strQuelle = "SollAbend"
}
// Werte zwischenspeichern
gSolltemperatur.members.filter[i|i.name.endsWith("SollSchatten")].forEach[| // nimm alle Items für den Schattenwert
val myWert = gSolltemperatur.members.filter[i.name.split("_").get(0) && i.name.endsWith(strQuelle)].head // suche den neuen Sollwert heraus
i.postUpdate(myWert) // speichere den Schattenwert
]
// Befehle senden
gSolltemperatur.members.filter[i|i.name.endsWith("Solltemperatur")].forEach[i| // für jede Solltemperatur
val myWert = gSolltemperatur.members.filter[i|i.name.endsWith("SollSchatten")].head // den passenden Wert auslesen
i.sendCommand(myWert) // schreiben
Thread.sleep(500) // Pause einlegen
]
gSolltemperatur.members.filter[i|i.name.endsWith("Solltemperatur")].forEach[i| // für jede Solltemperatur
val myWert = gSolltemperatur.members.filter[i|i.name.endsWith("SollSchatten")].head // den passenden Wert auslesen
i.sendCommand(myWert) // schreiben
Thread.sleep(500) // Pause einlegen
]
end
Du hast nun keine globalen Variablen mehr, sondern speicherst die konkreten Sollwerte in Items. Weil alle Items in der selben Gruppe liegen, muss die Gruppe beim Zugriff jeweils gefiltert werden, wahlweise kann man hier auch mit getrennten Gruppen arbeiten, das spielt aber unterm Strich keine Rolle. Wichtig ist nur, dass die Itemnamen passend gewählt sind. Die Solltemperaturen pro Zustand müssen nur einmalig festgelegt werden, dazu nutzt Du eine Persistence, um den letzten Wert beim Neustart des Systems wiederherzustellen (MapDB ist da das beste). Du kannst auch in der UI passende Ansichten gestalten, um die Solltemperaturen bei Bedarf anzupassen.
Alternativ definierst Du eine Rule, welche beim Systemstart die Sollwerte aus einer HashMap in die passenden Items schreibt.