Grundsätzlich werden Befehle in der DSL nicht mit einem Semikolon abgeschlossen.
Grundsätzlich heißt, es gibt mindestens eine Ausnahme (in diesem Fall: exakt eine Ausnahme), und diese ist
return;
Der Grund hierfür: return dient dem Abbruch einer Rule. Dabei muss immer ein "Grund" für den Abbruch angegeben werden, das ist der nachfolgende Wert hinter return. Deshalb wird der nachfolgende Befehl verschluckt, wenn man kein Semikolon setzt. Nun könnte man auf die Idee kommen, einen konkreten Wert mitzugeben, das Dumme ist nur: das Script kann den Wert nirgends los werden, weshalb die Rule dann abstürzen würde. Man muss also einen null-Value übergeben, die einfachste Möglichkeit dazu ist das Semikolon.
Ansonsten kommt es in der DSL nicht vor.
Es ist möglich, dass es nicht direkt zu einem Fehler führt, wetten würde ich darauf aber nicht.
Ich gehe davon aus, dass Du den eigentlichen Befehl in das Script ausgelagert hast, weil Du dieses Script auch von anderen Rules aus ansprichst. In den meisten Fällen wird es elegantere Wege geben, damit umzugehen. Dazu gehört auch dieser fürchterliche Trigger, das ist wirklich nicht schön.
Besser stattdessen:
Code: Alles auswählen
// Globalen Variablen müssen zu Beginn der Datei definiert werden!
var Timer tKitchenColour = null
rule "Automatischer Farbwechsel Küche Sockel"
when
Item Automatischer_Farbwechsel_Kueche_Sockel changed or
Item EnergieTVWohnzimmer_Power changed or
Item RolloWohnzimmerrechts_Level changed
then
tKitchenColour?.cancel
if(Automatischer_Farbwechsel_Kueche_Sockel.state == OFF)
return;
if(!(EnergieTVWohnzimmer_Power.state instanceof Number)) {
logWarn("kitchenColor","Kann Stromaufnahme nicht ermitteln! Abbruch ({})",EnergieTVWohnzimmer_Power.state)
return;
}
if((EnergieTVWohnzimmer_Power.state as Number).floatValue <= 10)
return;
if(!(RolloWohnzimmerrechts_Level.state instanceof Number)) {
logWarn("kitchenColor","Kann Behanghöhe nicht ermitteln! Abbruch ({})",RolloWohnzimmerrechts_Level.state)
return;
}
if(RolloWohnzimmerrechts_Level.state <= 90)
return;
tKitchenColour = createTimer(now.plusNanos(10000000),[|
if(!(KuecheSockelZone_Farbe.state instanceof HSBType)) {
logWarn("kitchenColor","KuecheSockelZone_Farbe liefert kein HSB! Abbruch ({})",KuecheSockelZone_Farbe.state)
return;
}
val myHSB = KuecheSockelZone_Farbe.state as HSBType
var myHue = myHSB.hue + 1
if(myHue > 359) myHue = 0
val mySat = myHSB.saturation
var myBright = 65
if(KuecheSockelZone_Helligkeit.state == ON)
myBright = 30
val newHSB = new HSBType(myHue,mySat,myBright)
KuecheSockelZone_Farbe.sendCommand(newHSB) // alternativ: newHSB.toString
tKitchenColour.reschedule(now.plusSeconds(2))
])
end
Da ich kein farbiges Licht habe, kann ich es nicht selbst ausprobieren

Aber ein paar Kommentare zum Code:
Erst mal triggert die Rule nicht alle zwei Sekunden, sondern bei Wertänderung der beteiligten Items. Das spielt dann eine Rolle, wenn eine der Bedingungen dazu geführt hat, dass der Farbwechsel stoppt, denn somit läuft auch die Rule nicht mehr alle zwei Sekunden.
Der Rulecode beginnt mit einem Abbruch des Timers, falls er läuft. Nun werden nacheinander die verschiedenen Bedingungen abgefragt. Die Warnmeldungen sind nicht unbedingt notwendig, aber zumindest sinnvoll, bis die Rule so arbeitet wie gewünscht.
Ein Rollershutter Item (RolloWohnzimmerrechts_Level) hat keine Einheit, es ist also sinnlos, irgendwelche Verrenkungen anzustellen, um sie loszuwerden.
Sobald alle Hürden genommen sind, wird der Timer angelegt und fast unmittelbar ausgeführt.
Eigentlich sollte ein now() ohne .plusIrgendwas ausreichen, aber es gab schon mal Situationen, wo das nicht wunschgemäß funktioniert hat, deshalb also 10 ms Verzögerung.
Innerhalb des Timer Codeblocks prüft die Rule, ob ein gültiger HSB-Wert extrahiert werden kann (das ist gar nicht so sicher)
Dann wird der Wert extrahiert, hue bestimmt (unnötig, die Werte vollständig zu bestimmen), die Nummer mit dem Modulo Operator kann funktionieren, ich bin mir aber nicht sicher, welche Typvoraussetzungen dazu erfüllt sein müssen, deshalb die weniger elegante Methode.

Die Werte für Saturation und Brightness werden ebenso bestimmt und ein neuer Wert vom Typ HSB erzeugt.
Der Wert wird nun gesendet, und zwar mit der Methode .sendCommand, anstatt die Action sendCommand zu verwenden.
Zum Schluss plant der Code den Timer erneut ein, nach zwei Sekunden. Es ist gut möglich, dass der Code etwas Zeit zum Ausführen braucht, dann sollte man besser mit einer globalen Variablen arbeiten, die außerhalb des Timers gefüllt wird. Damit ließe sich der Zeitbedarf für die Berechnung minimieren.
openHAB5.0.3 stable in einem Debian-Container (trixie, OpenJDK 21 headless runtime - LXC, 4 Kerne, 3 GByte RAM)
Hostsystem Proxmox 9.1.2 - AMD Ryzen 5 3600 6 Kerne, 12 Threads - 64 GByte RAM - ZFS Pools: Raid Z1, 3 x 20 TB HDD -> 40 TByte und Raid Z0-Mirrored 4 x 1 TByte NVMe -> 2 TByte