Page 1 of 16

Is it gonna rain within the next X minutes?

Posted: Friday 27 March 2015 14:40
by Hansbit
I wrote a function to predict if it gonna rain within the next X minutes. The function may be very handy for controlling sunscreens etcetera. The script uses the dutch weather website Buienradar.nl, so this script will only work for The Netherlands.
One may use the Buienradar's free service for non-commercial purposes.

Put your local lat/lon in the configuration part of the script. Calling the function IsItGonnaRain( 10) will return the average rain fall for the next 10 minutes. 0 is no rain, 255 is very heavy rain. When needed, mm/h is calculated by 10^((value -109)/32) (example: 77 = 0.1 mm/hour)

Please mail of PM your changes or suggestions, I'll update the script here.

Regards, Hans

Code: Select all

----------------------------------------------------------------------------------------------------------------
-- IsItGonnaRain( int minutesinfuture)
-- returns: int avarage rainfall for the next minutesinfuture
--
-- Function to get rain prediction from Buienradar.nl (dutch)
-- 
-- http://gratisweerdata.buienradar.nl/#Buienradar You may use their free service for non-commercial purposes. 
-- 
-- Written in LUA by Hans van der Heijden (h4nsie @ gmail.com)
-- Spring 2015
-- 28-03-2015 v0.3 bug: quotes around url added.
-- 27-03-2015 v0.2 return value is now average for next time
-- 26-03-2015 v0.1 Initial release
-- todo: some error checking on http and file handling (tmp file)
----------------------------------------------------------------------------------------------------------------
function IsItGonnaRain( minutesinfuture )

	-- config ---------------------------------------------------------
	lat='52.09'	-- example lat/lon for Utrecht
	lon='5.12' -- use MAX 2 decimals behind comma. (Requirement Buienrader)
	debug=false
	tempfilename = '/var/tmp/rain.tmp' -- can be anywhere writeable
	-- config ---------------------------------------------------------
			
	url='http://gps.buienradar.nl/getrr.php?lat='..lat..'&lon='..lon
	if debug then print(url) end
	read = os.execute('curl -s -o '..tempfilename..' "'..url..'"')
	file = io.open(tempfilename, "r")
	totalrain=0
	rainlines=0
	-- now analyse the received lines, format is like 000|15:30 per line.
	while true do 
		line = file:read("*line")
		if not line then break end
		if debug then print('Line:'..line) end
		linetime=string.sub(tostring(line), 5, 9)
		if debug then print('Linetime: '..linetime) end
	   	
	   	-- Linetime2 holds the full date calculated from the time on a line
	   	linetime2 = os.time{year=os.date('%Y'), month=os.date('%m'), day=os.date('%d'), hour=string.sub(linetime,1,2), min=string.sub(linetime,4,5), sec=os.date('%S')}
	   	difference = os.difftime (linetime2,os.time())
	
		-- When a line entry has a time in the future AND is in the given range, then totalize the rainfall
		if ((difference > 0) and (difference<=minutesinfuture*60)) then
			if debug then print('Line in time range found') end
			rain=tonumber(string.sub(tostring(line), 0, 3))
			totalrain = totalrain+rain
			rainlines=rainlines+1
			if debug then print('Rain in timerange: '..rain) end
			if debug then print('Total rain now: '..totalrain) end
		end
	
	end
	file:close()
	
	-- Returned value is average rain fall for next time
	-- 0 is no rain, 255 is very heavy rain
	-- When needed, mm/h is calculated by 10^((value -109)/32) (example: 77 = 0.1 mm/hour)
	averagerain=totalrain/rainlines
	
return(averagerain)
end

Example implementation in Domoticz:

Code: Select all

----- REGEN ------
minuten=10
regen = IsItGonnaRain(minuten)
print('Regen verwacht: '..regen..' binnen '..minuten..' minuten.')

if regen > 70 then
	commandArray['SendNotification']='Sunscreens#Regen verwacht'
end

Is it gonna rain within the next X minutes?

Posted: Friday 27 March 2015 16:05
by xces
Hi Hans,

Looking good! Can you post an example how to implement also? I have never done anything in Lua, only in C#. Do you run this script in a loop?

Re: Is it gonna rain within the next X minutes?

Posted: Friday 27 March 2015 16:34
by tlpeter
I am curious too.
I just installed a Fibaro roller/shutter for my sunscreen.
It would be nice to prevent it getting wet if i forget it :)

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 28 March 2015 8:52
by pvm
Did you put the lua script in the domoticz scripts/lua folder? This is automatically executed every minute when choosing the correct name

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 28 March 2015 13:31
by johnwulp
Thanks for your effort! I implemented it in my sunscreen script. Does is also spit out a value > 0 if it is raining?

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 28 March 2015 14:05
by tlpeter
John, can you share your script?

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 28 March 2015 14:50
by johnwulp
tlpeter wrote:John, can you share your script?
Offcourse. It's still 'in progress...'

Code: Select all

function IsItGonnaRain( minutesinfuture )

   -- config ---------------------------------------------------------
   lat='51.818930'   -- example lat/lon for Utrecht
   lon='4.427236'
   debug=false
   tempfilename = '/var/tmp/rain.tmp' -- can be anywhere writeable
   -- config ---------------------------------------------------------
         
   url='http://gps.buienradar.nl/getrr.php?lat='..lat..'&lon='..lon
   if debug then print(url) end
   read = os.execute('curl -s -o '..tempfilename..' "'..url..'"')
   file = io.open(tempfilename, "r")
   totalrain=0
   rainlines=0
   -- now analyse the received lines, format is like 000|15:30 per line.
   while true do 
      line = file:read("*line")
      if not line then break end
      if debug then print('Line:'..line) end
      linetime=string.sub(tostring(line), 5, 9)
      if debug then print('Linetime: '..linetime) end
         
         -- Linetime2 holds the full date calculated from the time on a line
         linetime2 = os.time{year=os.date('%Y'), month=os.date('%m'), day=os.date('%d'), hour=string.sub(linetime,1,2), min=string.sub(linetime,4,5), sec=os.date('%S')}
         difference = os.difftime (linetime2,os.time())
   
      -- When a line entry has a time in the future AND is in the given range, then totalize the rainfall
      if ((difference > 0) and (difference<=minutesinfuture*60)) then
         if debug then print('Line in time range found') end
         rain=tonumber(string.sub(tostring(line), 0, 3))
         totalrain = totalrain+rain
         rainlines=rainlines+1
         if debug then print('Rain in timerange: '..rain) end
         if debug then print('Total rain now: '..totalrain) end
      end
   
   end
   file:close()
   averagerain=totalrain/rainlines
   
return(averagerain)
end



commandArray = {}

time = os.date("*t")

--Extract Wind Gust speed from SValue Wind
wind = otherdevices_svalues['Wind']
--print("Wind: "..wind)

--Filter the third digitsequence from SValue
a = string.sub(wind,1,string.find(wind,';',1,true)-1)
--print("a: "..a)

b = string.sub(wind,string.find(wind,';',1,true)+1)
--print("b: "..b)

d = string.sub(b,string.find(b,';',1,true)+1)
--print("d: "..d)

windspeed = string.sub(d,1,string.find(d,';',1,true)-1)

f = string.sub(d,string.find(d,';',1,true)+1)
--print("f: "..f)

g = string.sub(f,string.find(f,';',1,true)+1)
--print("g: "..g)

--Extract Temp
tempstring = otherdevices_svalues['Temperatuur']
--print("Temp: "..tempstring)

temperature = string.sub(tempstring,1,string.find(tempstring,';',1,true)-1)

--Extract UV radiation from SValue Wind
-- solar = otherdevices_svalues['UV']
-- print("Solar Radiation: "..solar)
--Filter the first digit from SValue
-- uv = string.sub(solar,1,string.find(solar,';',1,true)-1)
-- print("UV: "..uv)

--Extract actual rainfall from Rain_SValue
rain = otherdevices_svalues['Regen']
--print("Rain: "..rain)

--Filter the first digit from SValue
currentrain = string.sub(rain,1,string.find(rain,';',1,true)-1)

--Filter the last digit from SValue
--totalrain = string.sub(rain,string.find(rain,';',1,true)+1)
--print("Total rain: "..totalrain)

print("Uur: " ..time.hour)

minuten=5
regen = IsItGonnaRain(minuten)
print('Regen verwacht: '..regen..' binnen '..minuten..' minuten.')

--Sunscreen thresholds:
        -- Windspeed            = 50 (value is multiplied by 10)
        -- Rain                 =  0.0
        -- UV                   =  2.0
        -- Temperature          = 10.0
        -- Closed       = Down  = On
        -- Open         = Up    = Off

if (timeofday['Daytime'] and time.hour > 11)
        then
                print('It is past sunrise, and after 11. monitoring variables for sunscreen')
                if (otherdevices['Zonnescherm_virtual'] == 'Open' ) then
                print ('Zonnescherm is up')
        else
                print ('Zonnescherm is down')
end

print("currentrain: "..currentrain)
print("temperature: "..temperature)
print("windspeed: "..windspeed)

currentrain = tonumber(currentrain)
temperature = tonumber(temperature)
windspeed = tonumber(windspeed)

if (otherdevices['Zonnescherm_virtual']   == 'Open'
        and regen         == 0
        and temperature         > 15
        and windspeed           < 50
	and time.hour		> 11)
        --and otherdevices['IemandThuis'] == 'On')

then
        print ('Sun is shining, all thresholds OK, lowering sunscreen')
        commandArray['SendNotification']='Zonnescherm#Zonnescherm gaat uit! --> De zon schijnt! Joepie!!! \rRegen: '..currentrain..'\rTemp: '..temperature..'\rWind: '..windspeed
        commandArray['Zonnescherm_virtual']='On'

        --elseif (otherdevices['Zonnescherm_virtual'] == 'Closed' and otherdevices['IemandThuis'] == 'Off') then
        --       print ('Nobody at home, raising sunscreen')
        --       commandArray['SendNotification']='Zonnescherm#Zonnescherm gaat naar binnen --> Niemand thuis!'
        --       commandArray['Zonnescherm_virtual']='Off'

        elseif (otherdevices['Zonnescherm_virtual'] == 'Closed' and regen > 0) then
                print ('It is raining, raising sunscreen')
                commandArray['SendNotification']='Zonnescherm#Zonnescherm gaat naar binnen --> Het gaat regenen!'
                commandArray['Zonnescherm_virtual']='Off'

        elseif (otherdevices['Zonnescherm_virtual'] == 'Closed' and temperature <= 15) then
                print ('Temperature too low, raising sunscreen')
                commandArray['SendNotification']='Zonnescherm#Zonnescherm gaat naar binnen --> Te koud'
                commandArray['Zonnescherm_virtual']='Off'

        --elseif (otherdevices['Zonnescherm_virtual'] == 'Closed' and uv < '1.0') then
        --        print ('Sun not shining too bright, raising sunscreen')
        --        commandArray['SendNotification']='Zonnescherm#Zonnescherm gaat naar binnen --> Zon schijnt niet voldoende'
        --        commandArray['Zonnescherm_virtual']='Off'

        elseif (otherdevices['Zonnescherm_virtual'] == 'Closed' and windspeed > 49) then
                print ('Windspeed too high, raising sunscreen')
                commandArray['SendNotification']='Zonnescherm#Zonnescherm gaat naar binnen --> Teveel wind'
                commandArray['Zonnescherm_virtual']='Off'
else
        print('Zonnescherm status OK --> No action')
end

elseif (timeofday['Nighttime']
        and otherdevices['Zonnescherm_virtual'] == 'Closed')
        then
                print('It is night, raising sunscreen')
                commandArray['SendNotification']='Zonnescherm#Zonnescherm naar binnen --> Zon gaat onder!'
                commandArray['Zonnescherm_virtual']='Off'
        else
                print('Zonnescherm already up --> No action')
end

return CommandArray

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 28 March 2015 14:54
by johnwulp
It also depends on several other devices:

The Wind, Temperatuur, Regen devices are from Forecast IO.
The IemandThuis device is a virtual one that i intend to use in the future. It switches on and off based on two bluetooth devices and a motion sensor.
The Zonnescherm_virtual device should be the actual sunscreen. In my case it's still a virtual one, when i'm happy with the code, i'll change it to the real sunscreen.

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 28 March 2015 15:19
by tlpeter
Thanks.

I do not have a weather station at the moment but I use weather underground at the moment.
There is a nice station near by but you will know that the weather can change quickly around the haringvliet.
I live on the other site of the water.

PS born and raised in spijkenisse.

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 28 March 2015 15:44
by johnwulp
Funny dat you live on the other side . I also don't have a weather station, that's why i use the forecast io. I've seen that rain is not very accurate. That's why this buienradar script comes in very handy!

Re: Is it gonna rain within the next X minutes?

Posted: Sunday 29 March 2015 12:06
by Mediacj
Thanks Hansbit for this nice script!!

I have implemented it on this way:
1. made a virtual humidity sensor (didn't know a better type)
2. made a time based lua script of it: script_time_rain.lua with both scripts together (see code below) within the code I update the virtual humidity device with the rain value, I also forward the humidity status which changes from dry to wet when the rain value is bigger then 0
3. change in the script the idx 125 of mine virtual device (in the update_device command) with your virtual humidity device idx
4. placed the lua script in the lua directory: /home/pi/domoticz/scripts/lua

Now you can use the value of this virtual humidity device to react on it in scripts or in blockly

Code: Select all

----------------------------------------------------------------------------------------------------------------
-- IsItGonnaRain( int minutesinfuture)
-- returns: int avarage rainfall for the next minutesinfuture
--
-- Function to get rain prediction from Buienradar.nl (dutch)
-- 
-- http://gratisweerdata.buienradar.nl/#Buienradar You may use their free service for non-commercial purposes. 
-- 
-- Written in LUA by Hans van der Heijden (h4nsie @ gmail.com)
-- Spring 2015
-- 28-03-2015 v0.3 bug: quotes around url added.
-- 27-03-2015 v0.2 return value is now average for next time
-- 26-03-2015 v0.1 Initial release
-- todo: some error checking on http and file handling (tmp file)
----------------------------------------------------------------------------------------------------------------
function IsItGonnaRain( minutesinfuture )

   -- config ---------------------------------------------------------
   lat='51.687895'   -- example lat/lon for Utrecht
   lon='5.057482'
   debug=false
   tempfilename = '/var/tmp/rain.tmp' -- can be anywhere writeable
   -- config ---------------------------------------------------------
         
   url='http://gps.buienradar.nl/getrr.php?lat='..lat..'&lon='..lon
   if debug then print(url) end
   read = os.execute('curl -s -o '..tempfilename..' "'..url..'"')
   file = io.open(tempfilename, "r")
   totalrain=0
   rainlines=0
   -- now analyse the received lines, format is like 000|15:30 per line.
   while true do 
      line = file:read("*line")
      if not line then break end
      if debug then print('Line:'..line) end
      linetime=string.sub(tostring(line), 5, 9)
      if debug then print('Linetime: '..linetime) end
         
         -- Linetime2 holds the full date calculated from the time on a line
         linetime2 = os.time{year=os.date('%Y'), month=os.date('%m'), day=os.date('%d'), hour=string.sub(linetime,1,2), min=string.sub(linetime,4,5), sec=os.date('%S')}
         difference = os.difftime (linetime2,os.time())
   
      -- When a line entry has a time in the future AND is in the given range, then totalize the rainfall
      if ((difference > 0) and (difference<=minutesinfuture*60)) then
         if debug then print('Line in time range found') end
         rain=tonumber(string.sub(tostring(line), 0, 3))
         totalrain = totalrain+rain
         rainlines=rainlines+1
         if debug then print('Rain in timerange: '..rain) end
         if debug then print('Total rain now: '..totalrain) end
      end
   
   end
   file:close()
   
   -- Returned value is average rain fall for next time
   -- 0 is no rain, 255 is very heavy rain
   -- When needed, mm/h is calculated by 10^((value -109)/32) (example: 77 = 0.1 mm/hour)
   averagerain=totalrain/rainlines
   
return(averagerain)
end



----- REGEN ------
commandArray = {}
minuten=15
regen = IsItGonnaRain(minuten)
print('Regen verwacht(0-255 hoe hoger hoe meer regen): '..regen..' binnen '..minuten..' minuten.')
if (regen > 0  ) then verw = 3 else verw = 2 end
commandArray['UpdateDevice'] = '125|'..tostring(regen)..'|'..tostring(verw)
return commandArray

Is it gonna rain within the next X minutes?

Posted: Sunday 29 March 2015 18:48
by Hansbit
Thanks all for the positive feedback on my script.

It's today a nice day to test this function.. :lol: rainfall 15mm!

Re: Is it gonna rain within the next X minutes?

Posted: Wednesday 01 April 2015 21:41
by niki_lauda
Mediacj wrote:Thanks Hansbit for this nice script!!

I have implemented it on this way:
1. made a virtual humidity sensor (didn't know a better type)
2. made a time based lua script of it: script_time_rain.lua with both scripts together (see code below) within the code I update the virtual humidity device with the rain value, I also forward the humidity status which changes from dry to wet when the rain value is bigger then 0
3. change in the script the idx 125 of mine virtual device (in the update_device command) with your virtual humidity device idx
4. placed the lua script in the lua directory: /home/pi/domoticz/scripts/lua

Now you can use the value of this virtual humidity device to react on it in scripts or in blockly
How do I create a virtual humidity device?

Re: Is it gonna rain within the next X minutes?

Posted: Thursday 02 April 2015 14:55
by Mediacj
1. go to setup tab
2. choose hardware
3. name: give it a name
4. type: Dummy (Does nothing, use for virtual switches only)
5. click on Add
6. now you have a new hardware device with the given name
7. choose 'Create Virtual Sensors' on the line of your new hardware device you just created
8. Sensor type: 'Humidity' and click OK
9. Go to the Setup tab again and now choose 'Devices'
10. there will be a new device with a green arrow on the end, click on the arrow and give your device a name
11. now you have the humidity device under the temperature tab

Re: Is it gonna rain within the next X minutes?

Posted: Thursday 02 April 2015 22:03
by niki_lauda
THX

Re: Is it gonna rain within the next X minutes?

Posted: Saturday 04 April 2015 17:34
by tlpeter
Hansbit wrote:Thanks all for the positive feedback on my script.

It's today a nice day to test this function.. :lol: rainfall 15mm!
Hi Hans,

I am running a Windows system with Domoticz.
Your script isn't working an i think because of some Linux commands.

The location /var/.... i have changed already.
What else needs to be changed?

Re: Is it gonna rain within the next X minutes?

Posted: Monday 06 April 2015 22:38
by Hansbit
tlpeter wrote:
Hansbit wrote: I am running a Windows system with Domoticz.
Your script isn't working an i think because of some Linux commands.

The location /var/.... i have changed already.
What else needs to be changed?
Hello tlpeter,

The 'curl' command is executed to get the url. That is not available in Windows.

Hans

Re: Is it gonna rain within the next X minutes?

Posted: Tuesday 07 April 2015 7:34
by tlpeter
Hi Hans i know, that is the problem :mrgreen:
I use a different script now and i have it working.
But thanks anyway.

Re: Is it gonna rain within the next X minutes?

Posted: Sunday 12 April 2015 14:20
by roblom
I added also a text device and filled it with the text from this script.

Code: Select all

function round(num, idp)
	local mult = 10^(idp or 0)
	return math.floor(num * mult + 0.5) / mult
end

----------------------------------------------------------------------------------------------------------
-- CommandArray
----------------------------------------------------------------------------------------------------------
commandArray = {}
	minuten=15
	RainPrediction = IsItGonnaRain(minuten)
	RainmmHour=10^((RainPrediction-109)/32)

	if (RainPrediction > 0  ) then
		verw = 3
		RainPredictionText=('Regen verwacht binnen '..minuten..' minuten, met ' ..round(RainmmHour, 1).. ' mm/uur')
	else 
		verw = 2
		RainPredictionText=('Geen regen verwacht binnen '..minuten..' minuten.')
	end
	commandArray[1] = {['UpdateDevice'] = RainDeviceIDX .. '|'..tostring(RainPrediction)..'|'..tostring(verw)}
	commandArray[2] = {['UpdateDevice'] = RainTextIDX .. '|0|' .. tostring(RainPredictionText)}

	print('-- Regen verwacht(0-255 hoe hoger hoe meer regen): '..RainPrediction..' binnen '..minuten..' minuten.')
	print('-- ' .. RainPredictionText )
return commandArray
RainTextIDX = the IDX of the text device.
And added a round function to display only 1 digit.

Re: Is it gonna rain within the next X minutes?

Posted: Monday 13 April 2015 23:32
by markk
tlpeter wrote:Hi Hans i know, that is the problem :mrgreen:
I use a different script now and i have it working.
But thanks anyway.
Hi Tlpeter

Would you mind sharing your windows script please?

Thanks
Mark