Page 1 of 3

Rain prediction - weather underground

Posted: Wednesday 23 August 2017 9:20
by elmortero
Hi all,

Beginning this year I was looking for something to get precipitation prediction. Since the "buienradar" script does not work for me because there is not data for locations with a latitude below 44 I started on something myself.

Below I will post my script that is based on Weather Underground which provides this information world wide.
Maybe I am a "dirty coder" (lack of training and experience) and you see something that could be cleaner/easier/better so don't hesitate to point this out.
The script version I am posting here has been stripped of the notification that I send. It gets the "pop" --percentage of precipitation-- field per hour and per day and updates 2 virtual switches if the percentage is lower/higher than 30%.
Also there is a virtual Percentage sensor that gets updated with the POP.

I salute you.
olivier

Code: Select all

-- required:
-- 2 virtual switches: one for next hour prediction and one for Today prediction
-- 1 virtual sensor Percentage: for Probability Of precipitation
-- a weatherunderground API key. Instructions to get one are on the Domoticz Wiki
return {
	active = true,  
	on = {
			timer = {'every 20 minuteS'}
			},

execute = function(domoticz)
-- Variables to customize ------------------------------------------------
local city = "XXXXXX"                 				-- Your city for Wunderground API
local countryCode = "XXXXX"                        	-- Your country code for Wunderground API
local wuAPIkey = "XXXXXX"          					-- Your Weather Underground API Key
local rainswitch1 = domoticz.devices('Rain-1-hour')	-- The switch for rain in the next hour
local rainswitch24 = domoticz.devices('Rain-today')	-- the switch for rain Today
local popDay = domoticz.devices('popday')			-- The percentage virtual sensor
------------------------------------------------------------------------------------ pop24
	--begin of the part to get hourly rain chances
	json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
	local linker1 = tostring('curl http://api.wunderground.com/api/' .. wuAPIkey .. '/hourly/q/' .. countryCode .. '/' .. city .. '.json')
	local config=assert(io.popen(linker1))
			local loc = config:read('*all')
			config:close()
			local jsonLocation = json:decode(loc)
			local pop1 = tonumber(jsonLocation.hourly_forecast[1].pop)
			popDay.updatePercentage(pop1)

			if pop1 >= 30 and rainswitch1.state ~= 'On'   --switch will be turned on if probability is higher than 30%
			then rainswitch1.switchOn()
			end
		
			if pop1 < 30 and rainswitch1.state ~= 'Off'		--if the probability is lower than 30% switch will be turned off
			then 
			rainswitch1.switchOff()
			end
	--end of the part to get hourly rain chances
	--begin of the part to get daily rain chances
 local linker2 = tostring('curl http://api.wunderground.com/api/' .. wuAPIkey .. '/forecast/q/' .. countryCode .. '/' .. city .. '.json')
		json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
    	local config=assert(io.popen(linker2))
        local loc = config:read('*all')
        config:close()
        local jsonLocation = json:decode(loc)
        local pop24 = tonumber(jsonLocation.forecast.txt_forecast.forecastday[1].pop)
			if pop24 >= 30 and rainswitch24.state ~= 'On' 
			then rainswitch24.switchOn()
			end
			if pop24 < 30 and rainswitch24.state ~= 'Off'
			then rainswitch24.switchOff()
			end		
		end
}
PS: In my own script there is also a part that checks for extreme weather (Heat/Storm/Hail/Hurricane/Snow/Thunderstorms/Flooding/Earthquake/Tsunami/)
If someone is interested in that part, let me know!!

Re: Rain prediction - weather underground

Posted: Thursday 24 August 2017 8:44
by MarceldeJongNL
Thanks for your info, very useful.
Would like to see the extreme weather part!

Re: Rain prediction - weather underground

Posted: Thursday 24 August 2017 10:18
by DewGew
If you add this line to "Variables to customize":

Code: Select all

local lang = "EN" -- Forecast in your language eg. SW = swedish, EN = english, NL = Dutch etc.
and change this line:

Code: Select all

local linker1 = tostring('curl http://api.wunderground.com/api/' .. wuAPIkey .. '/hourly/q/' .. countryCode .. '/' .. city .. '.json')
to this line:

Code: Select all

local linker1 = tostring('curl http://api.wunderground.com/api/' .. wuAPIkey .. '/hourly/lang:' ..lang.. '/q/' .. countryCode .. '/' .. city .. '.json')
You get the weather information from WU in your language.
See more at https://www.wunderground.com/weather/ap ... ge-support

Re: Rain prediction - weather underground

Posted: Thursday 24 August 2017 11:07
by MarceldeJongNL
Nice! Thanks!

Re: Rain prediction - weather underground

Posted: Thursday 24 August 2017 12:33
by elmortero
MarceldeJongNL wrote:Thanks for your info, very useful.
Would like to see the extreme weather part!
Will post It here this afternoon.

olivier@ALC


Re: Rain prediction - weather underground

Posted: Thursday 24 August 2017 13:25
by elmortero
The Sever Weather Alert part:
  • Create a virtual text sensor (mine is called Weather_Alert)
  • Paste this code just above the last end in the original script.
    Spoiler: show
    --this is the severe weather alert part
    local alertswitch = domoticz.devices('Weather_Alert') --this is a Virtual Text Sensor
    local prevAlert = tostring(alertswitch.rawData[1])
    local linker3 = tostring('curl http://api.wunderground.com/api/' .. wuAPIkey .. '/alerts/q/' .. countryCode .. '/' .. city .. '.json')
    json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
    local config=assert(io.popen(linker3))
    local loc = config:read('*all')
    config:close()
    local jsonLocation = json:decode(loc)
    local oldText = tostring(alertswitch.Text)
    --checks if there is an alert
    if jsonLocation.alerts[1] == nil and prevAlert ~= "No Alert"
    then
    nfo = "No Alert"
    alertswitch.updateText(nfo)

    else
    if jsonLocation.alerts[1] ~= nil then
    local pop = tostring(jsonLocation.alerts[1].wtype_meteoalarm_name)
    local wInfo = tostring(jsonLocation.alerts[1].message)
    if pop ~= prevAlert then
    alertswitch.updateText(wInfo)
    end
    end

    end
    -- end of severe weather alert part
  • It will get the info if it exists (if there is no alert the field 'alerts' is not present in the json result
  • Then it will check if the the current content of the Text Sensor is not already 'No Alert'
  • If that is the case it will change the value of the text sensor to 'No Alert'
  • Otherwise -there actually IS an alert and the Text sensor was not already set to that alert (throughout the day the same alert may be updated with extra/new info- it will update the Text.
  • As it is right now the text sent to the Text sensor is the full text message provided by wUnderground. If you want just the type of alert (e.g. "Thunderstorms" instead of "Thunderstorms throughout the day starting form..." all you need to change is (pop) to (winfo) in alertswitch.updateText(wInfo)
Enjoy!

Re: Rain prediction - weather underground

Posted: Saturday 26 August 2017 9:47
by mivo
Hi,

thank you, great scripts and flexible way to catch any data from Wunderground 8-) - just modify parsed JSON variable syntax and get any data from it. Modified it slightly - Wunderground has option to combine JSON calls and so save daily limit (i hope) of free requests. Just add more features to HTTP request:

http:// api.wunderground.com/api/xxx-apikey-xxx/hourly/forecast/alerts/q/LKPR.json

Example code with more data extracting and debug logging of data (no alerts yet):

Code: Select all

local link = 'curl http://api.wunderground.com/api/' .. wuAPIkey .. '/hourly/forecast/alerts/q/' .. que
ry .. '.json'
                local response = assert(io.popen(link))
                local lines = response:read('*all')
                response:close()
                local jsonLocation = json:decode(lines)

                local popH = tonumber(jsonLocation.hourly_forecast[1].pop)
                local popHmm = tonumber(jsonLocation.hourly_forecast[1].qpf.metric)
                domoticz.log('Hourly forecast for : ' .. tostring(jsonLocation.hourly_forecast[1].FCTTIME.hour) 
.. ' hour, rain percentage: ' .. tostring(popH) .. ', mm: ' .. tostring(popHmm))
                popHour.updatePercentage(popH)

                -- local popD = tonumber(jsonLocation.forecast.simpleforecast.forecastday[1].pop)
                -- local popHmm = tonumber(jsonLocation.forecast.simpleforecast.forecastday[1].qpf_allday.mm)
                local popD = tonumber(jsonLocation.forecast.txt_forecast.forecastday[1].pop)
                local popDmm = tonumber(jsonLocation.forecast.simpleforecast.forecastday[1].qpf_allday.mm)
                local forecastText = jsonLocation.forecast.txt_forecast.forecastday[1].fcttext_metric
                local forecastPeriod = jsonLocation.forecast.txt_forecast.forecastday[1].title
                domoticz.log('Next 12h forecast for : ' .. forecastPeriod .. ' - ' .. forecastText  .. ', rain p
ercentage: ' .. tostring(popD) .. ', mm: ' .. tostring(popDmm))
                popDay.updatePercentage(popD)

Re: Rain prediction - weather underground

Posted: Saturday 17 February 2018 21:09
by Qcvictor
Pretty interesting, I'm looking for the snow prediction %, can I change it easily for snow forecast ? any advice regard Vic

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 0:45
by elmortero
Well, on weatherunderground pop is the percentage of probability of any precipitation so that could be anything.
They do however also have a prediction of the quantity of snowfall (in metric and imperial value) so you could first check if that value is > 0 and assume then that the qpf refers to snowfall.
If you want the predicted snowfall in imperial units (I don't know what you guys use in Canada) :hourly_forecast[4].snow.english or in metric units:
hourly_forecast[4].snow.metric
And then if that is greater than zero assume that hourly_forecast[1].pop refers to snow

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 8:45
by acaonweb
i've tried to add weather underground hardware but i can't find devices... something wrong?
i have the api key
i inserted right location

...what i miss?

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 9:09
by elmortero
You need to create the virtual devices yourself and put the correct names in the "Variables to customize" part of the script.
Also, if your dzVents version is 2.3 or higher this script will not work due to the breaking changes that were announced with the release of 2.3.
Updated script below in spoiler
Spoiler: show
return {
on = {
timer = { 'at *:26', 'at *:52' },
httpResponses = { 'wUnderG' } -- matches callback string below
},

execute = function(domoticz, triggerItem)
----wunderground info
local apikey = 'XXXXXXXXXXXX' -- api key.Instructions to get one are on the Domoticz Wiki
local country = 'XX' -- countrycode (ISO) 2 characters
local city = 'XXXXXXXX' -- name of the city to query for
local tresh = 15 -- treshold for activating the rainswitch (or how high must the probability be for the raintoday
-- switch is switched on or off
-----define your virtual devices
-- for the next hour
local switchH = domoticz.devices('Rain-1-hour')
local popHour = domoticz.devices('pop1hour')
local prevPopH = tonumber(popHour.percentage)
local qpsH = domoticz.devices('Predicted next hour')
--for today
local switchD = domoticz.devices('Rain-today')
local popDay = domoticz.devices('popday')
local prevPopD = tonumber(popDay.percentage)
local qpsD = domoticz.devices('Predicted Today')

if (triggerItem.isTimer) then
domoticz.openURL({
url = 'http://api.wunderground.com/api/'..apik ... ty..'.json',
method = 'GET',
callback = 'wUnderG'
})

elseif (triggerItem.isHTTPResponse) then

local response = triggerItem
if (response.ok and response.isJSON) then
-- start of the 1-hour prediction
local popH = tonumber(response.json.hourly_forecast[1].pop)
local qpfH = tonumber(response.json.hourly_forecast[1].qpf.metric)
qpsH.updateRain(0,qpfH)
print('wUnderG qpfh = '..qpfH)
if popH ~= prevPopH then
popHour.updatePercentage(popH)
end
if popH >= tresh
then switchH.switchOn().checkFirst()
end

if popH < tresh
then
switchH.switchOff().checkFirst()
end
-- end of the 1-hour prediction
--start of the 1 day prediction
local popD = tonumber(response.json.forecast.txt_forecast.forecastday[1].pop)
local qpfD = tonumber(response.json.forecast.simpleforecast.forecastday[1].qpf_allday.mm)
qpsD.updateRain(0,qpfD)
print('wUnderG qpfD = '..qpfD)
if popD ~= prevpopD then
popDay.updatePercentage(popD)
end
if popD >= tresh
then switchD.switchOn().checkFirst()
end

if popD < tresh
then
switchD.switchOff().checkFirst()
end
--end of the 1 day prediction

else
print('**wUnderG failed to fetch info')
end
end
end
}

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 18:43
by Qcvictor
something goes wrong with the url in the latest script for new version of dzvents

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 19:07
by elmortero
You will have to give more info. Maybe an error message?

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 19:13
by elmortero
Maybe you can put a print(url) just before where it says
elseif (triggerItem.isHTTPResponse) then
That way the log will show the composed url and it might already be clear what is wrong.

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 19:47
by Qcvictor
elmortero wrote: Sunday 18 February 2018 19:13 url = 'http://api.wunderground.com/api/'..apik ... ty..'.json',
Change for

Code: Select all

domoticz.openURL({url = 'http://api.wunderground.com/api/' .. apikey .. '/hourly/forecast/alerts/q/' .. country .. '/' .. city .. '.json',
and get

Code: Select all

018-02-18 16:07:00.397 dzVents: Info: ------ Start internal script: Forecast:, trigger: at *:07
2018-02-18 16:07:00.428 dzVents: Info: ------ Finished Forecast
2018-02-18 16:07:01.897 dzVents: Info: Handling httpResponse-events for: "wUnderG
2018-02-18 16:07:01.897 dzVents: Info: ------ Start internal script: Forecast: HTTPResponse: "wUnderG"
2018-02-18 16:07:01.944 dzVents: Error (2.4.1): Method updateRain is not available for device "Predicted next hour" (deviceType=General, deviceSubType=Percentage). If you believe this is not correct, please report.
2018-02-18 16:07:01.944 dzVents: wUnderG qpfh = 0
2018-02-18 16:07:01.944 dzVents: Error (2.4.1): Method updateRain is not available for device "Predicted Today" (deviceType=General, deviceSubType=Percentage). If you believe this is not correct, please report.
2018-02-18 16:07:01.944 dzVents: wUnderG qpfD = 0
2018-02-18 16:07:01.944 dzVents: Info: ------ Finished Forecast 
Which kind of device should be "Predicted next hour" and "Predicted Today", I tried Text, Switch and Percentage no luck ...?

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 22:15
by elmortero
ah, my bad! Didn't check very well when pasting the code here.
this is what you need:
'http://api.wunderground.com/api/' .. apikey .. '/hourly/forecast/q/' .. country .. '/' .. city .. '.json'

That should do it!

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 22:38
by Qcvictor
elmortero wrote: Sunday 18 February 2018 22:15 ah, my bad! Didn't check very well when pasting the code here.
this is what you need:
'http://api.wunderground.com/api/' .. apikey .. '/hourly/forecast/q/' .. country .. '/' .. city .. '.json'

That should do it!
Issue now is with the type of device for "Predicted next hour" and "Predicted Today", see my log above.

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 23:07
by elmortero
Should be Rain device

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 23:07
by elmortero
Should be Rain device

Re: Rain prediction - weather underground

Posted: Sunday 18 February 2018 23:51
by Qcvictor
elmortero wrote: Sunday 18 February 2018 23:07 Should be Rain device
thank you so much elmortero, it's working now :D