Async solution for getting openUV data with API Key (no longer kind of )

Moderator: leecollings

Post Reply
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Async solution for getting openUV data with API Key (no longer kind of )

Post by waaren »

Because I could not use dzVents async openURL together with an API key to get UV and ozone data from openUV, I made a script that kind of simulates that approach with the help of a domoticz user variable.

[EDIT} no longer needed. See updated script and remarks in post 4

First get your free API key from https://www.openuv.io/ and enter that in the data section of the script.
In the same area you need to enter your longitude . latitude values and devicenumbers of your (to be created) virtual UV devices (current and max today) and of the two alerts (UV and ozone alert).

you need dzVents 2.4.0 or later to be able to use this script. Tested and working on PI-3 with Debian stretch. (domoticz V3.9476)

Code: Select all

--[[ openUV.lua for [ dzVents >= 2.4 ] 
]]--

return {
    on      =   {   timer           =   { "every 15 minutes at daytime" }, -- Triggers the getJsonPart
                    httpResponses   =   { "openUV_Response" }               -- Trigger the handle Json part
                },
                
    logging =   {   level     =   domoticz.LOG_DEBUG,                                   
                    marker    =   "openUV" 
                },                                           

    data    =   {   openUV_Longitude          = {initial = "x.xxxxxx"                           },  -- I store my longitude, latitude, APIkey, filename in data
                    openUV_Latitude           = {initial = "xx.xxxxxx"                          },  -- You can get them from domoticz settings
                    openUV_Filename           = {initial = "scripts/dzVents/data/OpenUV.json"   },  -- path relative to domoticz directory
                    openUV_APIKey             = {initial = "blablablabla1234567blablablablaa"   },  -- get your free API key from https://www.openuv.io/
                    openUV_currentUV_device   = {initial = xxx                                  },  -- You have to create a couple of virtual devices 
                    openUV_maxUV_device       = {initial = xxx                                  },  -- (first two as UV sensors and other two as Alert)
                    openUV_UV_Alert_device    = {initial = xxx                                  },  -- Remember device ID's and replace the "xxx" with them
                    openUV_ozone_Alert_device = {initial = xxx                                  },  -- Look at https://www.domoticz.com/wiki/Hardware_Setup#Dummy_Hardware 
                                                                                                    -- If you need help with this
                },
 
    execute = function(dz, trigger)
            
        local function UV_Index2Alert(index)                            -- Levels as from KNMI
            local alert = dz.ALERTLEVEL_RED
            if      index < 3 then alert = dz.ALERTLEVEL_GREY
            elseif  index < 5 then alert = dz.ALERTLEVEL_GREEN
            elseif  index < 7 then alert = dz.ALERTLEVEL_YELLOW
            elseif  index < 9 then alert = dz.ALERTLEVEL_ORANGE
            end
            return alert
        end

        local function ozone2Alert(value)                               -- Levels as found on various WIKI pages
            local alert = dz.ALERTLEVEL_RED
            if      value > 400 then alert = dz.ALERTLEVEL_GREY
            elseif  value > 340 then alert = dz.ALERTLEVEL_GREEN
            elseif  value > 310 then alert = dz.ALERTLEVEL_YELLOW
            elseif  value > 280 then alert = dz.ALERTLEVEL_ORANGE
            end
            return alert
        end
       
        local function getOpenUV_json()
            local openUV_url        = "https://api.openuv.io/api/v1/uv?lat=" .. dz.data.openUV_Latitude .. "&lng=" .. dz.data.openUV_Longitude 
             dz.openURL({
                            url = openUV_url ,
                            method = "GET",
                            callback = "openUV_Response",
                            headers = { ['x-access-token'] =  dz.data.openUV_APIKey },
                      })
        end
                
        local function handleOpenUVResponse()
            -- Read response into table and close file
            openUVResponse      = trigger.json

            if openUVResponse.result.uv                      == nil or
               openUVResponse.result.uv_max                  == nil or
               openUVResponse.result.uv_max_time             == nil or 
               openUVResponse.result.ozone                   == nil or
               openUVResponse.result.safe_exposure_time.st3  == nil then
               dz.log("Some values are missing; check it out",dz.LOG_ERROR) 
               dz.log(openUVResponse,dz.LOG_ERROR) 
               return
            end    

            -- Update UV devices    
            dz.devices(dz.data.openUV_currentUV_device).updateUV(dz.utils.round(openUVResponse.result.uv,1))
            dz.devices(dz.data.openUV_maxUV_device).updateUV(dz.utils.round(openUVResponse.result.uv_max,1))

            -- convert to local time
            local dateOutput        = assert(io.popen("date -d" .. openUVResponse.result.uv_max_time ..  " +%k:%M uur"))   
            local openUVMaxUVtime   = dateOutput:read("*all")
            dateOutput:close()
            
            -- Construct Alertlevel and text and update UV alert device (type = Alert)
            UV_AlertText = "Max UV index today is " .. dz.utils.round(openUVResponse.result.uv_max,1) .. " at " .. openUVMaxUVtime 
            dz.log("Current UV index = " .. dz.utils.round(openUVResponse.result.uv,1) .. ", " ..  UV_AlertText,dz.LOG_INFO)
            dz.devices(dz.data.openUV_UV_Alert_device).updateAlertSensor(UV_Index2Alert(openUVResponse.result.uv_max), UV_AlertText)

            -- Construct Alertlevel and text and update ozone alert device (type = Alert)
            ozoneAlertText = "Ozone (Dobson unit) is " .. openUVResponse.result.ozone .. "\n Max. exposure to sun (Skintype 3) is " ..
                            openUVResponse.result.safe_exposure_time.st3 .. " minutes."         
            dz.log(ozoneAlertText,dz.LOG_INFO)
            dz.devices(dz.data.openUV_ozone_Alert_device).updateAlertSensor(ozone2Alert(openUVResponse.result.ozone), ozoneAlertText)
        end
        
        if trigger.isTimer then
            getOpenUV_json()
        else     
            handleOpenUVResponse()
        end
    end
}
 
[EDIT & BTW] I am still considering if I will include this in my updateWeatherSensors solution. Any advice on that is appreciated.

have Fun!
Last edited by waaren on Friday 25 May 2018 2:33, edited 3 times in total.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
EddyG
Posts: 1042
Joined: Monday 02 November 2015 5:54
Target OS: -
Domoticz version:

Re: (kind of) async solution for getting openUV data with API Key

Post by EddyG »

Nice solution. I filled a bug report in the dzVents section for the problem with the header.
I hope that Dannybloe can solve that.
If that problem is solved, I think you should include this in your buienradar script.
Perhaps you could then also get 'cloudCover' from https://api.darksky.net/forecast/<api-key>/<lat>,<lon>
There are some calculations for UV and cloudCover to get the real UV. Just an idea. ;)
EddyG
Posts: 1042
Joined: Monday 02 November 2015 5:54
Target OS: -
Domoticz version:

Re: (kind of) async solution for getting openUV data with API Key

Post by EddyG »

My bad (syntax BUG). This works.

Code: Select all

                        domoticz.openURL({
                                url = 'https://api.openuv.io/api/v1/uv?lat=<lat>&lng=<lon>',
                                method = 'GET',
                                callback = 'UV-data',
                                headers = { ['x-access-token'] = '<api-key>' },
And later to get the UV from the response:

Code: Select all

 local UVvalue = item.json.result.uv
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: (kind of) async solution for getting openUV data with API Key

Post by waaren »

The reply from EddyG made it possible for me to modify my script in such a way that it is no longer dependent on user variables to simulate async behaviour of collecting the UV json and handling it.
The updated script now use native dzVents to achieve the async method.

[EDIT 20180525 - 18:05] bugfix in time conversion uv_max_time

Code: Select all

--[[ openUV.lua for [ dzVents >= 2.4 ] 
]]--

return {
    on      =   {   timer           =   { "every 15 minutes at daytime" }, -- Triggers the getJsonPart
                    httpResponses   =   { "openUV_Response" }               -- Trigger the handle Json part
                },
                
    logging =   {   level     =   domoticz.LOG_DEBUG,                                   
                    marker    =   "openUV" 
                },                                           

    data    =   {   openUV_Longitude          = {initial = "x.xxxxxx"                           },  -- I store my longitude, latitude, APIkey, filename in data
                    openUV_Latitude           = {initial = "xx.xxxxxx"                          },  -- You can get them from domoticz settings
                    openUV_Filename           = {initial = "scripts/dzVents/data/OpenUV.json"   },  -- path relative to domoticz directory
                    openUV_APIKey             = {initial = "blablablabla1234567blablablablaa"   },  -- get your free API key from https://www.openuv.io/
                    openUV_currentUV_device   = {initial = xxx                                  },  -- You have to create a couple of virtual devices 
                    openUV_maxUV_device       = {initial = xxx                                  },  -- (first two as UV sensors and other two as Alert)
                    openUV_UV_Alert_device    = {initial = xxx                                  },  -- Remember device ID's and replace the "xxx" with them
                    openUV_ozone_Alert_device = {initial = xxx                                  },  -- Look at https://www.domoticz.com/wiki/Hardware_Setup#Dummy_Hardware 
                                                                                                    -- If you need help with this
                },
 
    execute = function(dz, trigger)
            
        local function UV_Index2Alert(index)                            -- Levels as from KNMI
            local alert = dz.ALERTLEVEL_RED
            if      index < 3 then alert = dz.ALERTLEVEL_GREY
            elseif  index < 5 then alert = dz.ALERTLEVEL_GREEN
            elseif  index < 7 then alert = dz.ALERTLEVEL_YELLOW
            elseif  index < 9 then alert = dz.ALERTLEVEL_ORANGE
            end
            return alert
        end

        local function ozone2Alert(value)                               -- Levels as found on various WIKI pages
            local alert = dz.ALERTLEVEL_RED
            if      value > 400 then alert = dz.ALERTLEVEL_GREY
            elseif  value > 340 then alert = dz.ALERTLEVEL_GREEN
            elseif  value > 310 then alert = dz.ALERTLEVEL_YELLOW
            elseif  value > 280 then alert = dz.ALERTLEVEL_ORANGE
            end
            return alert
        end
       
        local function getOpenUV_json()
            local openUV_url        = "https://api.openuv.io/api/v1/uv?lat=" .. dz.data.openUV_Latitude .. "&lng=" .. dz.data.openUV_Longitude 
             dz.openURL({
                            url = openUV_url ,
                            method = "GET",
                            callback = "openUV_Response",
                            headers = { ['x-access-token'] =  dz.data.openUV_APIKey },
                      })
        end
                
        local function handleOpenUVResponse()
            -- Read response into table and close file
            openUVResponse      = trigger.json

            if openUVResponse.result.uv                      == nil or
               openUVResponse.result.uv_max                  == nil or
               openUVResponse.result.uv_max_time             == nil or 
               openUVResponse.result.ozone                   == nil or
               openUVResponse.result.safe_exposure_time.st3  == nil then
               dz.log("Some values are missing; check it out",dz.LOG_ERROR) 
               dz.log(openUVResponse,dz.LOG_ERROR) 
               return
            end    

            -- Update UV devices    
            dz.devices(dz.data.openUV_currentUV_device).updateUV(dz.utils.round(openUVResponse.result.uv,1))
            dz.devices(dz.data.openUV_maxUV_device).updateUV(dz.utils.round(openUVResponse.result.uv_max,1))

                -- convert to local time
            local commandString     = "date -d " .. openUVResponse.result.uv_max_time ..  "  '+%k:%M uur' "
            local dateOutput        = assert(io.popen(commandString))   
            local openUVMaxUVtime   = dateOutput:read("*all")
            dateOutput:close()
            
            -- Construct Alertlevel and text and update UV alert device (type = Alert)
            UV_AlertText = "Max UV index today is " .. dz.utils.round(openUVResponse.result.uv_max,1) .. " at " .. openUVMaxUVtime 
            dz.log("Current UV index = " .. dz.utils.round(openUVResponse.result.uv,1) .. ", " ..  UV_AlertText,dz.LOG_INFO)
            dz.devices(dz.data.openUV_UV_Alert_device).updateAlertSensor(UV_Index2Alert(openUVResponse.result.uv_max), UV_AlertText)

            -- Construct Alertlevel and text and update ozone alert device (type = Alert)
            ozoneAlertText = "Ozone (Dobson unit) is " .. openUVResponse.result.ozone .. "\n Max. exposure to sun (Skintype 3) is " ..
                            openUVResponse.result.safe_exposure_time.st3 .. " minutes."         
            dz.log(ozoneAlertText,dz.LOG_INFO)
            dz.devices(dz.data.openUV_ozone_Alert_device).updateAlertSensor(ozone2Alert(openUVResponse.result.ozone), ozoneAlertText)
        end
        
        if trigger.isTimer then
            getOpenUV_json()
        else     
            handleOpenUVResponse()
        end
    end
}
 
so many thanks and credits to @EddyG

have Fun !
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest