Page 1 of 1

deviceData to JSON file

Posted: Saturday 06 October 2018 2:45
by waaren
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 !

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
}

Re: deviceData to JSON file

Posted: Saturday 06 October 2018 19:34
by devros
Thanks waaren, very usefull :)
Im using this script together with M5stack and micropython to get domoticz data (is in one file so its faster a easier).

just

Code: Select all

	
	url = urequests.get(url='http://xxx. xxx. xxx. xxx:8080/m5.json')
	url_json = url.json()
	
	temp_out = (url_json[2]["payload"]) # temp