Variable_set inside scene running by interval invokes request=user_data on each interval

Hello,
I’m not sure if this is ok, but seems like setting values via lua code inside a scene running on an interval forces the engine to invoke a new user_data request. Is this normal?

Example:

I have a scene that runs every second to check the content of a file in a home directory. it looks something like this:

local file = "cat /home/userdir/cecstatus"
local handle = io.popen(file)
local result = handle:read("*a")
result = string.gsub(result, "%s+", "")
luup.log(result)
handle:close()
    if result=="on" then
        luup.log("Turning ON VSwitch")
        luup.variable_set("urn:upnp-org:serviceId:SwitchPower1", "Status", 1, 91)
        luup.variable_set("urn:upnp-org:serviceId:VSwitch1", "Status", 1, 91)
    else
        luup.log("Turning OFF VSwitch")
        luup.variable_set("urn:upnp-org:serviceId:SwitchPower1", "Status", 0, 91)
        luup.variable_set("urn:upnp-org:serviceId:VSwitch1", "Status", 0, 91)
    end

luup.variable_set is called every second and ALTUI requests a new user_data every second as well. the moment I turn off the scene, everything goes back to normal. If I modifying the conditional statement to something like this:

local VSwitch_Status = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", 91)
local file = "cat /home/userdir/cecstatus"
local handle = io.popen(file)
local result = handle1:read("*a")
result = string.gsub(result, "%s+", "")
luup.log(result)
handle:close()
    if (result=="on" and VSwitch_Status=="0") then
        luup.log("Turning ON VSwitch")
        luup.variable_set("urn:upnp-org:serviceId:SwitchPower1", "Status", 1, 91)
        luup.variable_set("urn:upnp-org:serviceId:VSwitch1", "Status", 1, 91)
    else
        luup.log("Turning OFF VSwitch")
        luup.variable_set("urn:upnp-org:serviceId:SwitchPower1", "Status", 0, 91)
        luup.variable_set("urn:upnp-org:serviceId:VSwitch1", "Status", 0, 91)
    end

ALTUI would only request a new user_data when the conditional statement is valid. which makes believe that luup.variable_set could be the cause new user_data request.

Any ideas?

The user_data and status requests offer the ability to get “deltas” from previous requests, so their responses in circumstances like this would normally be much smaller–ALTUI isn’t asking for or getting a full system response each time, just what changes. That said, it still takes work to figure out the deltas, generate the response, parse the response on the other end, etc. You can (should?) optimize your code so that it doesn’t set the switch status to a status it already has–no need to set it to 0 or 1 if it’s already there. That will prevent the variable from being updated (timestamp) and the resulting no-change delta being generated for the user_data or status request response.

2 Likes

Hi,

Like rigpapa says many of us use a little wrapper for setting variables that only do the set command when
changed. Also reduces writing to the vera log file. Something simple like this:

	-- Set variable value
	local function _set(name, value, sid, device)
		local old, ts = luup.variable_get(sid, name, device) or ""
		if (tostring(value) ~= tostring(old)) then 
			luup.variable_set(sid, name, value, device)
		end
		return true
	end

Cheers Rene

1 Like

Hello Ron

This, in fact, is not what is causing the user_data request… it is, I believe, the fact that the scene is run.

Vera, and so openLuup, maintains two system-wide version numbers. Here’s their definition lifted from openLuup source code:

local dataversion = {value = initial_dataversion}             -- updated as data changes
local userdata_dataversion = {value = initial_dataversion}    -- updated as device/service/variable structure 

These are there to support the (somewhat baroque, not to say broken) lazy polling implementation done by the combination of the user_data and status requests. Setting a variable value updates dataversion so that that change will appear in (and trigger) a response to the status request. However, some data (quite a lot, in fact) are not included in that response, so things which need more significant updates increment the userdata_dataversion which triggers AltUI to issue a user_data request.

Again dipping into the openLuup source code, I see:

  devutil.new_userdata_dataversion ()       -- 2016.11.01

when a scene is run, so this ‘feature’ has been there for a while. The reason it is there is to ensure that AltUI updates the last/next scene run times. It may well be that I have not faithfully replicated Vera’s behaviour here, but I lost many days of development running tests to try and understand Vera’s behaviour, and this is what I ended up with. It is possible that a more sophisticated version of the status request response may work around this, but, quite honestly, I don;t have the appetite for that at the moment.

This does highlight a point, though: having AltUI running in a browser if you’re not using it does consume significant cpu and I/O resources. Whilst AltUI is absolutely amazing, I wouldn’t use it day to day for running the system (I normally let the automation get on with it, and use scene controllers for manual control.) As network bandwidth has massively increased, there is less and less advantage, in fact positive dis-advantage in client-side UI processing, particularly when it requires a very significant amount of state information to be kept up to date from the remote system. This is abundantly clear if you use openLuup’s console interface, which although far less capable than AltUI, is implemented server-side and significantly faster because it has all the state information it needs to hand.

Your example code, though, prompts a number of questions:

  • why are you spawning another process to read a file and pipe you the result, rather than opening it directly?
  • why are you reading the file at all, when you could simply be checking its attributes to see whether it has been updated, using the LuaFileSystem call attributes() ?
3 Likes

I was trying to reduce the unresponsive time the engine could take opening and capturing what’s inside the file.

Great idea. I will do that. Thanks

At least now I know setting the value of a variable using luup.variable_set inside a scene could lead to bigger problems while running ALTUI on a browser until lu_status gets improved.

Thanks @rigpapa @reneboer @akbooer for the input.

Did you actually benchmark that? I’d be surprised if it was much of an issue. Anyway, you will certainly save much more time by only opening when necessary.

Well, confirmed that is not luup.variable_set that causes the user_data request. it is the interval itself on the scene, just as @akbooer described above. so any scene with timers will cause ALTUI to send a user_data request. if the timer is set to run the scene to often it will definitely become a problem.

Just asking generically, then, what is a good / safe lower limit for the delay between firing:

a. The same Scene, repeatedly?
b. Multiple Scenes in succession?
c. Any Scene which contains delayed actions?

I realize this is an openluup board, but think it’s a fair question for all Vera users, and one to be mindful of when designing workflows in general.

My personal experience has been that the limiter has always been the vera’s zwave API and the inability of the luup engine to manage the command queue properly causing collisions and congestions then crashes. For openLuup, my guess is that it depends a lot on what hardware you run it on.

if user_data is too large (above 1mb) and there is a scene interval of 1 second with 2 browsers open… the engine will experience blockage for sure.

This might very well be mechanism for one of the rare lockups I observed with openLuup…

IMHO, scenes are not the mechanism to use if you want to run something every second anyway. You have at least three other options:

  1. Delay callbacks
  2. Timer callbacks
  3. Jobs (as part of action requests)

In openLuup, you can also create jobs dynamically, quite separately from the anything in the implementation .xml file. Jobs have the capability to suspend and reschedule themselves.

I really think you shouldn’t push a feature beyond the limits of what it was designed to do.

3 Likes

Very true, although it is tempting for unaware users to create this type of scenario.

1 Like