To help analyse scene/device interaction, I use this piece of code which scans all scenes for connected devices: both devices which trigger the scene, and devices which are actioned by the scene. It writes a file /www/scene_devices.txt which can be examined from a web browser using http://your-vera-ip-address/scene_devices.txt and gives an output like:
SCENES:
[2] "Barn All Off"
actions = {[151] Far Beam, [172] Near Beam, [173] Chandelier, [178] Standard Lamp, [185] Kitchen, [190] Dining Table}
[3] "Good Night"
actions = {[146] Bedside 1, [147] Bedside 2, [187] Bedroom Ceiling, [199] Table Lamp}
[5] "Apple TV Off"
actions = {[225] Apple-TV-Barn}
[89] "TEST"
+ Lua code
triggers = {[181] Study Ceiling}
actions = {[268] Smtp Notification}
Each scene has a scene number/name, as does each device. I’ve found this helpful in tracking down scene-related errors. What it can’t do is detect any interactions between devices and Lua code (in scenes, triggers, or other devices like PLEG), although it does flag the presence of Lua code attached to scenes.
Code appended below. Simply cut and paste into “Test Luup code” and press go, then head to another browser window to inspect the result. You could also put it into a scene’s Luup code and run it on demand. Note that there is one dependency: it requires a json package - this may involve a change to the first line json = require “json”. For testing I use the pure-Lua package dkjson from [url=http://dkolf.de/src/dkjson-lua.fsl/home]dkjson - dkjson, but if you have an app which already loads its own json package you may be able to use that (for example, dataMine has one, so writing json = require “json-dm” works just fine.)
Hope this helps.
json = require "json"
-- Build list of scenes with trigger devices and actioned devices
--
-- version = "2013.06.20 @akbooer"
--
-- SET and LIST utility functions: map, flatten, and set
-- classic map utility - cf. pairs
local function map (Xs , fct) -- map function to each item in table, returns {} if none
local table = {}
for i,x in pairs (Xs or {}) do table[i] = fct(x) end
return table
end
-- classic list flatten
local function flatten (array)
local l = {}
local function add_item (x) l[#l+1] = x; end
for _,x in ipairs(array) do
if type(x) == "table" then
map(flatten(x), add_item )
else
add_item (x)
end
end
return l
end
-- set operations, only what we need here: add, list
local function set() -- create new empty set
local s = {} -- holder for set
return {
add = function (x) s[x] = x; end, -- add element to the set
list = function ( ) -- return sorted list of set elements
local l = {};
for i in pairs(s) do l[#l+1] = i; end;
table.sort (l);
return l; end
}
end
-- formatting functions for printing data structure
local function format_devices(d)
return map (d, function (x) return string.format ('[%d] %s', x, (luup.devices[tonumber(x)] or {description = ''}).description); end)
end
local function format_triggers (t)
if #t == 0 then return '' end
return table.concat {' triggers = {', table.concat(format_devices(t), ', '), '}\n' }
end
local function format_actions (t)
if #t == 0 then return '' end
return table.concat {' actions = {', table.concat(format_devices(t), ', '), '}\n' }
end
local function format_lua (lua)
if not lua then return '' end
return ' + Lua code \n'
end
local function scene_tostring (s)
return string.format('[%d] "%s" \n%s%s%s ', s.id, s.name, format_lua(s.lua), format_triggers(s.triggers), format_actions(s.actions) )
end
-- functions to build data structure of devices triggering scenes, and actioned by scenes
local function get_device (x) return x.device end
local function trigger_devices (t)
local trigger_set = set() -- create a new empty set (of device numbers)
local device_list = map (t, get_device) -- create list of device numbers
map (device_list, trigger_set.add) -- add elements to set
return trigger_set.list () -- return sorted list of set members
end
local function action_devices (groups)
local action_set = set() -- create a new empty set (of device numbers)
local function actions (g) return map (g.actions, get_device) end
local action_list = map (groups, actions) -- create list of actions
map (flatten(action_list), action_set.add) -- mash together all the action device lists
return action_set.list () -- return sorted list of set members
end
local function attached_devices (sceneNo)
local _, s = luup.inet.wget("http://127.0.0.1:3480/data_request?id=scene&action=list&scene=" .. sceneNo)
if s == "ERROR" then return end
s = json.decode(s)
return setmetatable ({
id = s.id,
name = s.name,
lua = not not s.lua, -- double negative ensures boolean return, not Lua string itself!
triggers = trigger_devices (s.triggers),
actions = action_devices (s.groups) ,
},
{ __tostring = scene_tostring} )
end
-- main: build and write the database
local filename = "/www/scene_devices.txt"
local file = io.open(filename, "w")
if file then
luup.log ("Opening: " .. filename)
file:write '\nSCENES: \n\n '
for i in pairs (luup.scenes) do
scene_devices = attached_devices (i)
file:write( tostring(scene_devices) )
end
file:close()
luup.log ("Closing: " .. filename)
else
luup.log ("Failed to open: " .. filename)
end