Quantcast
Channel: Domotique – pon.fr
Viewing all articles
Browse latest Browse all 66

[DZvents] Qualité de l’air et données météorologiques

$
0
0

Bonjour,
je vous propose aujourd’hui la réécriture en DZvents du script qualité de l’air dans le monde
Pourquoi ce script alors que le précédent fonctionne très bien?
Ce nouveau script apporte son lot de nouveautés :

  • récupération automatique des données de localisation renseignées dans les paramétrés de domoticz
  • possibilité d’agréger plusieurs stations proches pour ajouter les mesures non présentes dans celle qui est la plus proche de chez vous
  • possibilité de récupérer, en plus des données de pollution, des données météo disponible telles que : température, hygrométrie relative, vent et rafale de vent, pression, pluie, pression atmosphérique et température de rosée
  • possibilité de paramétrer plusieurs devices pour une même donnée de pollution : custom sensor, alerte, qualité de l’air

tout cela avec une API gratuite.

le script complet pour Domoticz

--[[ ~/home/pi/domoticz/scripts/dzVents/scripts/airQuality.lua
Based on this script : http://www.domoticz.com/forum/viewtopic.php?f=59&t=22080&start=20#p216650
Minimal dzVents Version: 2.4.19
auteur : papoo
MAJ : 10/06/2019
création : 08/06/2019
Principe :
Ce script a pour but d'interroger l'API du site http://http://aqicn.org pour récupérer les informations de pollutions
Cette API utilise une clé gratuite, Il faut donc s'incrire sur http://aqicn.org/data-platform/token/  pour avoir accès à cette clé de 40 caractères
data from http://waqi.info/
An API key is required and can be aquired here ==> http://aqicn.org/data-platform/token/


https://pon.fr/dzvents-qualite-de-lair-et-donnees-meteorologiques
https://github.com/papo-o/domoticz_scripts/blob/master/dzVents/scripts/airQuality.lua
v1.x : https://pon.fr/qualite-de-lair-dans-le-monde/
]]--
local token_aqicn = 'api_aqicn'-- aqicn token chaine user variable name. if you don't want to use a user variable, change the value of the apiKey variable
local scriptName = 'airQuality'
local scriptVersion = '2.0'
return {
    active =  true, -- false,
    on =    {
                timer           = { "every 15 minutes" },
                httpResponses   = { "waqi*" }                            -- matches callback wildcard
            },

        data    =   {
                        safedMessage = { history = true, maxItems = 100 , maxHours = 168 }
                    },

        logging =   {   level   =   domoticz.LOG_DEBUG,
                        marker  =   scriptName..' v'..scriptVersion },

    execute = function(dz, triggerItem)

        local apiKey            = dz.variables(token_aqicn).value -- if you don't want to use a user variable, change this by your aqicn token like "123456789123456789" 
        --local defaultLocation   = "51.852062;4.507676"
        local defaultLocation   =  dz.settings.location.latitude ..";".. dz.settings.location.longitude  --using the location data declared in the parameters, utilisation des données de localisation déclarées dans les parametres
        local sensorType

        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     = "",--"51.867238;4.354981",   -- if value for this item cannot be obtained from "nearby"
                        co      = "",--"51.986119;4.934413",   -- else keep this as an empty string
                        pm25    = "",
                        pm10    = "45.873333332057;1.308",--dispo
                        o3      = "45.873333332057;1.308",--dispo
                        no2     = "",
                        aqi     = "",
                        w       = "",
                        wg      = "45.873333332057;1.308",
                        t       = "",
                        r       = "",
                        h       = "",
                        d       = "",
                        p       = "",
                      }

        local sensors = {    -- enter device index Numbers or 0 for sensor and alert "
                        so2     = { sensor = 0,  alert = 0},  -- Sulphur Dioxide
                        co      = { sensor = 0,  alert = 0},  -- Carbon Monoxyde
                        pm25    = { sensor = 0,  alert = 0},
                        pm10    = { sensor = 1140, alert = 1141},
                        o3      = { sensor = 0,  alert = 0},  -- Ozone
                        no2     = { sensor = 1143,  alert = 1142},-- Nitrogen Dioxide
                        aqi     = { sensor = 0,  alert = 0, aqiSensor = 0},      -- additional Air Quality sensor
                        w       = { sensor = 1144},-- wind
                        wg      = { sensor = 1146},-- wind gust
                        t       = { sensor = 0},-- Temperature
                        r       = { sensor = 0},-- rain (precipitation)
                        h       = { sensor = 0},-- Relative Humidity
                        d       = { sensor = 0},-- Dew
                        p       = { sensor = 0},-- Atmostpheric Pressure
                        }

        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 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,"Moyen" end
            if value < 150 then return dz.ALERTLEVEL_ORANGE,"Pollué" end
            return dz.ALERTLEVEL_RED,"Dangereux"
        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 : "..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
                        if idx ~= 0 then
                            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)
                                if rt.data.iaqi[type] ~= nil then setSensor(idx,rt.data.iaqi[type:lower()].v) end
                        end
                    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
}

Retrouver la derniere version de ce script sur

 Site Officiel :   github.com

Viewing all articles
Browse latest Browse all 66

Trending Articles