Undeclared/Uninitialized errors in LUA Activities

Hi guys,

Probably my lack of LUA knowledge here so please bare with me… I’ve got a bunch of variables and functions defined in my startup LUA file which are all accessible from my Vera scenes, no problem. I always assumed this was a good way of defining global params and functions and I’ve been doing this forever with great success.

Today I tried to take advantage of adding some LAU to some of my Reactor activities. The same function calls and references to variables from here though are failing similar to this:

01 02/27/19 18:51:00.141 luup_log:95: Reactor: "Initiate Home Mode" (185) runLua action: "scene__trip185_group1_action2" accesses undeclared/uninitialized global "getMultiSwitchStatus" <0x74756520> 01 02/27/19 18:51:00.142 luup_log:95: Reactor: "Initiate Home Mode" (185) runLua action: "scene__trip185_group1_action2" accesses undeclared/uninitialized global "DEVID_VERA_MULTISWITCH_1" <0x74756520> 01 02/27/19 18:51:00.144 luup_log:95: Reactor: "Initiate Home Mode" (185) aborting scene "__trip185" Lua execution at group step 2, Lua run failed: "[string \"scene__trip185_group1_action2\"]:3: attempt to call global 'getMultiSwitchStatus' (a nil value)" <0x74756520> 02 02/27/19 18:51:00.144 luup_log:95: Reactor: Lua: -- Enable lighting, heating and cooling local minLux = 5 local heaterOverride = getMultiSwitchStatus(6, DEVID_VERA_MULTISWITCH_1) if ((isNight()) or (isDark(DEVID_ENTRANCE_SENSOR_LUX, minLux)) or (isDark(DEVID_UPSTAIRS_RETREAT_SENSOR_LUX, minLux))) then setBinarySwitch(DEVID_KITCHEN_LIGHTS,1) setBinarySwitch(DEVID_RUMPUS_LEDS,1) setBinarySwitch(DEVID_LOUNGE_LAMP,1) setBinarySwitch(DEVID_RUMPUS_LAMP,1) end if (isWithinTempRange(DEVID_KITCHEN_HEATER, 0, VAR_HEAT_ON_TEMP_MIN)) then -- less than min temp threshold if (tonumber(heaterOverride) == 0) then -- override is off setThermostat(DEVID_KITCHEN_HEATER, "HeatOn", VAR_HEAT_SETPOINT) end end return true <

Any help appreciated.

Upload the L_Reactor.lua hotfix listed in this thread, then try again:

http://forum.micasaverde.com/index.php/topic,120160.0.html

Thanks for the reply. I applied the hotfix but this did not resolve the issue for me. Same “accesses undeclared/uninitialized global” error which results in all subsequent tasks after this failed LUA to be skipped as well.

OK. Sorry, I was reading too quickly here and completely spaced out on the part where you said these are defined in startup Lua.

Vera/Luup runs startup Lua in a different environment from plugins, so plugins do not have access to globals defined in startup Lua. They’re separate sandboxes. The easy solution to this is to copy the functions you need into the Run Lua activity.

The harder solution, but more “correct” and maintainable, is to put your functions into a module, and then use that module wherever you need access to those functions. You can use your module in startup Lua, scene Lua, Reactor Run Lua actions, anywhere.

For example, to make a module called “sm2117”, we create a file called “sm2117.lua” and move all of the function and variable/constant declarations out of startup Lua and into that file. Make sure any function or variable/constant you want to use is not declared with the local keyword (anything local is accessible from the code inside the module, but not outside).

Then, put the following line at the top of the file: module( "sm2117", package.seeall )

So now, your module file will contain something like this:

module( "sm2117", package.seeall )

DEVID_VERA_MULTISWITCH_1 = 123 -- you can define variables/constants too
DEVID_ENTRANCE_SENSOR_LUX = 456
DEVID_UPSTAIRS_RETREAT_SENSOR_LUX = 789
-- etc

function getMultiSwitchStatus( ...etc... )
    -- code 'n' stuff
end

function doSomethingElse( arg1, arg2 )
    -- more code 'n' stuff
end

Now, upload that file (sm2117.lua) to your Vera using the uploader at Apps > Develop apps > Luup files

Then, in your startup Lua, Reactor Run Lua, or anywhere else, you just:

local sm2117 = require "sm2117"
local heaterOverride = sm2117.getMultiSwitchStatus(6, sm2117.DEVID_VERA_MULTISWITCH_1)
if ((sm2117.isNight()) or (sm2117.isDark(sm2117.DEVID_ENTRANCE_SENSOR_LUX, minLux)) or (sm2117.isDark(sm2117.DEVID_UPSTAIRS_RETREAT_SENSOR_LUX, minLux))) then
   sm2117.setBinarySwitch(sm2117.DEVID_KITCHEN_LIGHTS,1)
   sm2117.setBinarySwitch(sm2117.DEVID_RUMPUS_LEDS,1)
   -- etc etc etc

Notice that each reference to a module variable or function has been prefixed with the module table name, which in this case, we made the same as the module name. If we had loaded the module using local XYZ = require "sm2117" then we would prefix our variable and function names with XYZ (e.g. XYZ.isNight()).

While this is more work to set up at first, the obvious benefit is that any change to a device constant or function applies to everywhere it is used throughout the system–you never need to worry if you updated every copy of a function, or every device number.

EDIT 2019-08-06: reformat for new forums

Wow, thank you for such a comprehensive answer! I will definitely apply the changes you’ve proposed.

Thanks so much!

Just a quick update on this. I followed your instructions and it all now works perfectly!

And thanks to your LuaView plugin, making the changes across all my scenes was a sinch!

Thanks for all your support.

I have same issue here so I just coded this… in run Lua
luup.call_action(“urn:micasaverde-com:serviceId:HomeAutomationGateway1”,“RunScene”,{SceneNum=“92”},0)

works great and a lot less hassle!