Creating triggers from luup code

I have never used modules or the “module” keyword. I can happily call functions and run code in the files that I “require” without any difficulty.

Cool. I’ll give it a go. Old habits die hard. Although I see it specified this way often.
Do you use the Luup files pages to download file to Vera, or some other way?

Yep I just use luup files to get them to the vera. It’s all been nice and simple - which makes a change!

Would I be right in saying that once a function is loaded either from an uploaded .lua file or specified in the Luup Start Up (under Apps/Dev) - can it be referred to within a scene?

Yes, that’s right.
Almost all my scene Luup is just one-liners which call functions loaded at startup.

[quote=“akbooer, post:10, topic:176379”]@dunked
[…]
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 ??[/quote]

At last, I’ve got to the root of this callback issue - the problem is well described in an old thread:
[url=http://forum.micasaverde.com/index.php/topic,10258.0.html]http://forum.micasaverde.com/index.php/topic,10258.0.html[/url]

…with solutions from @guessed:

…and @futzle:

[quote=“futzle, post:3, topic:171230”]The way I normally do this is to copy the function from the module into the global symbol table explicitly.

t =require("test") CallBackTimer = t.CallBackTimer [/quote]

Thanks to all on this thread and those mentioned above for putting me right.

I’ve avoided the trouble you’ve been having, and it seems that’s because I’ve never used any modules! I’ll try and keep it that way, the simpler the better!

Hi Guys,

I have been recommended to this thread for help.

I’m new to the Vera Lite and coding. I am looking for a solution so I can have my Vera Lite send node status updates out to my 3rd party home automation controller, as and when a node state is changed.

The data I need to send is-

  1. Node ID

  2. Node level On (1-100) or node Off.

I have the code below which will send the two variable values onto my 3rd party HA controller and run a macro to update the internal lighting table (Node 3 Light level 50%) -

local http = require(“socket.http”)
http.TIMEOUT = 5
result, status = http.request(“http://192.168.0.23:3005/HVTableVar.html","Var 241 : 3 = 3”)
result, status = http.request(“http://192.168.0.23:3005/HVTableVar.html","Var 242 : 50 = 50”)
result, status = http.request(“http://192.168.0.23:3005/HVTableMacro.html","Macro 37=Run Macro”)

Var 241 is for the light node ID

Var 242 is the light node level status

I would be grateful if someone could talk me through how I could set this up to trigger when a node state changes, then to send the http commands that would parse the relevant node and light level.

I rather not setup a scene for each node with the Luup code as this will need loads of scenes which would be a nightmare. If there is a way to put some code together that would work for new nodes as they are added that would be fantastic.

Please bear in mind I am a complete newbie… I realise I have a steep learning curve but I need to get this working.

Any help would be appreciated.

Steve

How would you envisage specifying which ‘nodes’ / variables you want this to apply to? There are different approaches, but the basis is to use [tt]luup.variable_watch[/tt] to watch those variables and to call a function with your code in it, so you do need some algorithmic way of defining what you’re interested in.

Thank you for your reply…

Ideally I want to watch all the Z-Wave nodes and send updates every time the node level changes.

I could do with some pointers on the following -

  1. is this possible?

  2. Where would the code be put?

  3. Where could i find a head start with the code needed to watch and parse the data?

Thanks again for any help/pointers

Steve

OK, I’m not sure whether we’re using the same terminology yet…

Ideally I want to watch all the Z-Wave nodes and send updates every time the node level changes
What specifically do you mean by 'node level'?

Each Z-Wave device in Vera comprises a number of variables - most of which aren’t interesting at the HA level, so I can’t believe you want to track every variable.

[quote=“akbooer, post:32, topic:176379”]OK, I’m not sure whether we’re using the same terminology yet…

Ideally I want to watch all the Z-Wave nodes and send updates every time the node level changes
What specifically do you mean by 'node level'?

Each Z-Wave device in Vera comprises a number of variables - most of which aren’t interesting at the HA level, so I can’t believe you want to track every variable.[/quote]

I’m sorry for the confusion… :-[

When I say node, I mean Z-Wave Light module.

Yes you’re correct, I won’t need to track all variables, I just need to track the light state i.e.

[b]Light is off

Light is on and at what level [/b](i.e. with a level between 1 and 100%) reported back by http as 1-100.

Ah, OK, you’re talking about dimmers specifically (ie not on/off switches.)

So to revert to your original question:

Ideally I want to watch all the Z-Wave nodes and send updates every time the node level changes.
we could say:

[ol][li]is this possible? - yes, for sure[/li]
[li]Where would the code be put? - several places, but simplest is in a file loaded in the Startup Lua code[/li]
[li]Where could i find a head start with the code needed to watch and parse the data? - here.[/li][/ol]

Basically, the [tt]luup.devices[/tt] table described here [url=http://wiki.micasaverde.com/index.php/Luup_Lua_extensions#variable:_devices]http://wiki.micasaverde.com/index.php/Luup_Lua_extensions#variable:_devices[/url] contains a table for each device number which includes an item [tt]device_type[/tt]. For dimmers, that string has the value [tt]“urn:schemas-upnp-org:device:DimmableLight:1”[/tt].

For each of these devices you need to set a variable watch callback, as described in this thread, the callback fuction would essentially contain the code you quoted for notifying your other system.

Do you need more (not sure what expertise level we’re talking, here) ?

That’s great news and reassuring to hear this is possible.

Ah, OK, you're talking about dimmers specifically (ie not on/off switches.)
Again I'm sorry for the confusion. I will need to watch for both dimmers and on/off switches.
For each of these devices you need to set a variable watch callback, as described in this thread, the callback function would essentially contain the code you quoted for notifying your other system. Do you need more (not sure what expertise level we're talking, here) ?
This is where I could do with having my hand held... I'm a complete newbie to luup and the Vera. However once I have the base of the code structure under my belt, I'm sure I could learn how to tweak it where necessary.

Thanks again for your assistance. It’s much appreciated.

Steve

Here’s a snippet of code that I use that sets a callback on all lights being switched on or off (the Status variable flips between 0 and 1). Basically it goes through all devices and sets a callback on those that are dimmable lights or binary lights. you can see the function “device_power_state_change” gets called each time Status changes. Note the callback is called when the device is switched on or off, not when the light level of a dimmable light changes. to do that you’d need to set a callback on LoadLevelStatus

function set_callback_on_light_on_or_off()
	-- goes through all devices and sets a callback on lights or switches that may control lights
	luup.log("--MC-- ======================== set_callback_on_device_power_on_or_off RUNNING ======================== ")
	for dev_id, device_details_table in pairs(luup.devices) do
		if device_details_table.device_type == "urn:schemas-upnp-org:device:DimmableLight:1" or device_details_table.device_type == "urn:schemas-upnp-org:device:BinaryLight:1" then
			luup.variable_watch("device_power_state_change", "urn:upnp-org:serviceId:SwitchPower1","Status", dev_id)
			luup.log(string.format("--MC-- setting callback on device %s",get_dev_name(dev_id)))
		end
	end
	luup.log("--MC-- ======================== set_callback_on_device_power_on_or_off ENDED ======================== ")
end

Hi Dunked,

Thank you for your code sample. Just so I am clear. If I amend your code to callback on LoadLevelStatus as below, this will then track LIGHT LEVELS and On/OFF status?

function set_callback_on_light_status_change()
	-- goes through all devices and sets a callback on lights or switches that may control lights
	luup.log("--MC-- ======================== set_callback_on_light_status_change RUNNING ======================== ")
	for dev_id, device_details_table in pairs(luup.devices) do
		if device_details_table.device_type == "urn:schemas-upnp-org:device:DimmableLight:1" or device_details_table.device_type == "urn:schemas-upnp-org:device:BinaryLight:1" then
			luup.variable_watch("LoadLevelStatus", "urn:upnp-org:serviceId:SwitchPower1","Status", dev_id)
			luup.log(string.format("--MC-- setting callback on device %s",get_dev_name(dev_id)))
		end
	end
	luup.log("--MC-- ======================== set_ callback_on_light_status_change ENDED ======================== ")
end

If the code above is correct, am I right in saying, this code together with my updated code (to parse the ID and status code) is to be pasted in the Edit Startup Lua section? Or have I completely lost the plot and showed my naivety?

Thank you for your patients with me being a complete novice.

Steve

Not quite - the callback function calls your function when the variable being watched changes

so to call a function you create called “my_function_to_handle_power_state_change” when the on/off status changes you’d need to code

luup.variable_watch("my_function_to_handle_power_state_change", "urn:upnp-org:serviceId:SwitchPower1","Status", dev_id)

and to call another function called “my_function_to_handle_dimming_level_change” you’d code

luup.variable_watch("my_function_to_handle_dimming_level_change", "urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", dev_id)

where dev_id is the device no.

you can paste code into the startup lua section - when you’ve got it all working and tested! - whatever code you put there will run every time you do a reload so you have to do a reload to test it. So whilst you are developing and testing its best to use the Test Luup code (Lua) section and keep an eye on the logs (you don’t need to keep reloading to run it there)

Callbacks like variable_watch can be tricky to use, so if you’re just beginning with Vera code then I’d start with something simpler like creating a function to print the dimming level to the log. When you’ve got that working ok then I’d add a callback to call your function (using code like that above). Don’t paste any of it into startup straight away - if you leave that empty until you’re sure it all works then if everything goes horribly wrong with your code you can just reload to get things back to normal.

Hope that’s of some use and good luck!

PS - I think I’m in a different time zone to you so I won’t get to any more questions until tomorrow.

Thanks I will give it a go tonight after work and report back…

I’m in the UK (GMT)

Steve

I have spent some time testing the code below and the function is called each time a light is turned on/off or level changed, which is just what I wanted thanks.

luup.variable_watch("my_function_to_handle_dimming_level_change", "urn:upnp-org:serviceId:Dimming1", "LoadLevelStatus", dev_id)

function my_function_to_handle_dimming_level_change(dev_id,service, variable, old_val, new_val)
   -- called when a device is switched on or off - from a variable_watch

local http = require("socket.http")
 http.TIMEOUT = 5
result, status = http.request("http://192.168.0.23:3005/HVTableVar.html","Var 241 : 3 = 3")
result, status = http.request("http://192.168.0.23:3005/HVTableVar.html","Var 242 : 40 = 40")
result, status = http.request("http://192.168.0.23:3005/HVTableMacro.html","Macro 37=Run Macro")
end

I now need to parse the node ID number and the light level number to my two variables no 241 and 242. I tried the syntax below to parse the data in but it doesn’t seem to work. Any ideas on what I have missed?

function my_function_to_handle_dimming_level_change(dev_id,service, variable, old_val, new_val)
   -- called when a device is switched on or off - from a variable_watch

local http = require("socket.http")
 http.TIMEOUT = 5
result, status = http.request("http://192.168.0.23:3005/HVTableVar.html","Var 241 : (dev_id) = 3")
result, status = http.request("http://192.168.0.23:3005/HVTableVar.html","Var 242 : (LoadLevelStatus) = 40")
result, status = http.request("http://192.168.0.23:3005/HVTableMacro.html","Macro 37=Run Macro")
end

Thanks again for the help.

Steve

I’m going to cheat and not check through your code (I’ve got 10 minutes before I have to go out!)

But it looks like you’re trying to call a web page with some parameters - something I do a lot but I do it a different way

function log_temperature_change(dev_id,service, variable, old_val, new_val)
	luup.log("--MC-- ======================== log_temperature_change RUNNING ======================== ")
	local dev_name = get_dev_name(dev_id)
	dev_name = string.gsub(dev_name, "%s", "+")
	dev_name = string.gsub(dev_name,"&","%%26")			-- change & for %26
	local reading_ts_as_datestring = string.gsub(os.date("%Y-%m-%d %H:%M:%S"),"%s","+")
	local url = "http://10.10.10.210/energy/add_temperature_reading.php?dev_name="..dev_name.."&reading_ts="..reading_ts_as_datestring.."&temperature="..new_val
	luup.log(url)
	local result = luup.inet.wget(url, 0)
	luup.log("--MC-- ======================== log_temperature_change ENDED ======================== ")
end

get_dev_name is a function that gets the device name that I wrote (it only has one line of code so you don’t really need it, but it’s neater)

this function is called from a variable_watch also (for devices that report a temperature). I had to spend lot of time working out how to escape characters and encode the URL, and the code above does work so it may save you some time if you hit that problem (particularly where a device name has a space in it).

Have a look and see if it’ll help you. I may get back on line later tonight. but I doubt it.

Cheers