Save state between scenes

I have two scenes one that runs when my Movie Projector starts and one when it shuts down.

The starting script I will turn off all lights that are on could be done by polling

luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", deviceId) and if its on call

luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget", {newTargetValue = "0"}, deviceId)

To turn it off

Problem is I need to save an array with the deviceIds that was on. And then from the projector shut down scene I need to access this array and turn the lights back on.
How can I save state between scenes? It does not need to survice power failure to controller etc.

Thanks, Anders

This does the trick

First the script that turns off lights, devices is a list of ids. A global array movieLights is also defined and all turned on lights in the devices array are pushed to it.

local devices  = {19}
movieLights  = {}

for i, device in ipairs(devices) do
   if luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", device) == "1" then
      table.insert(movieLights, device)
      luup.call_action("urn:upnp-org:serviceId:SwitchPower1", "SetTarget", {newTargetValue = "0"}, device)      
   end
end

And here is the script that resumes the lights

for i, light in ipairs(movieLights) do luup.call_action("urn:upnp-org:serviceId:SwitchPower1", "SetTarget", {newTargetValue = "1"}, light) end

This seems ridiculously complicated. Every time I look at one of these scripts I feel like I’m semi-retarded.
I was wondering if you could help me grasp this as it’s been so long since I did any real Lua scripting (like 10 years or something). I have one project that I’m currently trying to accomplish, though it seems that the shortfalls of the Vera may prevent any progress whatsoever. I’d like to cycle through scenes using tap events and tap-and-hold events on a Wallmote Quad. Unfortunately, it seems that no events are registered even when I’m 10 feet from the vera with the device.
In any case, it would be nice to figure out the coding in the event that the thing starts working as my Homeseer motion sensor did out of the blue, 2 days after I set it up.

This solution also won’t work across a Vera reload or reboot, if that happens while you’re watching a movie. To address that, you need to save the movieLights table to state somewhere:

-- Save the movieLights table in my private service on device 99 (projector?)
luup.variable_set( "urn:mydomainname-com:serviceId:MyServiceName", "MovieLights", table.concat( movieLights, "," ), 99 )

...

-- Get the movieLights table from my private service
str = luup.variable_get( "urn:mydomainname-com:serviceId:MyServiceName", "MovieLights", 99 ) or ""
movieLights = {}
str:gsub( "([^,]*),", function( m ) table.insert( movieLights, tonumber(m) ) return "" end )
if str ~= "" then table.insert( movieLights, tonumber( str ) ) end

This saves the table as a comma-separated list (string), but it’s kind of a pain to undo that, as you can see. It simplifies the code to use JSON, at a small expense of more memory use to do the module loading:

[code]json = require(“dkjson”)
– Save the movieLights table in my private service on device 99 (projector?)
luup.variable_set( “urn:mydomainname-com:serviceId:MyServiceName”, “MovieLights”, json.encode(movieLights), 99 )

– Retrieve the movieLights table
str = luup.variable_get( “urn:mydomainname-com:serviceId:MyServiceName”, “MovieLights”, 99 ) or “{}”
movieLights = json.decode( str ) or {}
[/code]

Note that this basically ignores any errors that might pop up in JSON decoding, but if the stored value is only touched by this code, there should never be any such errors. If an error does occur, this code just produces an empty table (no crash).

[quote=“rigpapa, post:4, topic:200032”]This solution also won’t work across a Vera reload or reboot, if that happens while you’re watching a movie. To address that, you need to save the movieLights table to state somewhere:

-- Save the movieLights table in my private service on device 99 (projector?)
luup.variable_set( "urn:mydomainname-com:serviceId:MyServiceName", "MovieLights", table.concat( movieLights, "," ), 99 )

...

-- Get the movieLights table from my private service
str = luup.variable_get( "urn:mydomainname-com:serviceId:MyServiceName", "MovieLights", 99 ) or ""
movieLights = {}
str:gsub( "([^,]*),", function( m ) table.insert( movieLights, tonumber(m) ) return "" end )
if str ~= "" then table.insert( movieLights, tonumber( str ) ) end

This saves the table as a comma-separated list (string), but it’s kind of a pain to undo that, as you can see. It simplifies the code to use JSON, at a small expense of more memory use to do the module loading:

[code]json = require(“dkjson”)
– Save the movieLights table in my private service on device 99 (projector?)
luup.variable_set( “urn:mydomainname-com:serviceId:MyServiceName”, “MovieLights”, json.encode(movieLights), 99 )

– Retrieve the movieLights table
str = luup.variable_get( “urn:mydomainname-com:serviceId:MyServiceName”, “MovieLights”, 99 ) or “{}”
movieLights = json.decode( str ) or {}
[/code]

Note that this basically ignores any errors that might pop up in JSON decoding, but if the stored value is only touched by this code, there should never be any such errors. If an error does occur, this code just produces an empty table (no crash).[/quote]

Good idea! You could also read the list of lights you want to be affeced the same way, that way you can edit the variable list for that device instead of editing the script

[quote=“Quixote, post:3, topic:200032”]This seems ridiculously complicated. Every time I look at one of these scripts I feel like I’m semi-retarded.
I was wondering if you could help me grasp this as it’s been so long since I did any real Lua scripting (like 10 years or something). I have one project that I’m currently trying to accomplish, though it seems that the shortfalls of the Vera may prevent any progress whatsoever. I’d like to cycle through scenes using tap events and tap-and-hold events on a Wallmote Quad. Unfortunately, it seems that no events are registered even when I’m 10 feet from the vera with the device.
In any case, it would be nice to figure out the coding in the event that the thing starts working as my Homeseer motion sensor did out of the blue, 2 days after I set it up.[/quote]

It doesnt help that Lua is a pretty backward language :smiley: In C# a foreach loop (Iterate over every item in a collection)

foreach(var item in items) 
{
}

Translates to this in lua

for i, item in ipairs(item) do
end

Or adding a item in C#

items.Add(myItem);

Translates to some static method mumbo jumbo

table.insert(items, myItem)

Though, any language support it better than no language support! Python would have been a better choice though in my own opinion

Lua is purpose-designed as an embedded language. It makes some syntactic trade-offs to keep implementation cost and resouce demand low, but it’s still quite powerful, once you get to know it. It’s a far more appropriate choice for a platform like this than either C# or Python, IMO, especially if you look at what most people do on the platform (write short script-like stubs to do simple tests and actions). Vera didn’t do the best job of building their Luup interface into it, or evolving it over the years, and as a very active developer in this community (and separately many other projects in C/C#/C++, Python, Java, JS family and others), I have many more issues with that than I do with Lua itself.

Thanks to the Roslyn project you can purpose fit C# for anything. But I dont have a problem with Lua, as a developer I can use any language. But Lua does have its quirks. :smiley:

edit: also pretty interesting how Lua handles array capacity :smiley: optimization - How do you pre-size an array in Lua? - Stack Overflow

I had the same problem. Thank you)