Motion Activated Lights, turn off after x unless Motion within x

Hi All,

I know this is a frequently covered topic but after months of testing and tweaking I am giving in and asking for help.

I have a scene that is triggered by motion in that area or the door being opened.
I then have it check if it is daytime and if not, turn the light on and set a timer for 6 mins with in the function. The idea being that if the scene is triggered again, the timer will be reset to 6 mins again and count down (to the Off function).

What is happing though is unpredictable. It most of the time comes on, but too often it will come on the turn strait back off. Or now that i added to check the status of the light, it may never turn on. The last part probably due to the dimmers being LightwaveRF dimmers which do not seem to transmit their status only receive a command so Vera can get out of sync when someone manually hits the switch.

Can someone cast an eye over this script and tell me where I am being an idiot and if they can think of a way to compensate for the lack of transmit from the switch (some kind of normalisation using LastTrip time maybe of the PIR in that area?)

I did originally use the call_delay function but i found that to just flash the lights also, i am guessing it was queuing up delays and sending off commands, hence trying to create a resettable timer for OFF.


local HallwayLight = 85
local day = luup.variable_get(“urn:rts-services-com:serviceId:DayTime”, “Status”, 105)
local SES_SID = “urn:micasaverde-com:serviceId:SecuritySensor1”
local Dimmer_SID = “urn:upnp-org:serviceId:Dimming1”
local LightStatus = luup.variable_get( Dimmer_SID, “LoadLevelStatus”, HallwayLight)

function HallwayLightsON ()
if (day == “0”) and (LightStatus == “0”) then
luup.call_action( Dimmer_SID, “SetLoadLevelTarget”, { newLoadlevelTarget = “100”}, HallwayLight)
luup.call_timer(“HallwayLightsOFF”, 1, “6m”, “”, “”)
elseif (day == “1”) and (LightStatus >= “1”) then
HallwayLightsOFF()
end
end

function HallwayLightsOFF ()
if (LightStatus >= “1”) then
luup.call_action( Dimmer_SID, “SetLoadLevelTarget”, { newLoadlevelTarget = “0”}, HallwayLight)
end
end

HallwayLightsON ()

andyvirus,

There are at least two ways of doing this with plugins rather than Luup code, but I’ll restrict myself to looking at your code.

The assignments to [tt]day[/tt] and [tt]LightStatus[/tt] happen outside any function. The trouble with this is that they will be set, once, when the Luup engine loads, then they will retain those same values forever. Probably you need to be testing those values each time the function runs. Move those lines.

Also comparing a string with >= isn’t going to do what you think, so convert the [tt]LightStatus[/tt] variable to a number before you compare it with 1.

Also, if you operate this code more than once in a six-minute period then each time it will schedule a call to HallwayLightsOFF() six minutes hence. The first one will still run, six minutes from the time you first walked past the sensor, even if you are still walking past. Fixing this is tricky. You will need to code HallwayLightsOFF() so that it exits without doing anything if there’s been a more recent trip. The below will sort of work; it increments a counter each time HallwayLightsON() is called and makes sure that this value hasn’t changed before turning the light off.

[code]local HallwayLight = 85
local SES_SID = “urn:micasaverde-com:serviceId:SecuritySensor1”
local Dimmer_SID = “urn:upnp-org:serviceId:Dimming1”
local tripCounter = 0

function HallwayLightsON ()
local day = luup.variable_get(“urn:rts-services-com:serviceId:DayTime”, “Status”, 105)
local LightStatus = luup.variable_get( Dimmer_SID, “LoadLevelStatus”, HallwayLight)
if (day == “0”) and (LightStatus == “0”) then
luup.call_action( Dimmer_SID, “SetLoadLevelTarget”, { newLoadlevelTarget = “100”}, HallwayLight)
luup.call_timer(“HallwayLightsOFF”, 1, “6m”, “”, tripCounter)
tripCounter = tripCounter + 1
elseif (day == “1”) and (tonumber(LightStatus) >= 1) then
HallwayLightsOFF()
end
end

function HallwayLightsOFF (oldTripCounter)
if (tonumber(oldTripCounter) ~= tripCounter) then return end
local LightStatus = luup.variable_get( Dimmer_SID, “LoadLevelStatus”, HallwayLight)
if (LightStatus >= “1”) then
luup.call_action( Dimmer_SID, “SetLoadLevelTarget”, { newLoadlevelTarget = “0”}, HallwayLight)
end
end

HallwayLightsON ()[/code]

There really aren’t any good workarounds for your lights not reporting their status.

Excellent, thanks futzle! I will update my scene(s) with your suggestions and give it a try. Thanks for taking the time to show me where I went wrong by providing an example as well with a description! I knew I was going wrong somewhere, but like many, not being used to scripting means mistakes will be made. Had your PL plugins been available when I started down this road many months back then I would have probably used them but I am in a little too deep to change now and I like the challenge of learning something new so want to do as much in LUUP as possible. I will give the PL plugins a look as soon as everything is working as expected though (or I pull my hair out, which ever comes first).

Thanks again!

Credit where it’s due: the Program Logic plugins are the work of RichardTSchaefer.

Apologies. I don’t know where I got that. Must have ready it on a post somewhere. Great work RichardTSchaefer, these plugins are what Mios/Vera should have in its core system as standard!

@futzle

I stand on the shoulders of men and women that have gone before me …
You deserve much credit for supporting me!

Quick question futzle: In your example, when does tripCounter get reset to 0?

I can see that each time the script is triggered it turns the light on if it is night, schedules the off for 6 mins and increments tripCounter by 1.

Each time the script runs is tripCounter not always 0? and if not how does it get reset to 0?

Apologies for what is probably a dumb question but cant figure it out. I think it does not help that the documentation of luup.call_timer lacks examples so possibly it is where you have tripCounter in the luup.call_variable but no idea.

As this could get tripped many times an hour I just want to get my head around this as I use similar code for lots of lights in the house (and will probably do a simular thing for heating but that’s on another thread).

Good point. If you put this code into the Luup text area for the device then it’ll keep getting reset to zero, which you don’t want.

It’s best to put functions and initialization code into Apps > Develop Apps > Startup Lua. You can put all this code there:

[code]HallwayLight = 85
SES_SID = “urn:micasaverde-com:serviceId:SecuritySensor1”
Dimmer_SID = “urn:upnp-org:serviceId:Dimming1”
tripCounter = 0

function HallwayLightsON ()
local day = luup.variable_get(“urn:rts-services-com:serviceId:DayTime”, “Status”, 105)
local LightStatus = luup.variable_get( Dimmer_SID, “LoadLevelStatus”, HallwayLight)
if (day == “0”) and (LightStatus == “0”) then
luup.call_action( Dimmer_SID, “SetLoadLevelTarget”, { newLoadlevelTarget = “100”}, HallwayLight)
luup.call_timer(“HallwayLightsOFF”, 1, “6m”, “”, tripCounter)
tripCounter = tripCounter + 1
elseif (day == “1”) and (tonumber(LightStatus) >= 1) then
HallwayLightsOFF()
end
end

function HallwayLightsOFF (oldTripCounter)
if (tonumber(oldTripCounter) ~= tripCounter) then return end
local LightStatus = luup.variable_get( Dimmer_SID, “LoadLevelStatus”, HallwayLight)
if (LightStatus >= “1”) then
luup.call_action( Dimmer_SID, “SetLoadLevelTarget”, { newLoadlevelTarget = “0”}, HallwayLight)
end
end
[/code]

(I took out the “local” because those variables aren’t really local any more.)

Then the only part that you need on the scene itself is:

HallwayLightsON ()

It’s OK that tripCounter keeps increasing forever. A different number each time the scene is called is what you want, and an always-increasing number is the simplest way to guarantee it.

I’m glad I found this forum and especially this thread.

I’m looking for a solution to activate a 3-way light switch based on motion detection from a Foscam camera. If the lights are off, the camera is armed, and any motion triggers the lights to come on.

Also, I’d like to set a rule that says if the camera doesn’t detect motion in, say 5 minutes after the light turns on, Vera should turn off the lights.

All of this will be time dependent, of course, so the lights won’t turn on in the middle of the day.

I’d really like to accomplish this with Zwave. Is this realistic and feasible?

It sounds like the information on this thread will accomplish this.

I’m just looking for real world practical experience here. Is Vera smart enough to do this (both the on and off rules) reliably, and if so, can I do this using the plug-in described here, or should I expect to cheat and paste some Luup code?

If this can’t be done reliably, I’d rather just get a non-Z-wave 3-way motion switch.

Thanks in advance for all your help.