PLEG - Light Control with Door Sensor

Hello Everyone -

I’m having a small issue working through some logic and am hoping for help.

I have a bathroom with a door sensor (UpstairsBathDoorOpen) and two separate switches (UpstairsBathLightsOn and UpstairsBathVanityOn)

I’d like to turn off both lights if the door has been open for more than 2 minutes. The problem I’m having is if someone turned a light on without “flipping” the sensor. (In other words, turning on the light, keeping the door open, and then walking out - keeping the lights on).

I thought the below would work but this is keeping me from turning the lights on. As soon as the light is flipped on, it runs the condition and turns them back off again.

UpstairsBathDoorOpen AND ((UpstairsBathLightsOn AND (UpstairsBathDoorOpen;NOW>2:00)) OR (UpstairsBathVanityOn AND (UpstairsBathDoorOpen;NOW>2:00)))

Basically, I want the lights to turn off if they stay on for more than 2 minutes with the door open.

Thanks for any help that you can provide.

Try the following:
UpstairsBathDoorOpen AND ( (UpstairsBathLightsOn AND (UpstairsBathLightsOn;NOW>2:00)) OR (UpstairsBathVanityOn AND (UpstairsBathVanityOn;NOW>2:00)) )

You want the timer to start when the light is turned on … not when the door was open … It could have been opened last night … and it will still be > 2:00 since then!

Appreciate these forums as I’m learning heaps.

[quote=“RichardTSchaefer, post:2, topic:180469”]Try the following:
UpstairsBathDoorOpen AND ( (UpstairsBathLightsOn AND (UpstairsBathLightsOn;NOW>2:00)) OR (UpstairsBathVanityOn AND (UpstairsBathVanityOn;NOW>2:00)) )

You want the timer to start when the light is turned on … not when the door was open … It could have been opened last night … and it will still be > 2:00 since then![/quote]

Doh! Of course! I was close, at least! :slight_smile:

So taking it a step further…

I have another condition that will turn on the hallway lights and this bathroom’s lights in the middle of the night to lead the path to the restroom.

TurnOnNightPathLight
!PartyOverride AND (VacationOn == 0) AND NightLightSched AND UpstairsHallwayMotion

Because I’m using PLEG vs PLTS, I will also need to run conditions to turn these lights off after a certain amount of time (say: 5 minutes)

This means I’ll need to add a stanza to the above bathroom light logic but make sure it does not interfere with your suggestions. Would something like this work?

First, I will create a condition to check for either vanity or the recessed lights on (just to clean up the original condition):
UpstairsBathLightCheck
UpstairsBathLightsOn OR UpstairsBathVanityOn

TurnOffUpstairsBathLights
UpstairsBathDoorOpen AND (((UpstairsBathLightCheck AND (UpstairsBathLightCheck;NOW>2:00)) OR (UpstairsBathLightCheck AND (UpstairsBathLightCheck;NOW > 5:00) AND (TurnOnNightPathLight; UpstairsBathLightCheck <30))))

I still want to check for the UpstairsBathDoorOpen in case they’re taking longer than 5 minutes. However, I now want to “clean up” the “Path Lights” in case the bathroom-user didn’t turn them off… I suppose this could be argued as unnecessary as the original condition would kill the lights after two minutes anyway. The timing is irrelevant and I’m doing this exercise more for learning than anything.

I’m still wrestling with this a little (see attached).

The problem is the auto-off (TurnOffUpstairsBathLights) after the TurnOnNightPathLight fires is not working all of the time. I think this is because the TurnOnNightPathLight refires (becomes true again) after the 30 second test.

This is partially intended as I don’t want the night lights to go off unless motion has stopped. I feel like I need a sequence/timer on the TurnOnNightPathLight. I’m just not sure what…

I use a different strategy for lighting.
For each lighting area … I have a timer:
It’s a SelfRetrigger call it sLightTimer1. You can have a default off time … It will use this if Vera Restarts during the time interval.

The Off might be:
LightsOff BathDoorOpen and (sLightAreaTimer; !sLightAreaTimer)
I then have something like:
LightAreaAutoOnDay MotioninLightArea and !Night (Actions:Start Timer for 5 Minutes, Light Level at 81) Allow Repeat

[b]LightAreaAutoOnNight[/b]    MotionInLightArea and Night          (Actions:Start Timer for 3 Minutes Light Level at 11)  Allow Repeat

[b]LightManualOn[/b]               LightTarget > 0 and (LightLevelTarget % 10 != 1)   (Actions:Start Timer for 15 Minutes, Level Set manually) Allow Repeat
[b]LongLightOn[/b]                   LightManualOn @ 3 < 30                  (Actions:Start Timer for 30 Minutes, Level Set manually) Allow Repeat

If you have more than one light that can manually be turned on … or multiple expressions like what is in LightManualOn together.
This only works with instant status switches.

[quote=“RichardTSchaefer, post:7, topic:180469”]I use a different strategy for lighting.
For each lighting area … I have a timer:
It’s a SelfRetrigger call it sLightTimer1. You can have a default off time … It will use this if Vera Restarts during the time interval.

The Off might be:
LightsOff BathDoorOpen and (sLightAreaTimer; !sLightAreaTimer)
I then have something like:
LightAreaAutoOnDay MotioninLightArea and !Night (Actions:Start Timer for 5 Minutes, Light Level at 81) Allow Repeat

[b]LightAreaAutoOnNight[/b]    MotionInLightArea and Night          (Actions:Start Timer for 3 Minutes Light Level at 11)  Allow Repeat

[b]LightManualOn[/b]               LightTarget > 0 and (LightLevelTarget % 10 != 1)   (Actions:Start Timer for 15 Minutes, Level Set manually) Allow Repeat
[b]LongLightOn[/b]                   LightManualOn @ 3 < 30                  (Actions:Start Timer for 30 Minutes, Level Set manually) Allow Repeat

If you have more than one light that can manually be turned on … or multiple expressions like what is in LightManualOn together.
This only works with instant status switches.[/quote]

Hey Richard -

While this varies greatly from the direction I’m going, I am intrigued. Can you expand a bit? Do you possibly have your timers documented somewhere (e.g. not sure how to “self retrigger”? I thought about using timers but also liked the idea of PLEG as I already had a foundation to build on.

It feels like I am very close with my solution above. I just don’t have the competency just yet to complete it.

Your way is much cleaner, no doubt…

My timers are Input Schedules the Start Type is Self Retrigger, Off Time is an Interval.

To start a timer … in your action … use the advanced tab … add the specific PLEG/PLTS device … Select StartTimer … Specify the Timer Name and provide a time if you do not want to use the default interval time.

I believe Rex has documented their use in his PLEG document.

The reason I mentioned this … is that you have a lot of sequence expressions and that is the most complicated to fully understand the behavior … because you have to start to worry about the
interactions of timings … So I try to simplify.

[quote=“RichardTSchaefer, post:9, topic:180469”]My timers are Input Schedules the Start Type is Self Retrigger, Off Time is an Interval.

To start a timer … in your action … use the advanced tab … add the specific PLEG/PLTS device … Select StartTimer … Specify the Timer Name and provide a time if you do not want to use the default interval time.

I believe Rex has documented their use in his PLEG document.

The reason I mentioned this … is that you have a lot of sequence expressions and that is the most complicated to fully understand the behavior … because you have to start to worry about the
interactions of timings … So I try to simplify.[/quote]

Agreed. After I sent my above post, I started to read in to those timers in a little more depth - cool stuff. It will certainly put me back a few days but let me work on it and see what I can come up with. I appreciate your thoughts as always.

I’m going to write this down here so I can clearly think about (and state) my goals:

  1. I have a motion detector in upstairs hallway. I’d like that detector to turn on the following lights during a “night time” schedule.

[ul][li]Bathroom Can and Vanity Lights - 10%[/li]
[li]Upstairs Hallway Lights - 10%[/li][/ul]

  1. I’d like the “night time” lights to turn off automatically after (example - still haven’t decided) after 5 minutes of no more motion detection. This will include both the hallway and bathroom lights.

  2. I’d like the bathroom lights to always turn off after 15 minutes if the door is open - as a fall back (regardless of schedule - covers lights being left on during the day). However, if the bath lights were turned on by the “night time” function, turn off these lights after 5 minutes of no motion(see item 2).

  3. If the door is closed, keep the bathroom lights on regardless if the rest of the lights get turned off by the 5 minute (no motion) timer.

Now that I’ve put my mind through that therapy, I need to figure out how to implement these using the timers you’re speaking about above.

In the Bathroom I turn the vanity lights on even during the day … In fact I turn then on to a level of 91. I have windows with light … but I still like a bright light … it’s usually the last place I visit before leaving the house.

Note: I use a value of 11, 41, 91 for AUTO turn on levels … Then I can easily differentiate between manual and auto settings with:
Manual LightTarget > 0 and (LightLevelTarget % 10 != 1)

[quote=“RichardTSchaefer, post:12, topic:180469”]In the Bathroom I turn the vanity lights on even during the day … In fact I turn then on to a level of 91. I have windows with light … but I still like a bright light … it’s usually the last place I visit before leaving the house.

Note: I use a value of 11, 41, 91 for AUTO turn on levels … Then I can easily differentiate between manual and auto settings with:
Manual LightTarget > 0 and (LightLevelTarget % 10 != 1)[/quote]

Can you expand on that condition for me? The PLEG document I have doesn’t cover modulus (that I could see).

LightTarget: A device status/trigger? The device is “on” because it is greater than 0.
LightLevelTarget: Another device status? Try to divide by 10, if there’s not a remainder of 1, it must have been set at the switch? (that is, it was set manually - hence the condition name)

Close?

Nice idea!

[quote=“RichardTSchaefer, post:12, topic:180469”]In the Bathroom I turn the vanity lights on even during the day … In fact I turn then on to a level of 91. I have windows with light … but I still like a bright light … it’s usually the last place I visit before leaving the house.

Note: I use a value of 11, 41, 91 for AUTO turn on levels … Then I can easily differentiate between manual and auto settings with:
Manual LightTarget > 0 and (LightLevelTarget % 10 != 1)[/quote]

clever

The operator:
X % Y

Where X and Y are integer numbers results in the integer remainder of the arithmetic division of X/Y
So if X is 21 and Y is 10, the modulus operator returns 1

The remainder has the property that its value is always between 0 and Y - 1.

See Modulo - Wikipedia for full details.
[hr]
Note: I have to use the Advanced TAB in the actions editor to set the dimming levels to things like 11, 41, 91 …

Alrighty. This wasn’t as bad as I thought it would be.

Check out my PLEG attached (which could use some separation to a new one at this point).

I haven’t been able to test the motion piece of this because I’m still at the office but the manual control/timers work great. This was a great learning experience. Thanks for the suggestion.

p.s. Stupid question time…because I allow for repeats on TurnOnNightPathLight, the 5 minute timer will continue to get reset, correct? It won’t start “counting down” until the motion (or other variable) goes false?

It’s probably good to describe the behavior of doing a StartTimer when a timer is already running (i.e. with a motion and a repeat set to yes).

In MCV there is no way to cancel a timer. So if you do 5 Restarts while the timer is running … I bump a count every time the timer is started.
I reduce the count every time a timer finishes. Only when the last timer finishes (based on last one finishing the count) and the count goes to zero to I actually do the stop.

If you do a:
StartTimer 10:00
and a
StartTimer 10
a few seconds later … the timer will not end until the first timer at 10 minutes finishes.

If the StartTimers are all the same duration … they will each finish in order, so the behavior is as if they were canceled and restarted.

[quote=“RichardTSchaefer, post:17, topic:180469”]It’s probably good to describe the behavior of doing a StartTimer when a timer is already running (i.e. with a motion and a repeat set to yes).

In MCV there is no way to cancel a timer. So if you do 5 Restarts while the timer is running … I bump a count every time the timer is started.
I reduce the count every time a timer finishes. Only when the last timer finishes (based on last one finishing the count) and the count goes to zero to I actually do the stop.

If you do a:
StartTimer 10:00
and a
StartTimer 10
a few seconds later … the timer will not end until the first timer at 10 minutes finishes.

If the StartTimers are all the same duration … they will each finish in order, so the behavior is as if they were canceled and restarted.[/quote]

This blew right over the top of my head, Richard. I think I understand the essence of what you’re saying but I’m having trouble applying it to “MCV” logic.

Would you mind elaborating when you have time? Perhaps by using my PLEG? Maybe I’m not seeing some sort of functionality. I don’t see how you can bump (or deduct) to/from a timer’s value. Or even if I could, how that would help in my situation. Is there a way to detect a “repeat” when you’d set a new timer interval?

It doesn’t just simply reset back to the original value (e.g. 00:05:00) every time the condition is met (i.e. movement detected)?

Sorry. I really appreciate you sticking with me here. Applying the usage of timers (as learned today) will really make things simpler in the future. (vs. using sequences, and a series of PLTS’s, etc)

In MCV a timer is created when you call luup.call_delay(“SomeFunctionName”, DelayInSeconds, “SomeStringArgument”)

Once you call this function there is no way to stop it.
[hr]
PLEG uses the name of the PLEG timer as the “SomeStringArgument”.
In PLEG a timer is a Named Object, that knows about StartType, StopTypes, Intervals, …, and, a variable I call “StopCnt”.
Ultimately the PLEG Timer is implemented with the MCV luup.call_delay function.
The StopCnt is not related to the delay … it just indicates that I called luup.call_delay for that specific PLEG timer.
If you call StartTimer multiple times before the timer has actually expired … then StopCnt increases from 0 initially to 1, then 2, then … N where N indicates there are N outstanding timer requests for this particular timer.

When you call StartTimer, it looks up the PLEG Counter using the name, and then Increments StopCnt before calling luup.call_delay.

When the timer finishes, Vera calls the “SomeFunctionName”. For me that function looks up the PLEG Counter, Using the CounterName, then decrements the StopCnt.
Only when the StopCnt reaches zero … do I really execute the stop behavior. The termination of the other counters only decrement the StopCnt.

i.e. When Vera finishes the timer, it calls my function. My function decrements the “StopCnt” from N, to N -1, … ultimately to zero where N indicates there are N outstanding timer requests for this particular timer. Only when it gets to 0 do I consider that the Logical Timer has actually expired.
[hr]

I guess I need a NON programmer to describe this in a manner suitable for non developers.
When the delay is always the same … the appearance to the end user is as you indicated. I.e. it appears to just reset.
But when you have different intervals passed to StartTimer, while the timer is running … the illusion is shattered … that’s why I felt it was important to understand the behavior.
The example I used before might be considered an unanticipated behavior.

[quote=“RichardTSchaefer, post:19, topic:180469”]In MCV a timer is created when you call luup.call_delay(“SomeFunctionName”, DelayInSeconds, “SomeStringArgument”)

Once you call this function there is no way to stop it.
[hr]
PLEG uses the name of the PLEG timer as the “SomeStringArgument”.
In PLEG a timer is a Named Object, that knows about StartType, StopTypes, Intervals, …, and, a variable I call “StopCnt”.
Ultimately the PLEG Timer is implemented with the MCV luup.call_delay function.
The StopCnt is not related to the delay … it just indicates that I called luup.call_delay for that specific PLEG timer.
If you call StartTimer multiple times before the timer has actually expired … then StopCnt increases from 0 initially to 1, then 2, then … N where N indicates there are N outstanding timer requests for this particular timer.

When you call StartTimer, it looks up the PLEG Counter using the name, and then Increments StopCnt before calling luup.call_delay.

When the timer finishes, Vera calls the “SomeFunctionName”. For me that function looks up the PLEG Counter, Using the CounterName, then decrements the StopCnt.
Only when the StopCnt reaches zero … do I really execute the stop behavior. The termination of the other counters only decrement the StopCnt.

i.e. When Vera finishes the timer, it calls my function. My function decrements the “StopCnt” from N, to N -1, … ultimately to zero where N indicates there are N outstanding timer requests for this particular timer. Only when it gets to 0 do I consider that the Logical Timer has actually expired.
[hr]

I guess I need a NON programmer to describe this in a manner suitable for non developers.
When the delay is always the same … the appearance to the end user is as you indicated. I.e. it appears to just reset.
But when you have different intervals passed to StartTimer, while the timer is running … the illusion is shattered … that’s why I felt it was important to understand the behavior.
The example I used before might be considered an unanticipated behavior.[/quote]

Actually, reading your text between the horizontal lines and then rereading your original statement helped a bit. So are the multiple “resets” additive?

For instance, I call a 00:10:00 timer and let it run for two minutes. I’d therefore have 00:08:00 left on the original timer call. At that two-minute mark, I call the same timer for a different condition/value (say 00:15:00) due to a motion hit. Does that mean that I will have to wait for 8+15 = 23 minutes? Or, does the 15 minute call just increment your StpCnt variable and do nothing as far as delay is concerned. Then only having to wait the original 8 minutes?

Or do the timers run in parallel? Therefore both 8:00 and 15:00 would countdown together? Making you wait a total of 2+15 = 17 minutes?