Motion detected, light on, turn off after 3 minutes but only between 8pm-5am

Hi everybody!

Its pretty simple what I’m trying to do (i think!), but I’ve done heaps of reading and research but I just cant figure it out…I’ve tried and read about expire binding, other posts, rules but to no success.

As in the heading. When my motion sensor detects movement turn the light on and then turn if off after 3 minutes but only in the evenings 8pm-5am.

default.items

Switch		Salt_Lamp		"Salt Lamp"		<fire>			(UpstairsLanding, gLight)		["Switch", "Switchable"]	{channel="tplinksmarthome:hs100:309A42:switch"}
Switch		Stairway_Motion		"Stairway Motion"			<lightbulb>			(Hallway, gLight)	{channel="mqtt:topic:openhabBroker:stairway_motion:occupancy"}

I have written the simple rule below, but it only satisfies only half what I’m trying to do…

rule "Stairway ON"
when
    Item Stairway_Motion changed from OFF to ON
then
    Salt_Lamp.sendCommand(ON) 
end

Please help, I just can figure this out and I’ve been stuck on it for sometime now, I’m hoping someone can help me figure this out. Happy to use the astro binding in the rule too, happy to use anything, just want it to work! Thanks for reading my post!

aworldofchaos

You can add time comparison like
if time i greater than and less than,
then start a timer for 3 minutes.
when timer finishes, check motion state again and if on, reschedule the timer.

I would do the complete rule in blockly, might be easier than writing in rules DSL.

Hi Hans, thanks for responding.

What would the code look like? I’m having trouble figuring out the code for this one.

What Motion Sensor are you using? In my case, using a Fibaro Motion Sensor, I can configure how long a motion alarm stays set to ON until it switches back to OFF. So for me, after the configured 30s, the alarm changes automatically from ON to OFF if no further movement is detected and a simple small rule can switch the light off.
In a rule you can get the current hour with

var int h = now.getHour

so you can use that easily in for a decision if switching takes place or not

Like @JensD I have Fibaro motion set to stay on 180 seconds. For various reasons I have separate rules for On and Off. Besides the hour, this will not turn on the light if it is sunny

rule "Turn Nook Lights On"
when Item NookMotion37_MotionAlarm changed to ON
then
    var Number hourofday = now.getHour()
    var light = Nook_luminence_hour_average.state as Number
    if( light <= 850 && hourofday < 23 && hourofday > 5) {
        NookLights6_Dimmer.sendCommand (100)
    }
end

The Open Reminder [3.3.0;3.4.9) rule template will do almost alll of this for you. You just need to write a rule to send the command OFF to the lamp. Everything else is handled by the rule created and configured from the rule template including the “do not disturb” period. The rule created and configured from the template will call the rule you write to do the job (in this case turn off the light),

This could be handled with the rule template above with a condition on the called rule.

As you are seeing though, this isn’t as simple as you might think.

The jruby rule engine is very nice:

rule "Light on for 3 minutes on motion detected" do
  changed Stairway_Motion, to: ON
  between "20:00".."05:00"
  run { Salt_Lamp.on }
  delay 3.minutes
  run { Salt_Lamp.off }
end
1 Like

Hi JensD I’m using a Xiaomi MiJia human body movement sensor, I dont know if its possible to set the time on this one - but it does set the motion sensor to OFF after a couple of minutes.

Hi Peter,

I tried using you rule there but I received errors…

Configuration model ‘stairway-light.rules’ has errors, therefore ignoring it: [1,50]: mismatched input ‘do’ expecting ‘when’

When I changed ‘do’ to ‘when’ I received…

Configuration model ‘stairway-light.rules’ has errors, therefore ignoring it: [3,3]: no viable alternative at input ‘changed’ ?

Hi apella12,

I’ve modified your rule and hopefully it will work. I took out the luminescence variable.

rule "Stairway Light Motion ON"
when Item Stairway_Motion changed to ON
then
    var Number hourofday = now.getHour()
    if( hourofday < 23 && hourofday > 5) {
        Salt_Lamp.sendCommand (ON)
    }
end

Hopefully I have modified it correctly?

If I put this at the end of the rule…

rule "Stairway OFF"
when
    Item Stairway_Motion changed from ON to OFF
then
    Salt_Lamp.sendCommand(OFF)
end

It turns itself off after a couple of minutes when the motion resets. This works, but its probably a ugly way of doing it…

I have just been thinking rather than a time (between the hours of X and X turn on, how to do it only after sunset? This will mean I dont have to change it a couple of times every year…

Thanks for everyones input so far, I really appreciate it! :slight_smile: :slight_smile:

I thought you wanted from 20 (8pm) to 5 am to go on. Mine is set to not go on (Wife gets up for midnight snack and doesn’t want lights to go on and make it harder to go back to sleep)

Don’t you want?
if( hourofday > 19 && hourofday < 5) {

Also you can combine both rules with

Item Stairway_Motion changed

& add

val status = Stairway_Motion.state.toString

& modify if

if( hourofday > 19 && hourofday < 5 && status == 'ON') {

and add else

else
      `Salt_Lamp.sendCommand(OFF)`

Lastly I have a day night switch in DSL using astro that might come in handy (Created DayorNight item)

rule "Day"
when
    Channel "astro:sun:home:rise#event" triggered START
then
    DayorNight.postUpdate("Day")
end

rule "Night"
when
    Channel "astro:sun:home:set#event" triggered START
then
    DayorNight.postUpdate("Night")
end

Configuration model ‘stairway-light.rules’ has errors

  1. you need to install the jruby automation addon to get support for jruby rules
  2. it’s a ruby file so it should be named stairway-light.rb
  3. the file doesn’t go into the normal rule directory but instead where you configure jruby to look, which by default is $OPENHAB_CONF/automation/jsr223/ruby/personal
  4. the file needs to have require "openhab" at the top before the rule
require "openhab"

rule "Light on for 3 minutes on motion detected" do
  changed Stairway_Motion, to: ON
  between "20:00".."05:00"
  run { Salt_Lamp.on }
  delay 3.minutes
  run { Salt_Lamp.off }
end

IMHO, the jruby rules are by far the nicest to write.

Why not:

Script:
image

All my timers work in something close to this.

1 Like

I’m genuinely curious - do people really find these graphical tools for rules/scripts easier than just writing the rules directly (in the rule DSL or possibly in one of the real languages)?

Yes. I’m an idiot and make mistakes when writing code which can be hard to track down. No syntax errors when using Blockly!

Also, I can adjust rules easily using the UI, for example on my phone - I don’t need access to the rules files.

Cool, that’s definitely one of the good things about openhab - everybody gets to pick their poison.

1 Like

Just to throw my hat in the ring.

You can also use a night-state-virtual-switch rule

rule "Night state"
when
    System started
then
    createTimer(now.plusSeconds(180)) [ |
        if (now.isAfter((SunsetTime.state as DateTimeType).calendar.timeInMillis) ||
            now.isBefore((SunriseTime.state as DateTimeType).calendar.timeInMillis)
        ) {
            postUpdate(NightState, ON)
        } else {
            postUpdate(NightState, OFF)
        }
    ]
end

Your system triggers a virtual switch using the Astro binding, depending if your night state is on or off do this.

var Timer UtilityLightsTimer = null

rule "Turn on Utility lights when motion triggered"
when
Item Utility_PIR_Occupancy changed
then
if (NightState.state == OFF) {
} else if(Utility_PIR_Occupancy.state == OPEN) {
if(Utility_LightChannel.state != ON) Utility_LightChannel.sendCommand(OnOffType.ON)
logInfo("UtilityLights.rules", "PIR Actuated Utility Lights ON Sent and Timer Started")
if (UtilityLightsTimer !== null) UtilityLightsTimer .cancel
UtilityLightsTimer = createTimer(now.plusMinutes(15), [ |
Utility_LightChannel.sendCommand(OnOffType.OFF)
logInfo("UtilityLights.rules", "Timer expired UtilityLights OFF Sent")
UtilityLightsTimer = null
] )
}
end

Absolutely. In addition to what @hafniumzinc mentions:

  • in the UI there is often less need to go to the reference docs to figure out how to do something. It’s all documented right there in front of you.

  • those who do not have a background in coding find a graphical interface like Blockly easier to understand (that’s why it’s often used to teach coding to children with systems like Scratch).

  • UI rules are only the only way to use/create rule templates (see my post above about Open Door, this whole thread could be solved without any coding required through the use of that rule template). Why code it yourself if you can instead install and configure?

  • this may be a controversial statement, but I find a managed configuration (i.e. UI configs) behave much more consistently and with fewer strange quirks than text based configs. It’s not controversial to say that changes made to a managed config are much less disruptive, impacting only that entity modified instead of everything in that file and more (e.g. editing a .items file can cause .rules files to be reloaded).

This part is a little over worked.

now.isAfter((SunsetTime.state as DateTimeType).getZonedDateTime())

It’s better to stay working in ZonedDateTimes than to fall to such a low level as epoch.

Also, as written this will only work for the first day. You’d need to trigger this at midnight too to change NightState for the days after the first day.

Though I’d use restoreOnStartup and the Astro event channels which would produce a much simpler set of rules that don’t need timers at all.

rule "Night Start"
when
    Channel 'astro:sun:home:set#event' triggered START
then
    NightState.postUpdate(ON)
end

rule "Night Stop"
when
    Channel 'astro:sun:home:rise#event' triggered START
then
    NightState.postUpdate(OFF)
end

In the UI you wouldn’t even need to write code for something like this (tying this back into the discussion above).

Or, even simpler, one can use the Astro Actions and see what the sun azimuth or elevation is and not need the rule at all.

1 Like

I haven’t moved over to UI rules, purely because my DSL rules work and I’ve made very few modifications over the past couple of years. If it ain’t broke, don’t fix it.

In addition to what @hafniumzinc and @rlkoshak already wrote, I’m intrigued by the ability for UI rules to enable/disable/run other UI rules.

I personally find Blockly a little hard to read, but that may be partially due to my red-green colourblindness. I’ve used Scratch before with children and agree that it’s excellent for teaching them the basics of programming.

3 Likes

That’s not unique to UI rules. It’s just not possible from Rules DSL.