Lichtwecker via Script für nächsten Morgen

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
wighdeas
Beiträge: 26
Registriert: 30. Dez 2019 18:01
Answers: 1

Lichtwecker via Script für nächsten Morgen

Beitrag von wighdeas »

Hallo zusammen,

würde gerne ein Script schreiben, das ich mittles einem Switch in Panel starten kann. Der "Clou" - ich will den Switch am Vortag betätigen und entsprechen am Folgetag soll das Licht schrittweise heller werden. Natürlich bin ich auch offen für eine Lösung bei der ich eine Uhrzeit eingeben und automatisch am Folgetag zu entsprechender Uhrzeit geweckt wird.

Mein aktueller Stand:

Code: Alles auswählen

var Number wakeUpDimmer
    DimmableLight8Brightness.sendCommand(0)
    when Time cron "0 0 06 * * ?"
    wakeUpDimmer=0
    while(wakeUpDimmer<100){
    	wakeUpDimmer=wakeUpDimmer+5
    	sendCommand(DimmableLight8Brightness,wakeUpDimmer)
    	Thread::sleep(20000)
    }
Wie kann ich das nun:

1. Mit einem Switch starten - ist vermutlich super einfach aber ich blicks nicht.
2. Das ganze mit einer bestimmen Uhrzeit starten`

Sidequest: die "Funktion" einer bestimmten Zeit am Folgetag lasse ich mir gerne zusätzlich erklären, da ich diese für weitere Scripts brauchen kann.

Ich freue mich wie immer über neue Erkenntnisse. Danke!
Openhabian/Openhab 2.4.0.
RasPi4 4B
HomeMaticIP (CCU3, Firmware 3.51.6)
Dezcon-Zigbee-Adapter

Benutzeravatar
udo1toni
Beiträge: 15248
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Lichtwecker via Script für nächsten Morgen

Beitrag von udo1toni »

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

Antworten