Author Topic: Creating triggers from luup code  (Read 24564 times)

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #30 on: March 18, 2014, 05:15:40 pm »
How would you envisage specifying which 'nodes' / variables you want this to apply to?  There are different approaches, but the basis is to use luup.variable_watch 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

Offline akbooer

  • Master Member
  • *******
  • Posts: 6123
  • Karma: +274/-69
  • "Less is more"
Re: Creating triggers from luup code
« Reply #31 on: March 18, 2014, 05:22:26 pm »
OK, I'm not sure whether we're using the same terminology yet...

Quote
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.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #32 on: March 18, 2014, 05:33:30 pm »
OK, I'm not sure whether we're using the same terminology yet...

Quote
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.

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.

Light is off

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



 

Offline akbooer

  • Master Member
  • *******
  • Posts: 6123
  • Karma: +274/-69
  • "Less is more"
Re: Creating triggers from luup code
« Reply #33 on: March 18, 2014, 06:31:46 pm »
Ah, OK, you're talking about dimmers specifically (ie not on/off switches.)

So to revert to your original question:
Quote
Ideally I want to watch all the Z-Wave nodes and send updates every time the node level changes.
we could say:
  • is this possible? - yes, for sure
  • Where would the code be put? - several places, but simplest is in a file loaded in the Startup Lua code
  • Where could i find a head start with the code needed to watch and parse the data? - here.

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

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) ?
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #34 on: March 19, 2014, 03:38:39 am »
That's great news and reassuring to hear this is possible.

Quote
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.

Quote
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



Offline dunked

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +3/-0
Re: Creating triggers from luup code
« Reply #35 on: March 19, 2014, 04:33:45 am »
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 


Code: [Select]
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

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #36 on: March 19, 2014, 03:17:37 pm »
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?

Code: [Select]
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

Offline dunked

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +3/-0
Re: Creating triggers from luup code
« Reply #37 on: March 19, 2014, 05:52:51 pm »
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
Code: [Select]
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
Code: [Select]
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.

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #38 on: March 20, 2014, 03:35:52 am »
Thanks I will give it a go tonight after work and report back...

I'm in the UK (GMT)

Steve

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #39 on: March 20, 2014, 02:23:05 pm »
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.

Code: [Select]
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?

Code: [Select]
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

Offline dunked

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +3/-0
Re: Creating triggers from luup code
« Reply #40 on: March 20, 2014, 02:51:18 pm »
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

Code: [Select]
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

Offline akbooer

  • Master Member
  • *******
  • Posts: 6123
  • Karma: +274/-69
  • "Less is more"
Re: Creating triggers from luup code
« Reply #41 on: March 20, 2014, 02:51:27 pm »
Not quite sure about the semantics or syntax of your http.request ("3=3" "40=40" looks weird), but the key parameters you need from the callback function parameter list are dev_id and new_val.  You can use the string concatenation operator ".." to join these to what you will.

For example:
Code: [Select]
local x = "Var 241 : "
local y = x .. new_val

would result in y having a value of "Var 241 : 42" if the received value of new_val was "42".  You can use identical syntax for dev_id (even though it is, in fact, a number.)

While you are at it, you should remove the "require" statement from the function (put it earlier in the code.)  Also, if you're not going to check the return value of result or status then you don't need them there.

Hope this helps.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #42 on: March 20, 2014, 03:28:41 pm »
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

Code: [Select]
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

Wow, now you lost me...

Offline Stealth

  • Sr. Newbie
  • *
  • Posts: 25
  • Karma: +0/-0
Re: Creating triggers from luup code
« Reply #43 on: March 20, 2014, 04:02:20 pm »
Not quite sure about the semantics or syntax of your http.request ("3=3" "40=40" looks weird),

Yes I agree.  I have just consulted my 3rd party HA Controller community and advised to use the following syntax to send a fixed data value-
("http://192.168.0.23:3005/HVTableVar.html","Var 241 : 3==")

Just to confirm the 3 repersents node id number 3 so this is where I need to parse the dev-id.  I tried this code below with no luck -
("http://192.168.0.23:3005/HVTableVar.html","Var 241 : dev-ID==")
("http://192.168.0.23:3005/HVTableVar.html","Var 241 : (dev-ID)==")
("http://192.168.0.23:3005/HVTableVar.html","Var 241 : "dev-ID"==")

Quote
but the key parameters you need from the callback function parameter list are dev_id and new_val.  You can use the string concatenation operator ".." to join these to what you will.

For example:
Code: [Select]
local x = "Var 241 : "
local y = x .. new_val

would result in y having a value of "Var 241 : 42" if the received value of new_val was "42".  You can use identical syntax for dev_id (even though it is, in fact, a number.)

I'm not sure I understand what you mean in your above recommendation.  Just to confirm the 3rd party HA controller variable number Var 241 needs to have the device ID parsed and Var 242 needs the light level parsed in.

Quote
While you are at it, you should remove the "require" statement from the function (put it earlier in the code.)  Also, if you're not going to check the return value of result or status then you don't need them there.

I'm not sure where to put it earlier in the code.  Where should it be?

Currently its now looking like this so far (I have taken the macro command out for now as I know that works ok)-

Code: [Select]
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
http.request("http://192.168.0.23:3005/HVTableVar.html","Var 241 : 3==")
http.request("http://192.168.0.23:3005/HVTableVar.html","Var 242 : (new_val)==")
end
[\Code]

I really appreciate the help you guys are giving....

Steve

Offline akbooer

  • Master Member
  • *******
  • Posts: 6123
  • Karma: +274/-69
  • "Less is more"
Re: Creating triggers from luup code
« Reply #44 on: March 20, 2014, 04:34:23 pm »
So to be even more specific:

Code: [Select]
local http = require("socket.http")
http.TIMEOUT = 5
local url = "http://192.168.0.23:3005/HVTableVar.html"

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
  http.request(url, "Var 241 : " .. dev_id .. "==") 
  http.request(url, "Var 242 : " .. new_val .. "==")
end

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


« Last Edit: March 20, 2014, 04:37:09 pm by akbooer »
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.