Luup Code to combat False Triggers of Aeon Labs 4 in 1 Multi Sensor

I’ve been thinking through the logic, and I think I may know how to prevent false positives from triggering the motion sensor. I came up with the idea after reading the section of the Luup wiki that talks about the “Thermostat conditioned by door/window”.

http://wiki.micasaverde.com/index.php/Luup_Scenes_Events#Thermostat_conditioned_by_door.2Fwindow

The problem is I have never coded at all for MIOS and have no clue how to do Luup code.

But here goes the idea:

  1. Set motion sensor timeout to a much faster setting than usual (i.e. 1 second if you really want to eat the batteries lol).
  2. Have the luup code run and only trigger for an armed sensor that detects two trips in a row within a certain time frame (if the motion time out is X seconds, allow the two trips to be seen within Y seconds, to give it time to trip again in case whoever is tripping the device stopped moving for a little while).
  3. False triggers should be taken care of, since from what I have seen are pretty random and are never that close together (I am running my motion time out at 1 second).

So if you set X to 1 second and Y to 10 seconds the code should cause this to occur: False trigger occurs with an armed sensor. A timer counts down from 10 seconds and waits to see if there is a second trigger, assuming the second trigger would be a real motion and not a false trigger. If it is a false trigger, the timer gets to 0 without detecting another motion trigger and nothing is sent to run the scene. If it is a real motion trigger, then the persons presence will trigger it again after 1 second and the timer hasn’t reached 0 yet, so the scene will run.

I think this is how you would go about doing it, but for some reason all I get is “ERROR : Error in lua for scenes and events”

[code]local SENSOR = 51 – The multisensor motion detector device number
local DELAY = 6 – Seconds to wait to check for a second trip

local SES_SID = “urn:micasaverde-com:serviceId:SecuritySensor1” – Not sure what to put here…

luup.call_delay( “falseTrigger”, DELAY)

– Skip running this scene if the last trip was more than DELAY seconds ago (a false trigger).
– Somehow this needs to only apply to when the 4 in 1 multi sensor is tripped, and not anything
– else that may start the scene. Otherwise, if something else triggers the scene and the
– multisensor hasn’t gone off in the last DELAY seconds, then it will think its a false trigger
– and exit out of the scene. If this isn’t possible, then there will always need to be a separate scene for the
– multisensors to activate, even if the scene is generally activated by other things as well.

function falseTrigger()
local lastTrip = luup.variable_get( SES_SID, “LastTrip”, SENSOR) or os.time()
– if statement also needs to include a check to see if the thing that is triggering the scene
– is a multisensor.
if (os.time() - lastTrip >= DELAY) then
return false
Else
return true
– Else statement will allow the scene to run if it is likely a real trigger

end

end[/code]

From a Lua syntax, “[tt]else[/tt]” should be written in lowercase.

You currently have it written as “[tt]Else[/tt]” which won’t work since the language is case sensitive.

Thanks!

Three questions:

  1. So I took out the “or os.time()” portion. In the example the wiki gives for the thermostat turning off when the door is open too long they used that there. I just don’t see the need for that in this example. What would be the point in putting that there? Will it error out if for some reason it can’t get the “lastTrip” variable?

  2. It still seems to trigger each time the sensor is tripped. Is the default time in seconds or minutes when I defined the DELAY variable as being 6? I see the lastTrip time as a long number (currently 1372043525). I was under the impression that with Lua, time is in seconds by default, so this should work right? I must be misinterpreting something.

Update - 3. I must be missing something, because I tested the code out by changing both outcomes to “return false” and the scene still runs regardless whenever a trip is detected. Any insight?

What would be the point in putting that there? Will it error out if for some reason it can't get the "lastTrip" variable?
If the lastTrip variable has never been set, then it's "value" will be nil, which represents "not set" in Lua. By writing the Lua construct "[tt]a or b[/tt]" then if [tt]a[/tt] is [tt]nil[/tt], then the value of [tt]b[/tt] will be returned.

In your case, if the [tt]LastTrip[/tt] UPnP State variable isn’t set, then [tt]variable_get[/tt] will return [tt]nil[/tt], and the overall expression (because of the or) will return the current time as the value for the [tt]lastTrip[/tt] variable.

Is the default time in seconds or minutes when I defined the DELAY variable as being 6?
[tt]os.time()[/tt] is a Lua call, and the units are in Seconds (since Epoch). So a DELAY of 6 represents 6 seconds.

You can use a site like this to see what the values mean:
http://www.epochconverter.com/

2. It still seems to trigger each time the sensor is tripped.
Right, but where did you inser the Lua code? If you've put this chunk into a Scene trigger, then it will fire each time that device causes the corresponding event. The "[tt]return[/tt]", when used in the timer function ([tt]falseTrigger[/tt]) is not going to do anything since it's async wrt the outer block of code... since you're using [tt]call_timer[/tt] to invoke it, which is asynchronous wrt to the outer block.

Effectively, your code is going to run something like:

setup stuff
tell the system to run [tt]falseTrigger[/tt] sometime later
implicitly return true, since you haven’t indicated otherwise ← so the Scene runs no matter what

<…sometime later…>
falseTrigger starts
does stuff
and return true/false (which is ignored.

It’s fine to have the trigger startup, and run [tt]falseTrigger[/tt] later, but you need to capture it’s state somewhere so that the first bit of code can act to de-bounce the event correctly, and it should explicitly [tt]return true[/tt] or [tt]return false[/tt] (not the [tt]falseTrigger[/tt] function)

Hopefully this makes sense…

That sort of makes sense… still trying to learn the language.

Questions:

  1. So essentially when I created the falseTrigger function, I needed it to run it immediately so as to not run the scene anyway? Not sure how I would do that.

  2. So if the LastTrip hasn’t been set before and therefore is nil, then by default it would show the current time aka os.time(). So what’s the point in putting in the or statement? Probably not any point right?

  3. So I stripped the code down to bare bones… and removed the falseTrigger function definition and it seems to work fine now. So what would be the benefit of leaving it in there and actually fixing it as stated in question 1?

Here is the code that seems to work fine:

[code]local SENSOR = 51
local DELAY = 20

local SS_SID = “urn:micasaverde-com:serviceId:SecuritySensor1”

local lastTrip = luup.variable_get( SS_SID, “LastTrip”, SENSOR)

if (os.time() - lastTrip >= DELAY) then

return false

else

return true

end[/code]

1. So essentially when I created the falseTrigger function, I needed it to run it immediately so as to not run the scene anyway? Not sure how I would do that.
I'm not sure of the question here, but originally your code has a need for some [i]deferred[/i] processing. Only the code running directly in the scene has the ability to return a value to let the scene proceed, or stop. Any deferred process is, well, deferred so it has no opportunity to stop the scene from executing. You were doing this to compute stuff.
2. So if the LastTrip hasn't been set before and therefore is nil, then by default it would show the current time aka os.time(). So what's the point in putting in the or statement? Probably not any point right?
In Lua, the expression [tt] x = a or b[/tt] will return the value of a, or it will return the value of b if a is nil. It's really just a convenience. In this case, it ensures that the rest of the code only has to deal with a value, and not have to handle "nil" values all the way though it.
3. So I stripped the code down to bare bones... and removed the falseTrigger function definition and it seems to work fine now. So what would be the benefit of leaving it in there and actually fixing it as stated in question 1?
If you have something work-able, then it should be fine to leave it. The one caveat here is that the Semantic of when [tt]LastUpdate[/tt] is set is not at all defined. In this case, you're relying upon it being set [i]after[/i] the state-change trigger fires your scene's code. In my Plugin code, I tend to set [tt]LastUpdate[/tt] [i]before[/i] I set the state-change. Without a clearly spec'd, and documented, behavior for when it's set, there's always the possibility that the behavior will change (with implementation) and the scene code won't work correctly (in some future patch and/or release)

[quote=“Outcomer, post:5, topic:175886”]That sort of makes sense… still trying to learn the language.

  1. So I stripped the code down to bare bones… and removed the falseTrigger function definition and it seems to work fine now. So what would be the benefit of leaving it in there and actually fixing it as stated in question 1?

Here is the code that seems to work fine:[/quote]

can you advise where this code should go ?

In the LUUP code section of the scene you wish for the multisensor to trigger