So schlecht sieht das schon gar nicht aus (ob es funktionieren wird, steht auf einem anderen Blatt).
Die Rule beinhaltet allerdings keinen Timer

dafür aber die Vorbereitung dafür, eine Liste von Wertetupeln zu durchlaufen.
Code: Alles auswählen
var List<String> colors = newArrayList("0,100,100", "60,100,100", "120,100,100", "180,100,100", "240,100,100")
var Integer colorIndex = 0 // Index als globales Integer Objekt
var Timer tColor = null // globales Timerobjekt
rule "Color Change Every 10 Seconds"
when
Item Kitchen_Party_Mode changed // Party Mode aktiviert oder deaktiviert
then
tColor?.cancel // Timer canceln, falls vorhanden
if(newState != ON) // Falls nicht ON
return; // Regel beenden
tColor = createTimer(now, [| // Timer anlegen
colorIndex += 1 // Index erhöhen
if(colorIndex >= colors.size) // Falls Obergrenze erreicht oder überschritten
colorIndex -= colors.size // Obergrenze abziehen
kitchen_color.sendCommand(colors.get(colorIndex)) // Farbwert an Color Item senden
tColor.reschedule(now.plusSeconds(10)) // Timer erneut ausführen in 10 Sekunden
])
end
Wichtig: Die Rule ist
sowohl für das Ein- wie auch das Ausschalten des Party Mode zuständig.
Wie auch immer ein Timer gesteuert wird, man muss sicherstellen, dass der Timer nur einmal läuft. Die einfachste Variante ist also, eventuell laufende Timer zu beseitigen, bevor man einen neuen Timer erstellt. Da dieses Beseitigen auch beim Ausschalten gebraucht wird, bietet es sich an, diese beiden Funktionen in einer Rule zu erledigen.
Gleich nach dem Beseitigen eventuell laufender Timer prüft die Rule den neuen Zustand des Schalters, falls dieser
nicht ON ist, kann die Rule beendet werden. Warum So rum und nicht andersrum? Weil damit die Schachtelungstiefe nicht erhöht wird

Ab der ersten Leerzeile ist also sichergestellt, dass der Timer gestartet werden muss, was auch umgehend passiert. Es wird also ein Timer angelegt und damit ist die Rule beendet. (unmittelbar!)
Im Anschluss(!) daran läuft der Timer zum ersten mal ab (weil die Startzeit des Timers
now ist).
Nun wird also der Timer Code ausgeführt, und der entspricht größtenteils der bereits vorhandenen Rule, der Index
colorIndex wird um eins erhöht. Anschließend wird geprüft, ob der Index die Grenze der Liste erreicht hat. Ist das der Fall, wird dieser Grenzwert abgezogen.
Warum nicht
%? (
% -> Modulo Operator), Modulo steht nur für
int zur Verfügung, nicht jedoch für
Integer. int (das Primitive) ist allerdings miserabel im Zusammenhang mit DSL Rules. Integer als Objekt ist wesentlich besser geeignet und verbraucht weniger Ressourcen.
Da Modulo nicht zur Verfügung steht, muss man den Grenzwert "manuell" abziehen, was aber (siehe Code) nicht sooo schlimm ist.
Nachdem der Index sich im erlaubten Bereich befindet (0 bis Listengröße - 1), kann aus der Liste ein wert entnommen werden und ins Item geschrieben werden. Anschließend wird der Timer erneu geplant, diesmal 10 Sekunden in der Zukunft.
Der Timer wird nun also so lange erneut aufgerufen, bis er über die Ursprungsrule gecancelt wird.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet