Confused about Lua variables (vs luup device variables)

So I’m decently adept with programming, I know a few different languages. Variables are a common thing in all of them.

But I’m very confused about variables in Lua and especially in Luup. Every time I look up variables and vera I get tons of hits – but they refer to device variables (i.e. z-wave configuration variables) and not programmatic variables. Does anyone have a primer anywhere on lua variables and specifically how they’re handled with vera? Specifically I’m looking for information on scoping; when variables are created how long do they persist, what is their scope, can I define different scopes (private/public/global), do they stay instantiated when you do a go away and come back call, your basic 4-1-1 on programmatic variables and scope.

The grand plan is that I’m looking to store a device’s state (on/off/color changing/etc.), go away for X seconds, then restore the device’s original state. The traditional way to do that would be to store the device’s original state in a variable, sleep (or cede control through a callback) for X seconds, then restore the device’s state. But without knowing when variables are available/destroyed/out of scope, can’t really figure out how I’d do that. (Timing isn’t critical, in case anyone is wondering. “vaguely around X seconds” is just fine.)

Thanks in advance!

Lua is Lua, even on Vera, so scoping works pretty much as you would hope. However Luup device variables are actually complex structures maintained and accessed through the Luup library extensions, and so essentially global in scope. On the whole, they also survive system restarts.

Only some Luup device variables have anything to do with Zwave, and they are best left to the internals of Luup, until you get very adventurous.

Thanks, but that really doesn’t tell me much of anything!

For example, let’s say I define a function inside a scene. Is that function available from other scenes? Is that function available from other scenes that affect other devices other than the original device? What about variables inside that function – are they global in scope, or are they in scope only inside that function? Or only inside that function for that device, and if I call that function on another device is another copy of those variables made? What about variables in that scene but outside of that function – are they in scope whenever lua runs, are they in scope only when that device is being considered?

There’s a lot of permutations here, and I really can’t find any information about what is in scope when with vera. I tend to write things and apply them many places; what I’m worried about is I write a function and apply it to the luup for RGB light 1 scene 1, and then go to paste the same code to RGB light 2 scene 2 and wind up clobbering things unintentionally because it has identical function and variable names!

And what about the idea of storing information for use later, as in my example case? What is the best method for doing that? Toss it in a lua variable and assume it’ll still be valid later?

All scenes and Lua startup share the same environment, so a global function, defined in startup will be available to all scenes. Local functions remain local to the scene.

Same with variables, but they don’t survive reloads. Only device variables are saved and restored across reloads.

Just to add to the confusion:

LUA is a “Just in time” type compiler. In other words, things only get compiled when they are needed.

A global function that is declared within a scene would therefore not exist until that scene is first run (after a reboot/LUA reload). From then on, that global function would be visible to other scenes.

That is why it is recommended to put global scenes in your LUA startup code section. The Start up code section will always be run when Vera restarts/LUA reloads, so you can be confident that the global function is accessible.

(Obviously you should not have multiple declarations with the same global function name. The compiler may not complain, but may not give you the results you expect.)

Thanks to both of you, the fog is starting to clear!

[quote=“aa6vh, post:5, topic:189840”]A global function that is declared within a scene would therefore not exist until that scene is first run (after a reboot/LUA reload). From then on, that global function would be visible to other scenes.

That is why it is recommended to put global scenes in your LUA startup code section. The Start up code section will always be run when Vera restarts/LUA reloads, so you can be confident that the global function is accessible.[/quote]

OK that makes sense (didn’t know Lua was a JIT, good things to know). But now I’m unclear on something… If I have a scene, and in the scene’s luup code I have:

-- start of luup code for scene
variable = "blah"
variable2 = "blahblah"

function Is_this_a_globally_accessible_function()
       variable3 = "blahblahblah"
end

Is “is_this_a_globally_accessible_function” globally callable, or only from within that scene? (If it’s global, I get the idea that it wouldn’t exist and therefore not be callable unless that scene has already been run at least once.) Pretty sure that variable3 should only exist within that function and not everywhere else, right? (whereas variable and variable2 should exist everywhere, again if the scene has been run at least once.) And if it is globally accessible like I suspect, how do I define a function that isn’t globally accessible?

Thanks in advance!

Declare it as local…

local function f(x)
  -- this is a locally accessible function
end

Take a look at the Programming in Lua book:
http://www.lua.org/pil/
and/or
https://www.google.co.uk/search?q=lua+5.1+reference&ie=utf-8&oe=utf-8&gws_rd=cr&ei=UepVVsulA8zXU76Mh6AG

Ah HA! The critical piece I was missing. Thanks!!

What he said, +

Yes, the function will be globally callable (after the scene has run once, of course).

variable3 is also visible globally. Its value will be null until the scene is run. However, if variable3 is specified elsewhere, it will have that leftover value. variable and variable2 will also be “visible”, and the values null, until the scene is run.

I am sure you are aware of the danger of re-using global variables, due to side effects. Always a good idea to always declare variables as “local”, unless there is a specific need to make them global. Then make sure the name is unique!

Perhaps everyone does this but I have found the following works for me.

I use “programmatic” variables (as soft switches) in my code to control logic flow (HVAC application). Declaring these in the start-up Lua code means they are global and can be accessed from any scene. They can also be set here with their initial values as they will not survive a reboot. I also place all other variables here regardless of where they will be used (except those that are obviously local to a scene) as well as all my functions even though they could be declared elsewhere and still have global status. It means I always know where to find them. I wrote my code some time back before the arrival of plugins that provide for managing variables through the Luup interface (e.g. Multistring) but the same principle applies (i.e. by putting a function that issues the Luup call in place of a programmatic variable name).

One other trick is to declare variables for devices Id’s and scene Id’s in the start up Lua and reference the variables in the scene code instead of the Id’s themselves (can also be used in Luup declarations). Not only does it make the code more readable but when you have to exclude/include any device (which will produce a new Id) you simply need to change the value of its variable even if you have multiple references to it perhaps in multiple scenes. One thing to be aware of though is that device Id’s must be declared as numeric and Scene Id’s as numeric literals (needs double quotes).

Basic stuff I know but if it helps anyone …

You may also find this object-oriented approach useful http://forum.micasaverde.com/index.php/topic,15138.msg115045.html#msg115045
as it can really improve readability of your code for when you come back to it later.