Die Frage ist zunächst, wie Deine Items definiert sind.
Ist
AUSonnenstand vom Typ
Number? Oder ist es vom Typ
Number:Angle (das wäre z.B. der Fall, wenn Du das mit dem Channel
astro:sun:local:azimuth automatisch verlinkt hast und es automatisch generiert wurde)
Weiterhin wird die erste Rule maximal ein
ON senden, aber niemals ein
OFF (es sei denn, Du hast die Aktualisierungsrate der Quelle so absurd niedrig eingestellt, dass die Sonne innerhalb eines Messzyklus von weniger als
136° auf mehr als
195° wandert - faul gerechnet wären das 4 Stunden.
So wäre es eher sinnvoll:
Code: Alles auswählen
rule "Verschattung Wohnzimmer"
when
Item AUSonnenstand changed
then
if(!(newState instanceof Number)) {
logWarn("autoshade","newState keine gültige Zahl! ({})",newState)
return;
}
val azimuth = (newState as Number).floatValue
var soll = OGWohnzimmerVerschattung.state
if(azimuth >= 137 && azimuth < 195)
soll = ON
else if(azimuth < 136 || azimuth >= 196)
soll = OFF
if(soll != OGWohnzimmerVerschattung.state)
OGWohnzimmerVerschattung.postUpdate(state.toString)
end
rule "Verschattung Wohnzimmer Jalousiefahrt"
when
Item OGWohnzimmerVerschattung changed
then
if(newState == ON) {
OGWohnzimmerJalousie_Rollensteuerung.sendCommand(DOWN)
OGWohnenBalkontuerJalousie.sendCommand(DOWN)
} else if(newState == OFF) {
OGWohnzimmerJalousie_Rollensteuerung.sendCommand(UP)
OGWohnenBalkontuerJalousie.sendCommand(UP)
}
end
Der alte Status des Items interessiert eigentlich nicht. Wichtig ist, dass der neue Status sich im gewünschten Bereich befindet, also zwischen
137°und
195°.
Damit wir die Unsicherheit der eventuell vorhandenen Einheit nicht mehr berücksichtigen müssen, füllen wir eine lokale Konstante
azimuth mit dem aktuellen Status (
newState), allerdings zuerst gecastet nach
Number (weil ein Number Objekt die Methode
.floatValue kennt) und anschließend in eine Fließkommazahl gewandelt. Fließkommazahlen sind einheitenlos, also ohne das ° hintendran.
Dann wird eine lokale Variable mit dem aktuellen Status des Items
OGWohnzimmerVerschattung gefüllt. Anschließend wird die lokale Variable geändert, je nach Wert von
azimuth. Es gibt ein (kleines) Fenster von 1° auf beiden Seiten (also zwischen 136 und 137 sowie zwischen 195 und 196), in diesem Bereich soll der Wert einfach so bleiben wie er gerade ist, dafür dieser Umweg
In einem letzten Schritt wird er Status des Items
OGWohnzimmerVerschattung auf das neue Soll gebracht, unter der Voraussetzung, dass das Soll vom Ist abweicht.
Die Statusänderung wird dabei direkt vorgenommen, per
.postUpdate(). Die Methode
.sendCommand() sendet einen Befehl an das Item, ändert aber nicht dessen Status. openHAB "errät" anhand des Befehls den vermutlich zukünftigen Status des Items und löst ein
.postUpdate() mit dem neuen Status aus, um schon mal dieAnzeige aktuell zu haben, auch wenn die angesteuerte Hardware noch kein Status Update gesendet hat. Hier steuern wir aber mit hoher Wahrscheinlichkeit gar keine Hardware, sondern lediglich andere Rules. Dann kann man auch gleich
.postUpdate() verwenden
Zu guter Letzt reicht eine Rule um aufgrund des Status von
OGWohnzimmerVerschattung die beiden Jalousien zu fahren (eigentlich könnte man da sauch in der Rule oben abfrühstücken, aber vielleicht willst Du noch von weiteren Rules aus auf die Steuerung zugreifen).
Ich habe hier bewusst darauf verzichtet, auch
previousState abzufragen, denn wenn das System neu gestartet wird, hat das Item evtl. den Status
NULL, d.h. ein Befehl
ON oder
OFF würde von der zweiten Rule ignoriert, das ist vermutlich eher nicht der Wunsch.
Es gibt noch einen weiteren Punkt, falls es nämlich so ist, dass Du tatsächlich die Jalousien auch von anderer Stelle steuen möchtest, wird Dir obige Rule die Suppe versalzen. Dann sähe die erste Rule eher so aus:
Code: Alles auswählen
rule "Verschattung Wohnzimmer"
when
Item AUSonnenstand changed
then
if(!(newState instanceof Number)) {
logWarn("autoshade","newState keine gültige Zahl! ({})",newState)
return;
}
if(!(previousState instanceof Number)) {
logWarn("autoshade","previousState keine gültige Zahl! ({})",previousState)
return;
}
val azimuthOld = (previousState as Number).floatValue
val azimuth = (newState as Number).floatValue
var soll = OGWohnzimmerVerschattung.state
if(azimuthOld < 137 && azimuth >= 137)
soll = ON
else if(azimuthOld < 196 && azimuth >= 196)
soll = OFF
if(soll != OGWohnzimmerVerschattung.state)
OGWohnzimmerVerschattung.postUpdate(state.toString)
end
Nun prüft die Rule, ob vom letzten Stand zum neuen Stand die Untergrenze (137) überschritten wurde (sie war also kleiner als 137 und ist jetzt größer oder gleich). Dann wird die Beschattung aktiviert.
Falls stattdessen die Obergrenze (196) überschritten wurde, wird die Beschattung deaktiviert. Es gibt nun also exakt zwei Zeitpunkte am Tag, an denen die Rule aktiv in den Schaltzustand des Items
OGWohnzimmerVerschattung eingreift, sonst nicht. Somit kannst Du die Verschattung jederzeit manuell ein- oder ausschalten. Die Automatik wird lediglich zum errechneten Zeitpunkt die Verschattung aktivieren, falls nicht schon aktiv, bzw. deaktiveren, falls noch nicht inaktiv. Ich vermute, das ist das gewünschte Verhalten
openHAB4.2.2 stable in einem Debian-Container (bookworm) (Proxmox 8.2.8, LXC), mit openHABian eingerichtet