Get online airquality data  [SOLVED]

Moderator: leecollings

User avatar
waltervl
Posts: 5148
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: Get online airquality data

Post by waltervl »

Or the OpenAQ plugin, works perfectly.

viewtopic.php?f=65&t=22092
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
mojso
Posts: 86
Joined: Friday 08 November 2019 23:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Get online airquality data

Post by mojso »

Hi, I have a question again, the script works great,

Can it be done in the script
if the rgb light is turned off, the command to change the color will not be sent

Code: Select all

   
 
--[[
data from http://waqi.info/
An API key is required and can be aquired here ==> http://aqicn.org/data-platform/token/

Based on the original idea and script from @elmortero

http://api.waqi.info/feed/geo:51.852062;4.507676/?token=Your_apikey = Zwartewaalstraat, Rotterdam Zuid
http://api.waqi.info/feed/geo:51.986119;4.934413/?token=Your_apikey = Lopik (co)
http://api.waqi.info/feed/geo:51.867238,4.354981/?token=Your_apikey = Leemkuil (so2)
]]--

return {
    on =    {  
                timer           = { "every 30 minutes" },
                httpResponses   = { "waqi*" }                            -- matches callback wildcard 
            },
        
        data    =   {   
                        safedMessage = { history = true, maxItems = 100 , maxHours = 168 }
                    },
        
        logging =   {   level   =   domoticz.LOG_DEBUG,
                        marker  =   "Waqi" },
    
    execute = function(dz, triggerItem)
        
        local apiKey            = "my api"
        local defaultLocation   = "my location"
        local sensorType
        local colorDevice = dz.devices('desk light')
        if dz.data.safedMessage.get(1) == nil then
            dz.data.safedMessage.add("Init") 
        end
        
        local geo   = { nearby  = defaultLocation,        -- to get station closest to your home 
                        so2     = "",   -- if value for this item cannot be obtained from "nearby"
                        co      = "",   -- else keep this as an empty string
                        pm25    = "",
                        pm10    = "",
                        o3      = "",
                        no2     = "",
                        aqi     = "",
                        p       = "", --barometer
                        w       = "",
                       -- wg       = "",
                      }  
                      
        local sensors = {   so2     = { sensor = 62,  alert = 63 },   -- enter device index Numbers or 0 for sensor and alert "
                            co      = { sensor = 64,  alert = 65 },
                            pm25    = { sensor = 66,  alert = 67 },
                            pm10    = { sensor = 68,  alert = 69 },
                            o3      = { sensor = 70,  alert = 71 },
                            no2     = { sensor = 72,     alert = 73 },
                            aqi     = { sensor = 76,  alert = 75  , aqiSensor = 74},      -- additional Air Quality sensor
                            p       = { sensor = 647, alert = 0 }, --barometer
                            w       = { sensor = 656, alert = 0 }, 
                           -- wg       = { sensor = 657, alert = 0 },
                            
                        }
       
        local sensorTypes = { alert = "Alert", aqi = "Air Quality", custom = "Custom Sensor" } 
        
        local function responseType(str)   -- strip waqi_ from string
            return str:gsub("waqi_","")
        end
       
        local function setColor(value, device) 
            local colors =  {
                                green =  {min = 0, max = 50, red = 0, green = 255, blue = 0},
                                yellow = {min = 51, max = 100, red = 255, green = 255, blue = 0},
                                orange = {min = 101, max = 150, red = 255, green = 165, blue = 0},
                                red    = {min = 151, max = 200, red = 255, green = 0, blue = 0},
                                purple = {min = 201, max = 300, red = 128, green = 0, blue = 128},
                                maroon = {min = 301, max = 999999, red = 128, green = 0, blue = 0},
                            }
            for color, control in pairs(colors) do
                if value > control.min and value <= control.max then
                    device.setColor(control.red, control.green, control.blue, device.level)
                    device.dimTo(device.level).afterSec(1)
                    --device.dump()
                end
            end
        end

        local function errorMessage(message,notify)   -- Add entry to log and notify to all subsystems
            dz.log(message,dz.LOG_ERROR)
            if notify then 
                dz.notify(message)
            end
        end    
        
        local function callPollutionURL(location,callback,delay)
            local delay = delay or 1
            local url   = "http://api.waqi.info/feed/geo:".. location .. "/?token=" .. apiKey
            dz.openURL({    url         = url,
                            method      = "GET",
                            callback    = callback
                       }).afterSec(delay)
        end
        
        local function getAirQualityData()
            local delay = 1
            for callType, location in pairs(geo) do
                if location ~= "" then
                    callPollutionURL(location,"waqi_" .. callType,delay) 
                    delay = delay + 30                    
                end    
            end
        end
        
        local function alertLevelAQI(value)
            if value < 50 then return dz.ALERTLEVEL_GREEN,"Excellent" end
            if value < 100 then return dz.ALERTLEVEL_YELLOW,"Poor" end
            if value < 150 then return dz.ALERTLEVEL_ORANGE,"Polluted" end
            return dz.ALERTLEVEL_RED,"Dangerous"
        end
        
        function deviceType(device)
            if device ~= nil then
                if dz.devices(device).deviceType:upper() == "GENERAL" then
                    return dz.devices(device).deviceSubType
                else
                    return dz.devices(device).deviceType
                end
            else
                return nil
            end
        end
        
        
        local function setSensor(sensor,value)
            if sensor ~= 0 and value ~= nil then
               
                if deviceType(sensor) == sensorTypes.custom then 
                    dz.devices(sensor).updateCustomSensor(value)
                elseif deviceType(sensor) == sensorTypes.aqi then
                    dz.devices(sensor).updateAirQuality(value)
                else
                    local alertLevel, alertText = alertLevelAQI(value)
                    local alertString = alertText .. "(" .. tostring(value) .. ")"   
                    if dz.devices(sensor).text ~= alertString then
                        dz.devices(sensor).updateAlertSensor(alertLevel, alertString)
                    end
                end 
            end
        end
        
        local function handleResponse(type)
            local rt = triggerItem.json                        -- rt is just a reference to the data no actual copy is done
            dz.log(triggerItem.data,dz.LOG_DEBUG)
            if triggerItem.json ~= nil and rt.data ~= nil and tonumber(rt.data.aqi) then
                if type == "nearby" then
                    rt.data.iaqi["aqi"] = {}; rt.data.iaqi["aqi"].v = rt.data.aqi    -- handle exception in iaqi as aqi is stored elsewhere
                    
                    for nearbyType, location in pairs(geo) do
                        if nearbyType ~= "nearby" and location == "" then               -- No other location for this type 
                            handleResponse(nearbyType)    
                        end    
                    end
                else
                    for setDevice, idx in pairs(sensors[type]) do
                        dz.log("setDevice" .. setDevice, dz.log_DEBUG)
                        dz.log("idx" .. idx, dz.log_DEBUG)
                        dz.log("sensors[Type]" .. tostring(sensors[Type]), dz.log_DEBUG)
                        dz.log("rt" .. tostring(rt), dz.log_DEBUG)
                        dz.log("rt.data" .. tostring(rt.data), dz.log_DEBUG)
                        dz.log("rt.data.iaqi" .. tostring(rt.data.iaqi), dz.log_DEBUG)
                        dz.log("rt.data.iaqi[type]" .. tostring(rt.data.iaqi[type]), dz.log_DEBUG)
                        setSensor(idx,rt.data.iaqi[type:lower()].v)
                    end
                    dz.log("type" .. tostring(type), dz.log_DEBUG)
                    if type:lower() == 'pm10' then 
                        dz.log("pm10 value" .. tostring(rt.data.iaqi.pm10.v), dz.log_DEBUG)
                        setColor(rt.data.iaqi.pm10.v, colorDevice) 
                    end
                end
            else
                errorMessage("This should not happen")   -- aqi should always be there and set
                if dz.data.safedMessage.get(1).time.secondsAgo > 30 then
                    errorMessage("I will call url again")   -- aqi should always be there and set
                    callPollutionURL(geo[responseType(triggerItem.trigger)],triggerItem.trigger,1)
                    dz.data.safedMessage.add("Extra call to openURL for " .. triggerItem.trigger)
                end    
            end
        end
        
        if triggerItem.isHTTPResponse then
           if triggerItem.ok and triggerItem.isJSON then 
               handleResponse(responseType(triggerItem.trigger))
           else
               errorMessage("Problem with response from waqi",true)  
           end
        else
            getAirQualityData()
        end    
    end
}
  
   
   
      
User avatar
waltervl
Posts: 5148
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: Get online airquality data

Post by waltervl »

You can add a check for device.active in the if statement.
See also wiki https://www.domoticz.com/wiki/DzVents:_ ... ll_devices
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
mojso
Posts: 86
Joined: Friday 08 November 2019 23:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Get online airquality data

Post by mojso »

Thanks i added in line 80 "and device.active" and i think it works as it should
waltervl wrote: Saturday 23 July 2022 22:58 You can add a check for device.active in the if statement.
See also wiki https://www.domoticz.com/wiki/DzVents:_ ... ll_devices
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests