Reading input from lighting system

I modified the RadioRA plugin to work with my LiteTouch system. Unfortunately, it can only send updates for what button was pressed, and not updates for the level each load (light) is at. I have to query the system to get the load status for every load. The RadioRA plugin seems to just listen for updates and then update the switch in vera with the correct information. I need to poll. I have a couple of problems:

  1. What’s the best way to go about polling? Should I just create a loop that runs every 30 seconds and queries all 50+ loads?
  2. The response I get from a query doesn’t tell me which load I queried, it only shows the level. “18” is the query, and it works like this:
Query: " 18 02-6\r" (where 02-6 is the load I'm querying) Response: "18 250" (250 is the current level, levels go from 0-250)

Because the response doesn’t list the load I queried, I need to somehow keep track of which load I just queried and the next response needs to be parsed to update the switch in vera. What’s the best way to go about this?

I’m trying to see if I can get loads to send notifications, but I’m having problems getting the config from the controller downloaded to bring it into LiteWare for changes. I haven’t seen anything in the documentation about getting load notifications, only button presses. And most of my buttons are configured as scene presets.

So this is the code in the implementation file that listens for updates coming from the lighting controller:

<incoming> <lua> litetouch_cmd_buf = litetouch_cmd_buf .. tostring(lul_data) local cmd while true do local i = string.find(litetouch_cmd_buf, "\r") if i == nil then break end cmd = string.sub(litetouch_cmd_buf, 1, i-1) litetouch_cmd_buf = string.sub(litetouch_cmd_buf, i+1) ltReceiveCmd(cmd) end </lua>

I’m writing this function:

local function ltPollDimmer(load) log("Polling dimmer load: " .. load) cmd = " 18 " .. id ltSendCmd(cmd) -- do I need to handle the response here? end

That function will send something like " 18 02-6\r" to the controller. And the controller responds with something like “18 250”. The response does NOT contain the load id, only the level. So, how do I make sure that received data from the incoming function is used to update the correct switch in Vera?

Would this work:

  • set a global variable in my function above that denoted the load I was currently waiting on a response for
  • Create a new function that updates the switch with the load information and resets the global variable to nil
  • Use this new function in the “incoming” section above and call it when I see a response that starts with “18”

Can I set a global variable from within a function?

Would this work: - set a global variable in my function above that denoted the load I was currently waiting on a response for - Create a new function that updates the switch with the load information and resets the global variable to nil - Use this new function in the "incoming" section above and call it when I see a response that starts with "18"
This should work provided you only issue one request at a time. You should probably incorporate a timeout in case you get no response.
Can I set a global variable from within a function?
A variable that you define at the top level of your plugin implementation code is [i]global[/i] for the device. You can access it from any function in your implementation.

I remember reading somewhere that if I put a wait or sleep in any of my LUA code, it basically makes the entire LUUP engine hang until it’s over. Is this true?

My plan is to poll all loads on startup, and the poll loads after issuing a command. I’d like to wait 1 second after issuing the command because the poll function returns the current load level. So if it’s a dimmer that fades on and off, it won’t get the end result if it goes too quickly.

Also, I see that ZWave devices can be set to be polled every X seconds. How would one implement that in the plugin?

Ah! So I figured out an awesome solution for this. I was looping through the devices on startup to get the initial values of each dimmer/relay, and it would loop through them all before it started getting any response. So all of the responses would be given to my last device that I queried (because of the global queryLoad variable I set to indicate which response I’m waiting on.

I changed that queryLoad to an array, and use table.insert and table.remove to create a FIFO queue. As I do the requests, I do a table.insert, and as I receive them, I do a table.remove. Works awesome. All of the responses come back in order and get assigned to the proper switch.

Now, I just have to figure out how to make it automatically poll every X seconds.

Using a table is a good idea as long as the responses come back in the same order as the requests.

The best way to do polling from a plugin is by using luup.call_delay(“callbackfunction”,seconds,“parameter”). This will call your function callbackfunction after seconds and pass it the string parameter. The called function must be global (not local).

In callbackfunction you do your poll activity and then issue another luup.call_delay to itself for the next poll. Example:

function initstatus(lul_device) ...Initialization code ... luup.call_delay("doPoll",30,lul_device) end

function doPoll(deviceNum) local deviceNo = tonumber(deviceNum,10) ...poll stuff... luup.call_delay("doPoll",30,deviceNum) end
Note that I’m passing device number as the optional parameter as, otherwise, the called function will not have access to it.

What the difference between luup.call_delay and luup.call_timer? I’m using luup.call_timer as of last night and it seems to work.

Also, I ran into another problem… The FIFO works great, unless you press a switch or slider during the time it’s polling the devices. Then, it get’s all messed up and you end up with statuses getting set to the wrong switches.

I don’t see a good way to make this status update thing work reliably since the response from the CCU for a query does not include the load you just queried. Maybe if I used luup.call_delay to just do one query every second instead of all at once?

Annoying.

What the difference between luup.call_delay and luup.call_timer? I'm using luup.call_timer as of last night and it seems to work.
For this application you could use either. luup.call_timer has additional capabilities for dates, sunrise, etc. If it is working, great.
I don't see a good way to make this status update thing work reliably since the response from the CCU for a query does not include the load you just queried. Maybe if I used luup.call_delay to just do one query every second instead of all at once?
That's what I would do. It should minimize the chance of getting the queries and responses mixed-up.

Sweet! I got it working. I created a circular queue with every device in it. It’s basically a FIFO, but when I pop stuff off the top, I push it back on the bottom. Every 2 seconds, a device is polled and the top item is moved to the bottom. But when you press a button in Vera, it basically interrupts the 2 second polling and is given priority for an immediate update of the button/dimmer status in Vera.

Any drawbacks to polling a device every 2 seconds? Would it hurt to go to 1 second? I have about 50 loads, so it takes up to 100 seconds to update one when someone changes it outside of Vera.

Here’s the documentation I whacked up for it:
https://code.google.com/p/vera-litetouch-2000/wiki/Instructions

I also submitted it as a plugin, but it doesn’t appear to be up yet. It’s plugin number 5056. If you want to look at the files for this, you can grab them at the google code link above.

I’m happy to hear that you’ve got it working. Robbie Burns would approve. ;D

Any drawbacks to polling a device every 2 seconds? Would it hurt to go to 1 second? I have about 50 loads, so it takes up to 100 seconds to update one when someone changes it outside of Vera.
This is going to depend on Vera loading and the response time of your interface. I would think you want each query to complete before you issue the next one with some margin for peak Vera loading. You could make the poll delay a variable and change it from [b]Test Luup[/b] to see how it copes.

[quote=“RexBeckett, post:10, topic:177823”]I’m happy to hear that you’ve got it working. Robbie Burns would approve. ;D

Any drawbacks to polling a device every 2 seconds? Would it hurt to go to 1 second? I have about 50 loads, so it takes up to 100 seconds to update one when someone changes it outside of Vera.
This is going to depend on Vera loading and the response time of your interface. I would think you want each query to complete before you issue the next one with some margin for peak Vera loading. You could make the poll delay a variable and change it from [b]Test Luup[/b] to see how it copes.[/quote]

Right now, it’s working fine at 2 seconds, but this is currently the only thing I’m doing with my Vera. I just moved and left the last one behind as the HA system was one of the selling points of the house. Soon, I’ll have it connected to an Elk M1 Gold and some locks.

How do I add a variable that will automatically show up in the Advanced tab of my plugin?

It will be created when you write it with luup.variable_set(,,,).

Plugins usually create their variables in the initialization code. Typically, for each variable, the plugin will try a luup.variable_get(…) to get the last saved value. If the returned value is nil, the code issues a luup.variable_set with a default value.

You can create a new variable for a device at any time using luup.variable_set(…) or even from the advanced tab Add button (after entering the new service, name and value). You can also use any serviceID you like but it would be sensible to use the same one as for other variables in that device.

Note that it is not possible to remove a variable once added without deleting and recreating the device.