I generate a number of html reports (hosted on Vera) , which are created/update via a scene every x minutes.
Does anyone know of a way in which, when viewing the report I could re-run the scene ( to get the most up to date information ) by just reloading/refreshing the browser ?
If that’s not possible, what other options are there ?
If you define a short piece of code in Lua Startup, you could define a specific data request handler which would run every time you accessed that specific URL.
So, with this http_handler route (to be sure I understand) - i would move away from using scenes ? and need to run them differently, this time creating the html file within a dedicated function ?
function HTTP_reports ()
... my report generation code here..
end
global = {} -- 'global' table, call it whatever you like
luup.register_handler ("HTTP_reports", "dsc")
Then access it via…
http://veraip:3480/data_request?id=lr_dsc
As my code is currently creating html files (with html tables in) - how will that be presented via this new http-reports url ?
An alternative idea I’ve thought of is to have a url at the bottom of the report to re-run the scene?
I’ve updated the code as suggested, does all this have to go in the Lua startup area or can each report be stored (and run) separately as a module by putting the following into a .Lua file and uploading it to Vera ?
function HTTP_reports ()
local d, n
local html = {[[
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style type="text/css">
body {font-family: monospace;font-size: 13px; white-space: pre-wrap;}
.custom { font-size: 1em; font-family: Gill Sans Extrabold, sans-serif; padding:5px; border-collapse: collapse; border: 1px solid black; }
table { width:100% }
.th { width:50% }
</style>
</head>
<body>
<table class=custom>
<tr class=custom>
<th class=custom>Security Sensor</th>
<th class=custom>
Last Tripped</th>
</tr>
<br/>
]]}
local tt = {}
for n,d in pairs(luup.devices) do
if d.category_num == 4 then
local lasttrip = tonumber(luup.variable_get ("urn:micasaverde-com:serviceId:SecuritySensor1", "LastTrip", n) or os.time())
local timeString = os.date(" %Y/%m/%d - %X", lasttrip)
if lasttrip > 0 then
table.insert(tt, { devnum=n, last=lasttrip, ltime=timeString })
end
end
end
table.sort(tt, function(a,b) return a.last > b.last end) -- sort highest to lowest
for n,d in ipairs(tt) do
html[#html+1] = "<tr class=custom><td class=custom>" .. luup.devices[d.devnum].description .. "</td><td class=custom>".. d.ltime .. "</td></tr>\n"
print (d.ltime .. ' : ' .. luup.devices[d.devnum].description .. " Sensor was last tripped")
end
return table.concat(html), "text/html"
end
global = {}
luup.register_handler ("HTTP_reports", "dsc")
In this case, nothing. It’s a left over from the piece of code you copied it from. It was useful there, but not used by you here.
I’d make a couple more points, so that you don’t unnecessarily duplicate effort:
All your reports can be generated (separately) by one handler if you add a parameter such as `&report=dsc’ to the request. The handler has to parse this parameter and then dispatch the appropriate function to generate the output. The header and style information would be shared between reports.
local function hue_rep()
-- whatever needed to consruct report HTML
return report_html
end
local function dsc_rep()
-- whatever for this report, etc...
end
function HTTP_reports (_, params)
local reports = {hue = hue_rep, dsc = dsc_rep, lasttrip = last_rep, lights = light_rep}
local fct = reports[params.report] or dsc_rep -- dsc is default if not specified
return fct, "text/html"
end
Your loop which builds each line of the report would be much clearer (and more efficient) if written like this:
local line = [[
<tr class=custom>
<td class=custom>%s</td>
<td class=custom>%s</td>
</tr>
]]
for n,d in ipairs(tt) do
html[#html+1] = line: format (luup.devices[d.devnum].description, d.ltime)
end
Ok, so does that mean I start each function after the header/style part?
This section is the default for all…
function HTTP_reports ()
local d, n
local html = {[[
<html>
<head>
<title>Vera Last Trip</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="refresh" content="10">
<link rel="icon" type="image/png" href="https://community.getvera.com/uploads/default/optimized/3X/4/1/41fe9abf0b738352cb5bb34abfe0c22d2e3ef100_2_32x32.png">
<style type="text/css">
body {font-family: monospace;font-size: 14px; white-space: pre-wrap;}
.custom { font-size: 1em; font-family: Gill Sans Extrabold, sans-serif; padding:5px; border-collapse: collapse; border: 1px solid black; }
table { width:100% }
.th { width:50% }
</style>
</head> ]]}
And then for each one begin with the html body to record the different column headers ?
local function dsc_rep()
local html = {[[ <body>
<table class=custom>
<tr class=custom>
<th class=custom>Security Sensor</th>
<th class=custom>Last Tripped</th>
</tr>
<br/>
]]}
local tt = {}
-- rest of the code here ... etc...
end
Well, it all depends. I imagine that your other report functions will want to write a similar table header, so you could abstract out a function which had the column headers as a parameter.
What overall structure were you planning to put the routines together?