Consolidate all your Lua scene code into one location.

[ul][li]Lost track of what all that Lua code does in your scenes after a few months?[/li]
[li]Do you have miscellaneous Lua code remnants hanging around in your scenes as part of some failed experiment from years ago?[/li]
[li]You reinstalled a plugin and now you have to find and update the plugin’s IDs used in the Lua code throughout your scenes?[/li]
[li]Do your scenes contain wasteful duplicate Lua code?[/li]
[li]Reckon you could do more, if you could just visualize your scene code a bit more easily?[/li]
[li]Can’t see the forest for the trees?[/li][/ul]

Well how about consolidating all your Lua scene code into one location?

The following framework allows this to be done and builds on a couple of other posts:

http://forum.micasaverde.com/index.php/topic,28804.msg206166.html#msg206166
http://forum.micasaverde.com/index.php/topic,12963.msg95662.html#msg95662

Please proceed carefully as this involves extensive changes to your Vera. Code tested on UI5 and UI7.

Step 1:
Download the attached “L_MyLuaCode frame work.lua” and rename it to: “L_MyLuaCode.lua”

You modify the attached L_MyLuaCode.lua framework to suit your existing scenes. You will make a new function for every scene and transplant your existing Lua scene code into that function. In the example code these functions are named by combining the scene room name with the actual scene name, so they can be more readily recognized at a later date eg

Entrance_Lights_on_for_10_min Lounge_Standard_lamp_on_for_10_mins

All of these functions must return true or false. If false is returned, the scene is aborted, if true the rest of the scene commands will be executed. Refer to this diagram:

http://wiki.micasaverde.com/index.php/Luup_Scenes_Events#Adding_Lua_code_to_scenes_and_events

Make one function for each of your scenes, with the code for each scene, moved into each function:

local function Some_room_Some_scene_name() -- INSERT YOUR EXISTING SCENE CODE HERE - ONE FUNCTION FOR EACH SCENE return XYZ -- your scene should always return either true or false end

If your scene has no associated Lua code, then a place mark function that does nothing is used, ready for any future expansion or code modifications eg

local function Office_Printer_on_for_30_mins() -- turn the printer on for 30 minutes return true end

Here is a simple function where a light can only be turned on at night time:

local function Lounge_Standard_lamp_on_for_10_mins() -- only allow the light to go on at night time return luup.is_night() end

Step 2:
We have to link the scenes to the new functions. In the function createSceneNumberTable, in the file L_MyLuaCode.lua, you have to fill out the jump table - one line per scene.

sceneFunctions[Your_scene_number] = Some_room_Some_scene_name

Do it in alphabetical order for clarity, eg:

sceneFunctions[46] = Lounge_Standard_lamp_on_for_10_mins sceneFunctions[22] = Office_Printer_on_for_30_mins sceneFunctions[36] = Unused_TEST

Modify all the scenes to use this new arrangement:

  1. Cut & paste the existing scene Lua code into a new function as just described above. One per scene.

  2. Having moved the existing scene code for all scenes into L_MyLuaCode.lua, insert this line into every scene and replace xx with the associated scene number. The scene will then be linked to the scene function via the jump table in L_MyLuaCode.lua:

return myLua.executeSceneNumber(xx)

Step 3:
Upload your modified L_MyLuaCode.lua using the command: APPS → Develop Apps —> Luup files
Using the command: APPS → Develop Apps —> Edit Startup Lua insert the following line to initialize the L_MyLuaCode.lua code:

myLua = require("L_MyLuaCode")

Notes:

  1. Numerious Luup engine restarts and browser refreshes will be required to get everything settled in. In the interim your house will be in chaos - be careful. You could alter each scene one by one to try things out first.

  2. You can check functionality by running each scene and looking at the log file. Log entries are preceded by “My Lua ver 0.xx debug:” If you experience problems with a scene you can add in logging code, into the associated function for that scene, to check further.

  3. you can consolidate all your plug in IDs, eg:

local SONOS_POWER_SOCKET_IN_LOUNGE_ID = 39  -- power on/off for SONOS in lounge
  1. and consolidate your service IDs as well, eg:

local SWITCH_SID = "urn:upnp-org:serviceId:SwitchPower1" local SONOS_PLAYER_SID = "urn:micasaverde-com:serviceId:Sonos1"

  1. WARNING - scenes that use code that access global variables need to be handled more carefully. The functions in L_MyLuaCode.lua are not Global. So for example, attempting to execute this:
luup.call_delay("myLua_a_function_in_our_file", DELAY_5_SECONDS)

results in the log entry : “attempt to call global ‘myLua_a_function_in_our_file’ (a nil value)”
To make this work; the reference to myLua_a_function_in_our_file must be inserted into the Global symbol table during initialisation, eg:

_G["myLua_a_function_in_our_file"] = myLua_a_function_in_our_file

See the example in the attached example L_MyLuaCode.lua in the “globaliseTheseFunctions”. This is a total hack but I’m not aware of any alternative.

  1. when finished you should be able to delete the demonstration code.

  2. there are probably other and potentially better ways of implementing this code?

Thank you sir for your time and effort! I’ve clipped this to my Evernote for future reference. I am in the process of getting rid of some scenes and moving to PLEG but this information is still very helpful, especially to a newb like me.

This would be SO much easier if only there was a global variable somewhere which told you the number of the currently executing scene/trigger. But sigh I don’t think there is.

Great tip @a-lurker, thanks! I have a lot of LUUP code scattered around, so this will come in handy.

I agree that would be handy to have. But you can simulate such a feature yourself, by adding a LUA statement to each scene that sets a global value. Then you could use the scene name instead, to make it more readable.

Of course scene execution is a momentary event, so the variable would actually reflect the last scene run.