[SOLVED] Switching light by daytime and presence

Hi everybody,

I am facing an issue which seems to be simple to the more advanced.
My trigger is a motion sensor. It provides the state ON/OFF by motion. Then, by vTimeOfDay the light should be switched to a defined state. If no motion is detected for e.g. 3 min the light should be swittched of.
What is happening? Motion is detected, but the timer runs and switches OFF the light after 3 min.
Please help me!!!:
Thank you!

My rule:

import org.openhab.model.script.actions.Timer
var Timer = null

rule "Badlicht mit Bewegungsmelder"

when 
Item HueBadBewegungsmelderPresence received update

then
    if((HueBadBewegungsmelderPresence.state == ON) && (vTimeOfDay.state == "MORNING" || vTimeOfDay.state == "DAY" || vTimeOfDay.state == "AFTERNOON")){
        Hue_Badschrank_Switch.sendCommand(ON)
        gTradfriBadDimmer1.sendCommand(80)

    }
else
    if((HueBadBewegungsmelderPresence.state == ON) && (vTimeOfDay.state == "EVENING" || vTimeOfDay.state == "NIGHT")){
        Hue_Badschrank_Switch.sendCommand(ON)
        gTradfriBadDimmer1.sendCommand(50)

    }
else
    if((HueBadBewegungsmelderPresence.state == ON) && (vTimeOfDay.state == "BED")){
        Tradfri_Bad2_Brightness.sendCommand(15)
        
    }

else
    if(HueBadBewegungsmelderPresence.state == OFF)
        Timer = createTimer(now.plusMinutes(3)) [|
            sendCommand(gTradfriBadDimmer1, OFF)
            sendCommand(Hue_Badschrank_Switch, OFF)
            Timer = null
            ]
end

What are is the Item & rules setting vTimeOfDay?

It is from the Design Pattern: Time Of Day by @rlkoshak.

Beside that: The state request for the time of day works. So the preset light is used.

1 Like

The logic breaks in 2: your rule processes either HueBadBewegungsmelderPresence.state is ON or OFF. But the logic is incomplete and the rule will indeed turn off gTradfriBadDimmer1 and Hue_Badschrank_Switch whenever the motion sensor goes from “presence/motion detected” to “no presence/motion detected”).

What is missing in your code, is:

  1. a way to cancel the timer_BadzimmerLichte timer when (a) HueBadBewegungsmelderPresence.state is ON and (b) it has been previously scheduled (Timer is not null) due to a “no motion detected” signal (HueBadBewegungsmelderPresence.state was OFF previously).
  2. a way to switch off Tradfri_Bad2_Brightness when vTimeOfDay.state is no longer set to "BED".

You may want to reassess the actual use case you intend to implement with your rule with a state table.

I rewrote your rule replacing the complex if () statements with a more elegant switch () { case } approach, and moved the "BED" case from your rule in another rule as it’s most likely unrelated to the motion sensor logic:

import org.openhab.model.script.actions.Timer

// This timer will take care of turning off the bathroom lights:
var Timer timer_BadzimmerLichte = null

rule "Badlicht mit Bewegungsmelder"

when 
    Item HueBadBewegungsmelderPresence changed

then
    switch (HueBadBewegungsmelderPresence.state) {
        case ON:
            {
                // Cancel timer_BadzimmerLichte if it was running, or we will end up in the dark
                timer_BadzimmerLichte?.cancel()
                // Process time of day
                switch (vTimeOfDay.state) {
                    case "MORNING",
                    case "DAY",
                    case "AFTERNOON":
                        {
                            Hue_Badschrank_Switch.sendCommand(ON)
                            gTradfriBadDimmer1.sendCommand(80)
                        }
                    case "EVENING",
                    case "NIGHT":
                        {
                            Hue_Badschrank_Switch.sendCommand(ON)
                            gTradfriBadDimmer1.sendCommand(50)
                        }
                }
            }
        case OFF:
            {
                timer_BadzimmerLichte = createTimer(now.plusMinutes(3), [ |
                    sendCommand(Hue_Badschrank_Switch, OFF)
                    sendCommand(gTradfriBadDimmer1, OFF)
                    timer_BadzimmerLichte = null
                ])
            }
    }
end



rule "Nachtlicht im Badzimmer"

when 
    Item vTimeOfDay changed

then
    // Process time of day
    switch (vTimeOfDay.state) {
        case "BED":
            {
                Tradfri_Bad2_Brightness.sendCommand(15)
            }
        default:
            {
                // Turn off:
                Tradfri_Bad2_Brightness.sendCommand(0)
            }
    }
end

Thank you for the enormous help! I did expect something, but not such a big solution. Very nice!

You are right, I missed the way to cancel the timer. The idea to put the “BED” time of day into a seperate rule is okay. But I would prefer to trigger it by the motion sensor as well. So I just created ontoher case for “BED”.

Here my final rule:

import org.openhab.model.script.actions.Timer

// This timer will take care of turning off the bathroom lights:
var Timer timer_BadzimmerLichte = null

rule "Badlicht mit Bewegungsmelder"

when 
    Item HueBadBewegungsmelderPresence changed

then
    switch (HueBadBewegungsmelderPresence.state) {
        case ON:
            {
                // Cancel timer_BadzimmerLichte if it was running, or we will end up in the dark
                timer_BadzimmerLichte?.cancel()
                // Process time of day
                switch (vTimeOfDay.state) {
                    case "MORNING",
                    case "DAY",
                    case "AFTERNOON":
                        {
                            Hue_Badschrank_Switch.sendCommand(ON)
                            gTradfriBadDimmer1.sendCommand(80)
                        }
                    case "EVENING",
                    case "NIGHT":
                        {
                            Hue_Badschrank_Switch.sendCommand(ON)
                            gTradfriBadDimmer1.sendCommand(50)
                        }
                    case "BED":
                        {
                            Tradfri_Bad2_Brightness.sendCommand(15)
                        }
                }
            }
        case OFF:
            {
                timer_BadzimmerLichte = createTimer(now.plusSeconds(30), [ |
                    sendCommand(Hue_Badschrank_Switch, OFF)
                    sendCommand(gTradfriBadDimmer1, OFF)
                    timer_BadzimmerLichte = null
                ])
            }
    }
end

You’re welcome.

In re-reading my code I see that I wrote a mistake in the timer call-back: I forgot to rename Timer to timer_BadzimmerLichte. I updated this in my earlier post.

The problem with the one single rule is that:

  1. you only switch on Tradfri_Bad2_Brightness when the motion sensor is activated and vTimeOfDay equals "BED".
  2. you don’t control when to switch off Tradfri_Bad2_Brightness.

The 2nd rule I wrote ("Nachtlicht im Badzimmer") takes care of this, I assumed the following (which may not be right):

  1. Tradfri_Bad2_Brightness is a night-mode auxiliary light that you set to a low value (15%) when vTimeOfDay is set to "BED" to avoid being blinded at night when entering the bathroom
  2. Tradfri_Bad2_Brightness is switched off when vTimeOfDay is not set to "BED".

In case all you want to do is to define the lights to manipulate depending on the time of day, then the timer call-back method should also manage Tradfri_Bad2_Brightness (through gTradfriBadDimmer2, I guess).

You also may want to watch out for situations where vTimeOfDay changes value while the timer is running. The call-back should probably switch off all lights. That’s fairly simple, add sendCommand(gTradfriBadDimmer2, OFF) before timer_BadzimmerLichte = null.

‘Tradfri_Bad2_Brightness’ is a member of gTradfriBadDimmer1. So it should be switched of when the timer finishes, does it not? So three bulb in the bathroom which could be triggered seperately and in group.
Additionally there is a smart plug.

The Items are

Group gTradfriBadDimmer1

Dimmer Tradfri_Bad1_Brightness "...." (gTradfriBadDimmer1) {channel="---"}
Dimmer Tradfri_Bad2_Brightness "...." (gTradfriBadDimmer1) {channel="---"}
Dimmer Tradfri_Bad3_Brightness "...." (gTradfriBadDimmer1) {channel="---"}
Switch Hue_Badschrank_Switch   "..."  (...)                {channel="---"}

I will check how it will run.
Thank you!

Indeed, that should do the job!