openHAB bietet für Automationen die Rules DSL (DomainSpecificLanguage). Wie der Name schon vermuten lässt, geht es dabei immer um Rules.
Es reicht nicht, Befehle aneinander zu reihen, man muss sich sehr genau an die Form halten.
Jegliche Automation läuft über Rules. Jede Rule besitzt mindestens einen Trigger und genau einen Codeblock, der ausgeführt wird, sobald der Trigger auslöst. Die Trigger sind Events auf dem openHAB Bus.
eine Rule hat also immer die Form
Code: Alles auswählen
rule "Name der Rule (eineindeutig)"
when
<einer oder mehrere Trigger>
then
<auszuführender Code>
end
Die Schlüsselworte rule, when, then und end sind exakt so anzugeben. (Über Leerzeichen streiten wir uns jetzt nicht, aber es bietet sich an, zur Übersichtlichkeit auch eine gewisse Formatierung einzuhalten)
Es gibt verschiedene Trigger (kann man in der Doku gut nachlesen), insbesondere zeitbasierte und solche, die durch Befehle oder Statusänderungen auslösen.
Du möchtest einen Wecker programmieren, da wäre ein zeitbasierter Trigger natürlich naheliegend, allerdings muss man da aufpassen, denn der Trigger ist statisch, man kann also nicht den Zeitpunkt mittels Variablen oder ähnliches beeinflussen.
In Deinem Code taucht ein Trigger auf, nämlich Time cron "0 0 06 * * ?", die führende 0 könntest Du Dir sparen, der Trigger würde so aber um 6 Uhr morgens auslösen, und das wäre nicht beeinflussbar. Wenn Dir das reicht, prima, ich möchte es hier nur erwähnt haben.
openHAB arbeitet asynchron und eventbasiert. Das hat auch für die Rules Folgen. Beispielsweise kann eine Rule belieibig oft gestartet werden, aber openHAB stellt für die Ausführung von Rules nur 5 Threads zur Verfügung. Wenn also 5 Rules zeitgleich ablaufen, wird keine weitere Rule ausgeführt, bis mindestens eine der laufenden Rules ihre Arbeit beendet hat.
Warum ist das jetzt wichtig? Weil Thread::sleep() tatsächlich wörtlich zu nehmen ist. Der Thread, in dem dieser Befehl ausgeführt wird, schläft für die angegebene Zeitspanne. Die while-Schleife und der Zähler zusammen mit dem sleep bedeuten, dass dieser Thread 400 Sekunden läuft (die Laufzeit der restlichen Befehle spielt nur eine untergeordnete Rolle, vermutlich insgesamt nicht mal eine Sekunde).
Solange dies die einzige Rule ist, die sich so verhält, mag das noch gehen, aber es ist schlechter Stil und eine mögliche Falle, also solltest Du es gleich korrekt lösen, denn openHAB bietet einen besseren Mechanismus für verzögerte Iterationen, nämlich den Scheduler.
Die DSL kann Timer anlegen, die dann bei Erreichen der Startzeit vom Scheduler ausgeführt werden. Bis zu diesem Zeitpunkt werden weder Threads noch Rechenzeit verbraucht.
Deine Rule sollte deshalb besser so aussehen:
Code: Alles auswählen
// gloable Variablen werden zu Beginn der Datei definiert!
var Timer tWakeup = null // ein Timer Objekt
var Integer nDim = 0 // Variable zum hochdimmen initialisieren
rule "Wakeup Dimmer" // Rule zum Anlegen des Timers um 6 Uhr
when
Time cron "0 0 6 * * ?" // täglich um 6:00:00 Uhr
then
if(wakeupEnable.state == ON) { // falls der Schalter um 6 Uhr morgens auf ON steht
nDim = 0 // Variable zum hochdimmen auf 0 setzen
tWakeup?.cancel // Timer löschen, falls vorhanden
tWakeup = createTimer(now.plusMillis(10),[ | // Timer anlegen und nach 10 Millisekunden ausführen
DimmableLight8Brightness.sendCommand(nDim) // Licht auf Helligkeitswert dimmen
if(nDim < 100) { // Falls Helligkeit unter 100
nDim += 5 // erhöhe Helligkeit um 5
tWakeup.reschedule(now.plusSeconds(20)) // und führe den Timer in 20 Sekunden erneut aus
}
])
}
end
Die Schreibweise nDim += 5 ist gleichzusetzen mit nDim = nDim + 5. Allerdings geht das nur mit Integer Werten. Wichtig ist auch, dass die Variablen global definiert sind, sonst sind sie nur zur Laufzeit der Rule gültig, un die läuft nur wenige Millisekunden.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet