while ist aus verschiedenen Gründen verpönt. Wenn Du in einer Rule auf den Status eines Items zugreifen willst, musst Du Item.state schreiben, Item ist das Item selbst (Der when Teil der Rule gehört nicht zum ausgeführten Code, das ist nur der Trigger, dort geht es ums Item).
Thread::sleep() (Groß/Kleinschreibung...) ist in diesem Zusammenhang auch keine gute Idee.
Da sind noch ein paar andere Ungereimtheiten mit drin, beispielsweise ist HSBType eben nicht vom Typ Number und kann auch nicht dorthin gecastet werden.
Ich bin jetzt nicht der Spezialist, was Color Steuerung betrifft, ich habe nur ein einziges Color Item, und das ist mit einem Selbstbauprojekt verbunden. Aber ich gehe davon aus, dass eine "bessere" Rule so aussieht:
Code: Alles auswählen
var Timer tDimmer = null
rule "Dimmer Taster"
when
Item IKEASchalter1_Button received command
then
if(receivedCommand.toString == "1001") {
tDimmer?.cancel
tDimmer = createTimer(now, [|
val HSBType currentState = LIFX_Spitzboden_Color.state as HSBType
val hue = currentState.hue
val sat = currentState.saturation
val bri = currentState.brightness + 5
if( bri > 100)
bri = 100
LIFX_Spitzboden_Color.sendCommand(new HSBType(hue, sat, bri))
if(bri < 100)
tDimmer.reschedule(now.plusMillis(500))
])
} else if(receivedCommand.toString == "1003") {
tDimmer?.cancel
tDimmer = null
}
end
Ich gehe hier von OH2 aus, bzw. davon, dass die Rule in einer *.rules Datei gespeichert ist. Die Rule benötigt globale Variablen, welche nur in rules Dateien zur Verfügung stehen. Diese Variable wird vor der ersten Rule in der Datei definiert (wichtig!)
Die Rule triggert auf received command, man könnte auch mit changed aerbeiten, aber eigentlich sollte ein Taster auch ein Kommando senden. Wenn received command nicht funktioniert, muss der Trigger auf changed geändert werden und in der if- Anweisung muss auf IKEASchalter1_Button.state.toString getestet werden.
Die Rule triggert genau zweimal, nämlich beim Drücken und beim Loslassen.
Beim Drücken wird der erste Teil des Codes ausgeführt. Zunächst wird ein eventuell laufender Timer abgebrochen, dann wird ein Timer angelegt und unmittelbar ausgeführt. Im Timer läuft der Code wie von Dir entworfen, es werden die drei Werte separiert und wieder zurückgeschrieben, allerdings nehme ich die Grenzwertbetrachtung etwas anders vor (wie ich glaube, etwas eleganter...)
Nachdem der Wert ins Item geschrieben wurde, wird der Timer neu geplant, das heißt, der Code bleibt so wie er ist erhalten. Das geschieht allerdings nur, solange noch nicht die Maximalhelligkeit erreicht ist. (bri < 100).
Wird die taste losgelassen, so wird der Timer unmittelbar abgebrochen und aus dem Scheduler entfernt.
Bei den Eigenschaften currentState.hue, .saturation und .brightness bin ich mir nicht sicher (wie gesagt, nutze ich praktisch nicht...), es könnte auch sein, dass new HSBType() als Zuweisung nicht funktioniert, dann wäre es einen Versuch wert, das so zu formulieren: (new HSBType(...)).toString also den HSBType als String zu übergeben.
Wie oben erwähnt ist das mit while in openHAB nicht gern gesehen. der Grund hierfür ist, dass openHAB für Rules exakt 5 + 2 Threads zur Verfügung stellt, es können also maximal 5 +2 Rules gleichzeitig ausgeführt werden. Läuft nun eine Rule "dauerhaft", so blockiert sie auch dauerhaft einen der Slots. Thread::sleep() tut genau das, was der Name sagt, sie legt den Thread für die angegebene Zeit schlafen, die Rule ist also aktiv und belegt den Slot. Im Gegensatz dazu läuft das mit der gezeigten Rule anders. Diese läuft nur wenige Millisekunden, eben gerade so lang, wie sie braucht, den Timer anzulegen.
Der Timer selbst läuft nur, wenn der Code gerade ausgeführt wird. der Scheduler in openHAB merkt sich die gewünschte Stratzeit und führt den Code zu diesem Zeitpunkt aus. der Reschedule ist dann die Schleife, aber eben indirekt, der Timer ruft sich selbst erneut auf und die Codeausführung ist danach beendet, also auch der Timer Code läuft nur wenige Millisekunden und wird dann (in openHAB-Größenordnungen) erst sehr viel später erneut aufgerufen. Dazwischen steht der benötigte Slot für andere Aufgaben zur Verfügung.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet