Seite 1 von 1

Rule Bewegungsmelder - Timer Problem

Verfasst: 1. Jul 2020 10:27
von Christoph
Hallo liebe Community,

ich versuche mich nun schon seit geraumer Zeit an meiner Rule für meinen Bewegungsmelder, leider bekomme ich diese aber nicht sauber zum Laufen.

Hardware:
- Rasp 4 - OpenHAB 2.5.5
- Hue Motion Sensor (nicht über die App konfiguriert)
- 2 Philips Hue Leuchten

Rule:

Code: Alles auswählen


rule "bath_motionsensor_on"

when
    Item hue_bath_motionsensor received update ON
then
    if((now.getHourOfDay > 4 && now.getHourOfDay < 22) && hue_floor_motionsensor_illuminance.state <= 10 | "lx" && timer_bath_motion === null || timer_bath_motion.hasTerminated) {  // zwischen 05:00 und 22:00 Uhr
        logInfo("BATH", "(DAY) IF okay")
        hue_bath_lamp_color.sendCommand(1)
        hue_bath_lamp_brightness.sendCommand(100)
        if(hue_bath_motionsensor.state == ON) {
            logInfo("BATH", "create 1st Timer")
            timer_bath_motion = createTimer(now.plusMinutes(2)) [|
            if (hue_bath_motionsensor.state == ON) {
                timer_bath_motion.reschedule(now.plusMinutes(2))
                logInfo("BATH", "reschedule 1st Timer")
            }
            ]
        }   
    }
    if((now.getHourOfDay > 21 && now.getHourOfDay < 5) && hue_floor_motionsensor_illuminance.state <= 10 | "lx" && timer_bath_motion === null || timer_bath_motion.hasTerminated) {  // // zwischen 22:00 und 5:00 Uhr
        logInfo("BATH", "(NIGHT) IF okay")
        hue_bath_lamp_color.sendCommand(100)
        hue_bath_lamp_brightness.sendCommand(25)
        if(hue_bath_motionsensor.state == ON) {
            logInfo("BATH", "create 1st Timer")
            timer_bath_motion = createTimer(now.plusMinutes(2)) [|
            if (hue_bath_motionsensor.state == ON) {
                timer_bath_motion.reschedule(now.plusMinutes(2))
                logInfo("BATH", "reschedule 1st Timer")
            }
            ]
        }   
    }
    else if (timer_bath_motion !== null) {
        if(now.getHourOfDay > 4 && now.getHourOfDay < 22) {
            hue_bath_lamp_brightness.sendCommand(100)
            timer_bath_motion.reschedule(now.plusMinutes(2))
            logInfo("BATH", "(DAY) Timer on/off rescheduled")
        }
        if(now.getHourOfDay > 21 && now.getHourOfDay < 5){
            hue_bath_lamp_brightness.sendCommand(25)
            timer_bath_motion.reschedule(now.plusMinutes(2))  
            logInfo("BATH", "(NIGHT) Timer on/off rescheduled")
        }
        
    }
end

rule "bath_motionsensor_off"

when
    Item hue_bath_motionsensor changed from ON to OFF
then
    if (hue_bath_lamp_brightness.state == OFF){
        return;}
        logInfo("BATH", "no motion - set Timer")
        hue_bath_lamp_brightness.sendCommand(25)
        timer_bath_motion = createTimer(now.plusMinutes(2), [ |
            timer_bath_motion.cancel
            timer_bath_motion = null
            hue_bath_lamp_brightness.sendCommand(OFF)
            logInfo("BATH", "all off")
        ])
end


Soll:

Der Bewegungsmelder sollte bei Bewegung vom Status OFF auf ON wechseln, die Rule entsprechend der definierten Kriterien (Helligkeit, Zeit) triggern und anschließend das Licht einschalten.
Wird eine kontinuierliche Bewegung (dauernd Status ON) oder eine unterbrochene Bewegung (ON -> OFF -> ON) innerhalb der definierten Zeit erkannt, soll das Licht bis zum Status OFF eingeschaltet bleiben, dann die Lichter für eine gewisse Zeit auf X% dimmen und erst anschließend soll das Licht ausgeschaltet werden.

Ist:

Das Licht geht immer wieder aus, obwohl ich mich noch im Raum befinde. Manchmal gibt es lt. Log eine Timer.cancel-Fehlermeldung, manchmal läuft der Timer trotz Bewegung ab und schaltet das Licht aus und manchmal funktioniert alles (denke eher durch Zufall) wie es soll.
Zudem sollte der Bewegungsmelder nur unter einem definierten Helligkeitswert (lx) ein Event auslösen. Das führt jedoch manchmal zum Problem, dass bei einem zeitnahen ON/OFF-Event die Helligkeit noch nicht aktualisiert wurde und so die Rule nicht mehr getriggert wird.

Fragen:

Was kann ich an meiner Rule noch optimieren bzw. wo habe ich noch einen Fehler drin?
Schön wäre es natürlich auch, wenn man die zweite Rule "bath_motionsensor_off" auch noch in die erste Rule packen könnte.

Primäres Ziel ist aber, dass das Licht ohne Unterbrechungen eingeschaltet bleibt, bis man den Raum verlässt.

Vielen lieben Dank im Voraus!

LG Christoph

Re: Rule Bewegungsmelder - Timer Problem

Verfasst: 1. Jul 2020 15:12
von udo1toni
Was habt Ihr alle immer mit timer.hasTerminated?
hasTerminated bedeutet, dass der Timer abgelaufen ist und der Code ausgeführt wurde. Einfacher ist es, im Timer die Referenz auf null zu setzen (spart eine Bedinung)
Die Nacht-Bedingung lautet, dass die Stunde gleichzeitig größer als 21 und kleiner als 5 ist. -> nie
Dein Timer in der ersten Rule macht exakt nichts. Na ja, er müllt Dein Log zu...
Wie verhält sich Dein Bewegungsmelder nun tatsächlich?
Sendet er bei jeder Bewegung ein ON? Sendet er nach einer gewissen Zeit ohne Bewegung zuverlässig ein OFF?
Wenn der Timer-Code bereits ausgeführt wird, kann man ihn nicht mehr mittels .cancel anhalten (und das wäre ja auch Quatsch, dann würden die nachfolgenden Befehle nicht mehr ausgeführt...)

Ich denke, Du willst eher sowas:

Code: Alles auswählen

// globale Variablen gehören an den Anfang der Datei!
var Number nBright = 100
var Number nColor = 1
var Boolean bTimer = false

rule "bath motionsensor"
when
    Item hue_bath_motionsensor received update ON
then
    bTimer = false                                                                                           // Default Tag
    nBright = 100
    nColor = 1
    var String strMessage = "DAY"
    if(now.getHourOfDay > 21 || now.getHourOfDay < 5) {                                                      // Falls nach 22 Uhr oder vor 5 Uhr
        nBright = 25                                                                                         // Nacht-Werte
        nColor = 100
        strMessage = "NIGHT"
    }
    if(hue_floor_motionsensor_illuminance.state instanceof Number)
        if((hue_floor_motionsensor_illuminance.state as Number).intValue > 10 && timer_bath_motion === null) // zu hell und kein laufender Timer
            return;                                                                                          // also Abbruch
    logInfo("BATH", "({}) IF okay",strMessage)
    timer_bath_motion?.cancel                                                                                // stoppe eventuell laufenden Timer
    hue_bath_lamp_color.sendCommand(nColor)                                                                  // setze Farbe
    hue_bath_lamp_brightness.sendCommand(nBright)                                                            // und Helligkeit
    timer_bath_motion = createTimer(now.plusMinutes(2), [|                                                   // erzeuge Timer
        if(!bTimer) {                                                                                        // falls 1. Durchlauf
            nBright = 25                                                                                     // ändere Helligkeit
            bTimer = true                                                                                    // markiere 2. Durchlauf
            logInfo("BATH","dim light")
            timer_bath_motion.reschedule(now.plusMinutes(2))                                                 // Plane erneute Ausführung
        } else {                                                                                             // falls nicht 1. Durchlauf
            nBright = 0                                                                                      // Setze Helligkeit auf 0
            timer_bath_motion = null                                                                         // lösche Timer
            logInfo("BATH","switch OFF light")
        }
        hue_bath_lamp_brightness.sendCommand(nBright)                                                        // Setze Helligkeit
    ]
end
Solange es Updates mit ON gibt, wird der Timer immer wieder neu angelegt. Läuft der Timer ab, so kam kein Update ON und die Helligkeit wird reduziert. Anschließend wird der Timer erneut ausgeführt und beim 2. Durchlauf das Licht abgeschaltet.
Sollte der Bewegungsmelder zuverlässig ein OFF senden, wenn keine Bewegung erkannt wird, sähe die Rule etwas anders aus:

Code: Alles auswählen

// globale Variablen gehören an den Anfang der Datei!
var Number nBright = 100
var Number nColor = 1
var Boolean bTimer = false

rule "bath motionsensor"
when
    Item hue_bath_motionsensor changed
then
    timer_bath_motion?.cancel                                                      // stoppe eventuell laufenden Timer
    if(hue_bath_motionsensor.state == OFF) {                                       // falls Ende der Bewegung
        bTimer = false
        timer_bath_motion = createTimer(now.plusMinutes(2), [|                     // erzeuge Timer
            if(!bTimer) {                                                          // falls 1. Durchlauf
                nBright = 25                                                       // ändere Helligkeit
                bTimer = true                                                      // markiere 2. Durchlauf
                timer_bath_motion.reschedule(now.plusMinutes(2))                   // Plane erneute Ausführung
            } else {                                                               // falls nicht 1. Durchlauf
                nBright = 0                                                        // Setze Helligkeit auf 0
                timer_bath_motion = null                                           // lösche Timer
            }
            hue_bath_lamp_brightness.sendCommand(nBright)                          // Ssetze Helligkeit
        ]
    } else {
        if(hue_floor_motionsensor_illuminance.state instanceof Number)
            if((hue_floor_motionsensor_illuminance.state as Number).intValue > 10) // zu hell und kein laufender Timer
                return;                                                            // also Abbruch
        nBright = 100                                                              // Default Tag
        nColor = 1
        var String strMessage = "DAY"
        if(now.getHourOfDay > 21 || now.getHourOfDay < 5) {                        // Falls nach 22 Uhr oder vor 5 Uhr
            nBright = 25                                                           // Nacht-Werte
            nColor = 100
            strMessage = "NIGHT"
        }
        logInfo("BATH", "({}) IF okay",strMessage)
        hue_bath_lamp_color.sendCommand(nColor)                                    // setze Farbe
        hue_bath_lamp_brightness.sendCommand(nBright)                              // und Helligkeit
    }
end
Die Rule triggert nur bei Änderung. Ein laufender Timer wird auf jeden Fall abgebrochen. Empfängt die Rule ein OFF, so wird der 1. Timer gestartet und der Rest läuft so wie in der 1. Rule. Empfängt sie ein ON, wird nur die Helligkeit entsprechend der Vorgaben korrigiert.