Creating triggers from luup code

Hi,

I have over 10 door and motion sensors. I’ve written some luup code to alert me (using Vera Alerts - great app!) when they get tripped and also they get logged to a mysql database using some php code as well. That all works very well.

My issue is that I’ve done this by creating a scene for every sensor that calls my luup function, passing in a device id - so that’s a lot of scenes I’ve had to manually create - and I’m wondering if there is a better way (it’s not very tidy!). I have tried creating one scene and manually creating lots of triggers for it (one for each sensor) that seems to be working but again that’s a lot of manual triggers to create.

I’d rather somehow automate this in my lua startup to run some code that can read through all my devices of a certain type (e.g. door sensors) and create a trigger for each of them that calls my function. I’ve not seen any obvious way to do that (create the trigger that is, I know how to read the device list)

The only way I can think of is to use variable_watch checking for changes to “Tripped” I’ve not tried that yet and worry about how efficient and quick it might be. But I do wonder if that is what the Vera is doing internally whenever you create a trigger for a scene.

Does anyone know or have any ideas? I’d appreciate some guidance.

Thanks

You can replace the many scenes with many triggers in 1 scene … one for each trigger.
In the LUA you can set a variable indicating witch trigger caused the scene to wake up.

In the Scene Level LUA you can do the common code, using the variable that was set by the trigger level lua code.

Or you can use the Program Logic Event Generator plugin.

I know it’s not popular with some folk, but since you know how to scan the device list, then why don’t you just poll the required sensors with a one minute scheduled scene?

Thanks for the replies - it’s taken me a while to get them as I’ve been away on holiday (… seems like distant memory already …)

I spotted the trick with many triggers in each scene and had a go - but it still didn’t meet my insane desire to do it in code rather than muck around in the Vera UI.

I had a look at PLEG some time back, I think it could work, but, I want to learn more about luup coding and write my own. So I’m determined to do it the hard way!
And yes polling could be a plan B, but it would add a performance hit.
There must be some code internally to the Vera that sets up triggers and I’m guessing that it’s something like variable_watch - but not sure enough to stake my life on it! What I don’t know is just how reliable variable_watch is.

So what I’ve done is run some tests using variable_watch to watch for SwitchPower1 status changes - so capturing when lights etc. are turned on and off - it does seem to work consistently well - there are too many such events to be absolutely sure none have been missed, but all the ones I know about have been fine.
and rather than write a loop to go through the device list I just manually added a variable_watch line for each device in my startup code using notepad++ it’s a doddle to copy and paste those and a darn sight easier than setting up all those scenes and triggers manually.

So I think I’ll bite the bullet and add variable_watch for all my security sensors too. If it goes horribly wrong I’ll report back.

Cheers

So it’s really about event logging rather than triggering per se. Have you looked at all the discussion on alternative notification? See [url=http://forum.micasaverde.com/index.php/topic,15245.0.html]http://forum.micasaverde.com/index.php/topic,15245.0.html[/url].

For variable_watch, it’s pretty fundamental to how the system works, and lots of very trusted apps (DataMine an example, I think) use this. No reason to suppose what you are planning won’t work.

Let us know how it goes!

How did it go @dunked?

I’m always interest to see the code people use…

Well so far so good. I’ve had this running for over a week now. I did decide on a simple loop in my code that sets a callback on all my sensors (that way if I add a sensor or take one out it gets picked up automatically) and it all seems very reliable.

My callback is getting more complicated as initially I used it just to log events to a database, now I have it sending alerts to my phone if a sensor is armed (using Vera Alerts), and I’ve just added a bit more code to help me manage my automatic lights (if a light gets turned manually off and back on then it resets a variable which stops any timers running that would turn it off automatically).

To akbooer’s point I hadn’t spotted the alternate event server you pointed me at. It won’t work for me as I want to run LUA code on the Vera when something happens, but I may well use it another time.

My current challenge is to tweak my code so that I can spot if a device is actually owned by another Vera (I have 3 with some bridging), so that I don’t start tracking a device from another Vera if that one is also tracking it - luckily I think using the parent device id will help with that.

I still don’t know for sure but my guess is that when you set a trigger using the Vera UI it’s just adding a variable_watch to its own code. I wondered if that was the case when I started this thread, I’m more confident now. I wonder if the Vera’s own routines are written in LUA and I can find them somewhere to check this out.

Good to hear. Can you be explicit about where you have the code running? I’ve never had any luck with callbacks in startup or scene code.

Regarding the alternate server, I’m excited to have found an old post by @TOP320
[url=http://forum.micasaverde.com/index.php/topic,9525.msg91855.html#msg91855]http://forum.micasaverde.com/index.php/topic,9525.msg91855.html#msg91855[/url]
which shows how to run that server locally on the Vera, opening up a host of opportunities to do the sort of things you are doing. I just can’t understand why this hasn’t been taken up in the discussions on this topic. I’m obviously missing something.

The technique I use for running my code stemmed from what seems to be best advice from the forums (and it works so I’m happy).
Essentially I have 2 Vera 3s and a Vera Lite. I have one lua file for each of them and a common file. These are where I keep all my code - most of the code is in my common file as it contains routines that all the veras use. So in my case I have 4 files -
my_common_code.lua
my_vera_house_code.lua
my_vera_stables_code.lua
my_vera_study_code.lua

So in the Apps/ Develop Apps / Luup files section I upload two files to each Vera - The common one and the one specific to that device. So for my Study one (which is my test Vera) I upload my_common_code.lua and my_vera_study_code.lua.

Then in the Edit Startup Lua section I have two lines
require(“my_common_code.lua”)
require(“my_vera_study_code.lua”)

those require statements tell the vera that when it starts up to load those two files and run whatever’s in them.

I’m an old fashioned programmer so I prefer procedural rather than Object Oriented programming so my common code file is full of functions such as turn_device_on(dev_id). When the startup runs those functions all get loaded (as part of that require statement above) and then I can call the function from luup code in a scene e.g. turn_device_on(26)

Hope that all makes sense.

@dunked

Thanks for the speedy reply with very full information. And, in fact, yes, I do all that too with the only difference being that I have exactly the same files ‘required’ on all three machines and they auto-configure depending of what installed devices they find.

One utility code I use everywhere maps device names to IDs so that helps with machine independence too.

My problem is simply that when I’ve tried to use any callback like variable watch or timers, etc., then the function supplied as a named string in the setup call is never found and generates a runtime error when the event occurs. What am I doing wrong ??

The error messages can be a pain and really unhelpful sometimes >:(

Here are some genuine working code snippets.

luup.variable_watch(“device_power_state_change”, “urn:upnp-org:serviceId:SwitchPower1”,“Status”, 112)

sets up the callback to the function pasted below

function device_power_state_change(dev_id,service, variable, old_val, new_val)
– called when a device is switched on or off - from a variable_watch
if new_val == “1” then
device_switched_on_or_off(dev_id,“true”) – NOTE WE ARE USING A TEXT STRING FOR TRUE NOT A BOOLEAN VALUE
else
device_switched_on_or_off(dev_id,“false”)
end
end

as an aside(and you may know this already) but when I’m testing a function (such as that above) if you copy and paste it into the test luup code box and run it, it will seemingly do nothing but it does get registered, so then you can clear the text box and happily call it. If it doesn’t work right then you can tweak the code in an editor and then paste the function in again and it will use the new code. Of course as soon as you restart Lua for whatever reason the function goes back to what’s defined in your luup files. Doing it this way means you haven’t got to save your code and upload it each time.

Thanks, will give it a go again.

Re. your “aside”, yes indeed, I’m a proponent of the approach to Vera development…
[url=http://forum.micasaverde.com/index.php/topic,14815.msg112418.html#msg112418]http://forum.micasaverde.com/index.php/topic,14815.msg112418.html#msg112418[/url]

Aha! I should have read your post a few months back!

I just realised you also mentioned timers so here’s working call_delay code snippet

luup.call_delay(‘turn_off_device_timer’, timer_value,dev_id_string)

and the first two lines of the function

function turn_off_device_timer(dev_id_string)
– called as a call_delay timer, does a few checks and turns a device off, for example if light level has been changed then don’t turn device off

Good luck with the callbacks.

(I’m making a concerted effort to see if I can use eclipse for my LUA development before I start my next project - trying to build a very simple web UI for the rest of the family to use!)

Hi @dunked

[quote=“dunked, post:11, topic:176379”]Here are some genuine working code snippets.

luup.variable_watch(“device_power_state_change”, “urn:upnp-org:serviceId:SwitchPower1”,“Status”, 112)

sets up the callback to the function pasted below

function device_power_state_change(dev_id,service, variable, old_val, new_val)
– called when a device is switched on or off - from a variable_watch
if new_val == “1” then
device_switched_on_or_off(dev_id,“true”) – NOTE WE ARE USING A TEXT STRING FOR TRUE NOT A BOOLEAN VALUE
else
device_switched_on_or_off(dev_id,“false”)
end
end[/quote]

Please forgive the non programmer question, but what goes next in the code? I’m keen to monitor an obscure variable on a thermostat. E.g if variable ModeStatus is set to ‘HeatOn’ or ‘Off’ - if it’s ‘HeatOn’ then I want to do something like notify me or run a scene.?

Nothing “next” really. The function…

[code]function device_power_state_change(dev_id,service, variable, old_val, new_val)
– called when a device is switched on or off - from a variable_watch

end
[/code]

…is exactly what the comment says. You can put whatever you like in the body to call a notification plugin or whatever.

Sorry if that’s not a complete answer for you. Just ask again.
@dunked can probably do better.

Pretty much as @akbooer says - you can write code to do whatever you need

so if you have a variable_watch such as

luup.variable_watch(“thermostat_heat_on”, “urn:upnp-org:serviceId:thermostat”,"ModeStatus ", 112) ---- I made those values up so you’d need to check what they really are!

then when ModeStatus changes the Vera will call the function thermostat_heat_on which you will need to write and add to the vera, then in that function you can check if the new value is “HeatOn” and do your stuff.

Having said all that if you’re not comfortable coding you may not enjoy the experience. I have spotted that when adding triggers to scenes that some devices have a lot of things you can use as triggers - such as temperature changes or device switched on - you may find what you need is already available without having to write any code.

Thanks guys

You’ll be surprised at how limited the trigger options are compared to the number of variables that are listed against the device. So this is largely the only option I really have (assuming that variable is updated - I’m still testing.

As for the coding, that side intrigues me, so I consider it a challenge. :wink:

Your suggestion to create a .lua file for your own code and adding the line to the startup sounds like a really good idea. I already have some lines in the start up, so I could also, move that out to it’s own file too I assume just by add another line e.g

require(“my_code.lua”). – my obscure triggers and actions
require(“my_danfoss_living_code.lua”) – syncing my temp sensor with the living connect Trv

Then if I wanted to stop anything I could just remove the line, rather than edit the file ?

[quote=“parkerc, post:17, topic:176379”]Your suggestion to create a .lua file for your own code and adding the line to the startup sounds like a really good idea. I already have some lines in the start up, so I could also, move that out to it’s own file too I assume just by add another line e.g

require(“my_code.lua”). – my obscure triggers and actions
require(“my_danfoss_living_code.lua”) – syncing my temp sensor with the living connect Trv

Then if I wanted to stop anything I could just remove the line, rather than edit the file ?[/quote]

I found a few challenges when creating modules to include (especially when it came to creating sub-modules), so wrote up my findings…

[url=http://forum.micasaverde.com/index.php/topic,13296.msg112631.html#msg112631]http://forum.micasaverde.com/index.php/topic,13296.msg112631.html#msg112631[/url]

@parkerc,
The require thing with the Lua files is a proven technique and works well, so what you describe would work fine. The snag is that if your lua files are anything like mine they will grow and grow. So removing the require line would take out whatever else in in the file also.

What I tend to do is edit the lua file with the code I’m writing but, when I’m testing rather than keep saving and uploading the file (which gets tedious when you’ve done it half a dozen times). I just paste it into the “test luup code box” and run it there and only when it’s working do I upload the file.

Looks like @akbooer replied just before I finished this, with a much more comprehensive example. But if you’re new to this coding lark then I’d stick with what you’re planning for now, then as you get more confident then you can move onto the more powerfull stuff!

But I started by doing exactly what you describe, so dive on in and have fun!

Thanks again.

@akbooer seems to suggest that each separate file I create needs to start with the following line?

module("module-name", package.seeall)

Does that mean the first line would be something like this ?

module("my_code.lua", package.seeall)