deviceData to JSON file
Posted: Saturday 06 October 2018 2:45
Based on an idea from @devros while working with micropython, I built a dzVents script that collects information from domoticz devices and stores the information in a file on OS level in JSON format where it can be used by other processes and systems. Explanation and prerequisite in the scripts comment.
Thx to @devros for the idea, testing and the sort function.
Have fun !
Thx to @devros for the idea, testing and the sort function.
Have fun !
Code: Select all
--[[
This script collects information from domoticz devices and stores the information in a file on OS level in JSON format.
default ascending sorted on the idx key but can be sorted on a different key, direction.
Before making this script active you should first create a uservariable type string, named myCollection.
The name and value of this variable are case sensitive and the value must follow this lay-out:
{"counter":[133],"counterToday":[133],"temperature":[1030,892,842],"state":[1054,583,650],"humidity":[115,113],"WhTotal":[704],"text":[1056,1057]}
where the strings are the type of information you want to collect and the comma separated numbers inside []
are the device index numbers from where you want to get the values from. You do not have to use all so
{"counter":[133],"counterToday":[],"temperature":[1030,892,842],"state":[1054,583,650],"humidity":[115,113],"WhTotal":[704],"text":[1056,1057]}
or
{"counter":[133],"counterToday":[133],"temperature":[1030,892,842],"humidity":[115,113],"WhTotal":[704]}
are also valid.
For additional informationTypes please look at the dzVents wiki.
as example if you want to add the setpoint values of device number 987 and 986 the last example would become
{"setPoint":[987,986],"counter":[133],"counterToday":[133],"temperature":[1030,892,842],"humidity":[115,113],"WhTotal":[704]}
]]--
return {
on = { timer = { "at *:23" }}, -- every hour at minute 23. adjust to your needs
logging = { level = domoticz.LOG_DEBUG, -- Comment this and the next line if script execute as expected
marker = "createJSON" },
execute = function(dz)
-- modify these vars to suit your requirements
local myFile = "www/my.json" -- the file that will receive the sorted JSON (relative from base domoticz directory)
local sortField = "idx" -- Set to "idx","name","type" or "payload" if you want the json sorted on that key or set to nil
local sortDirection = "ascending" -- defaults to "ascending" can be set to "descending"
-- *********
-- ********* It should not be needed to modify anything below this line.
-- ********************************************************************************************************************************************
-- initialize Lua variables as tables
local myDevices, myData = {}, {} -- init both as empty tables
-- multi purpose data formatter
local function format(device,dataType)
local content = device[dataType] -- device.datatype does not work because dataype will than be interpreted as string
if content == nil then content = "nil"
elseif dataType == "temperature" then content = dz.utils.round(content,3)
elseif dataType == "counterToday" then content = string.match(content, "%d+.%d*") or 0 -- remove kwH / m3 from string and keep the number
elseif type(content) == "number" then content = dz.utils.round(content,3)
end
return content
end
-- convert table to JSON and write to file
local function dumpTable2JSON(t,out)
file = io.open(out, "w+") -- Open file for (over)write
file:write(dz.utils.toJSON(t))
file:close() -- close the opened file
end
-- sort the table based on user set key and direction
local function sortTable(t,validSet)
if validSet[sortField] then
if sortDirection ~= nil and sortDirection:sub(1,3):lower() == "des" then
table.sort(t, function(a,b) return a[sortField] > b[sortField] end) -- as advised by @devros
else
table.sort(t, function(a,b) return a[sortField] < b[sortField] end)
end
else
dz.log("Warning !! " .. sortField .. " is not a valid sortfield. JSON is still unsorted",dz.LOG_ERROR)
end
end
-- do everything :-)
local function processCollection(myDevices)
for attribute in pairs(myDevices) do -- loop trought the informationTypes
for key,index in ipairs(myDevices[attribute]) do -- loop through the devicenumbers
if dz.devices(index) then -- Hope they exist as device
dz.log("Type: " .. attribute .. "; idx: " .. index .. " ===> " ..
dz.devices(index).name or "N/A" ,dz.LOG_INFO)
table.insert(myData,{ idx = index, -- populate the result table
name = dz.devices(index).name,
type = attribute,
payload = format(dz.devices(index),attribute) })
else
dz.log("Type: " .. deviceValue .. "; idx: " .. index .. " ===> N/A" ,dz.LOG_INFO)
end
end
end
-- should we sort ?
if sortField ~= nil then
local validKeys = { idx=true, name=true, type=true, payload=true }
sortTable(myData,validKeys)
end
end
-- Main code
processCollection(dz.utils.fromJSON(dz.variables("myCollection").value))
dumpTable2JSON(myData,myFile)
end
}