Seite 1 von 1

Lampe zeitverzögert schalten

Verfasst: 16. Mär 2019 11:27
von schnitzer
Hallo, ich will eine Lampe zeitverzögert schalten. Wenn ich in der Sitemap den Schalter betätige, soll Openhab ein paar Sekunden warten und dann erst die Lampe schalten. Der Schalter ist dabei ein Sonoff Pow, der über mqtt eingebunden ist.
Meine Sitemap sieht folgendermaßen aus:

Code: Alles auswählen

Switch item=Sonoff_P1_Schalter  mappings=["ON"="EIN", "OFF"="AUS"]
Mein Item dazu :

Code: Alles auswählen

Switch Sonoff_P1_Schalter "Testlampe" <light> (gLampen_Wohnzimmer) ["Switchable"] { channel="mqtt:topic:mosquitto:Sonoff_P1:Sonoff_P1_Power" }
Das manuelle schalten funktioniert einwandfrei. Jetzt kommt aber das Problem: I
Ich schaffe es ganz einfach nicht, dass ich mit der Regel folgenden Ablauf erreicht:
1. Gibt den Befehl schalte ein.
2. Warte 3 Sekunden.
3. Schalte tatsächlich die Lampe ein

Könnt ihr mir sagen, wie die Regel aussehen muss, um mein Ziel zu erreichen ?

Zudem habe ich gelernt, dass es 3 Möglichkeiten einer Zeitverzögerung gibt:
a) über Thread::sleep(xxx)
b) über createTimer(now.plusSeconds(5)
c) über die Definition einer Variablen z.B var Timer
Auch davon habe ich keine Ahnung, wann ich was einsetzen soll und was der Unterschied ist.

Ich hoffe, ihr könnt mir einen Tip geben, wie ich meine Zeitverzögerung realisieren soll.
Mit freundlichen Grüßen
Konrad

Re: Lampe zeitverzögert schalten

Verfasst: 16. Mär 2019 12:14
von Heavy-Dee
Du brauchst ein Dummy Item mit dem du eine Rule ansprichst und auf der Sitemap schaltest.
In der Rule ist dein reales Item.

Item:

Code: Alles auswählen

Switch Dummy "Name des Schalters"
sitemap:

Code: Alles auswählen

Switch item=Dummy
rule:

Code: Alles auswählen

rule "Verzögerung"
when
    Item Dummy received command                            // Zustand geändert
then
    if(receivedCommand == ON)                              // Kommando AN
    {
                Thread::sleep(3000)                        // Eingestellte Zeitdauer in ms
                Sonoff_P1_Schalter.sendCommand(ON)              // Licht an                
    } 
    else Sonoff_P1_Schalter.sendCommand(OFF)                    // Licht aus
end

Re: Lampe zeitverzögert schalten

Verfasst: 17. Mär 2019 07:40
von schnitzer
Dankeschön. Hat super funktioniert. Auf die Idee einen Dummy dazwischen zu schalten wäre ich nie gekommen.

Re: Lampe zeitverzögert schalten

Verfasst: 17. Mär 2019 18:35
von udo1toni
Bitte setze Thread::sleep() nicht mit Zeiten über 500 Millisekunden ein.

Die korrekte Lösung des Problems ist ein Timer (zusammen mit dem Dummy Item natürlich, immer vorausgesetzt, Du brauchst tatächlich einen Schalter, der erst verzögert zum Schalten führt).

Code: Alles auswählen

// globale Variablen und Konstanten werden immer am Beginn der Datei definiert!
var Timer tDelay = null                               // Zeiger auf den Timer

rule "Verzögerung"
when
    Item Dummy received command                       // Befehl empfangen
then
    tDelay?.cancel                                    // lösche Timer, falls einer existiert
    if(receivedCommand == ON)                         // Kommando AN
        tDelay = createTimer(now.plusSeconds(3), [ |
            Sonoff_P1_Schalter.sendCommand(ON)        // Licht an                
        ])
    else
        Sonoff_P1_Schalter.sendCommand(OFF)           // Licht aus
end
Der wesentliche Unterschied zu Thread::sleep() ist, dass die Rule bei ON den Timer anlegt und zuende ist, das dauert etwa 5 Millisekunden.
Wenn der Timer abläuft, startet der Scheduler den Code (eine Zeile), was wiederum innerhalb 5 Millisekunden erledigt ist.
Thread::sleep(3000) hält die Abarbeitung des Threads für 3000 Millisekunden an, die Ausführung des Codes dauert also die 3000 + noch einige Millisekunden obendrauf, in dieser Zeit steht dem System ein Thread weniger zur Abarbeitung von Rules zur Verfügung.
Default gibt es 5 Threads für Rules plus 2 Threads für Timer. Damit ist aber der aktive Timercode gemeint.
Ich kann dutzende oder gar hunderte Timer planen, die das System dann zuverlässig zur geplanten Zeit ausführt.
Solange die Threads nicht exakt zeitgleich ausgeführt werden müssen, gibt es keine Probleme.

Ein weitere Punkt ist, dass der Code mit Thread::sleep() keine Sorge für den Fall trägt, dass die Rule mehrfach getriggert wird.
Was passiert, wenn ich den Schalter ein- und sofort wieder ausschalte?
Die Rule wird zweimal parallel gestartet, das erste Mal wird der Thread::sleep() gestartet, das zweite Mal wird einfach ein OFF-Befehl gesendet.
Nach drei Sekunden ist dann Thread::sleep() fertig und der ON-Befehl wird gesendet.
Der Dummy Schalter steht aber auf OFF.

Wer jetzt wieder kurz auf ON schaltet, um wieder auf OFF schalten zu können, stellt fest, dass er in einer Zwickmühle ist.
Erst das geduldige Warten auf den ON-Befehl hilft dann.
Mehrfaches Hin- und Herschalten kann sogar dazu führen, dass sämtliche Threads (5) belegt sind.

Die Timer-Variante hingegen löscht einen laufenden Timer und erstellt ihn bei Bedarf erneut, die Ausführung des Codes läuft so schnell, dass die Rule nur unter extremen Bedingungen zweimal gestartet sein kann, was aber keine Auswirkungen hat (der Timer wird ja gelöscht).

Re: Lampe zeitverzögert schalten

Verfasst: 19. Mär 2019 12:04
von schnitzer
Hallo Udo, sehr gut erklärt.. danke. Mir ist genau das passiert, was du beschrieben hast. Wenn ich zum Testen schnell hintereinander schalte, kennt sich das System nicht mehr aus. Habe jetzt umgebaut auf createTimer(now....... Jetzt funktioniert es sicher

Re: Lampe zeitverzögert schalten

Verfasst: 19. Mär 2019 17:34
von udo1toni
:)