Is it gonna rain

From Domoticz
Jump to: navigation, search

Purpose

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. which covers The Netherlands, Belgium and might even work in Europe. One may use the Buienradar's free service for non-commercial purposes.

When the 1st script is implemented you will have a virtual switch which can be used to use notify or trigger a scene.
Rain expected.png

When the 2nd script is implemented you will have a text device which can be used in a dashboard.
Regen verwacht.png

Dependencies - hardware / software / operating system

This script depends on the website Buienradar (dutch) and will only work for coordinates (locations) in The Netherlands. Script is written in Lua to work on Linux systems.

Domoticz Setup - switches, variables, version

For the 1st script create a virtual switch (dummy device) with the name "Rain expected" For the 2nd script create a text device (dummy device) with the name "Regen verwacht"

Installation instructions

Copy this script in your domoticz\scripts\lua\ folder and name it script_time_rain.lua or place it in the Domoticz events system and set the parameters, lua and time.

For the 1st script edit the lat-lon in the config section to your location.

For the 2nd script edit the lat-lon and the IDX number

1st script - virtual switch

----------------------------------------------------------------------------------------------------------------
-- 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
-- 02-05-2018 v0.4 changed from curl to wget and added time-out.
-- 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.090737'	-- example lat/lon for Utrecht
	lon='5.121420'
	debug=false
	tempfilename = '/var/tmp/rain.tmp' -- can be anywhere writeable
	-- /config ---------------------------------------------------------
	
	
	url='https://gadgets.buienradar.nl/data/raintext?lat='..lat..'&lon='..lon
	if debug then print(url) end
	read = os.execute('wget -m 10 -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())
	
		if debug then print (difference) end
		-- 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

commandArray = {}
 
time = os.date("*t")
if ((time.min % 15)==0) then
   
   ----- REGEN ------
   minuten=20
   regen = IsItGonnaRain(minuten)
   print('Regen verwacht: '..regen..' mm binnen '..minuten..' minuten.')
   
    if regen > 70 and otherdevices['Rain expected']=='Off' then
      commandArray['SendNotification']='Regenscript#Regen verwacht'
      commandArray['Rain expected']='On'
    end
    if regen == 0 and otherdevices['Rain expected']=='On' then
       commandArray['SendNotification']='Regenscript#Geen regen meer verwacht'
       commandArray['Rain expected']='Off'
    end   
   
end 
 
return commandArray

2nd script - text device

local RainTextIDX = 19 -- your domoticz virtual TEXT device (add virtual text device first, if you didnt do this allready and use its idx)
debug = false -- enable or disable debug output
tempfilename = '/var/tmp/rain.tmp' -- be sure this is in the correct map, and give it chmod 0666
totalrain = 0
rainlines = 0

function IsItGonnaRain( minutesinfuture )
   url='http://gadgets.buienradar.nl/data/raintext/?lat=52.06&lon=4.39' -- NOTE: lat and lon should have max 2 decimals after comma to function (requirement Buienrader)
   if debug then print(url) end
   read = os.execute('curl -s -o '..tempfilename..' "'..url..'"')
   file = io.open(tempfilename, "r")

   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 = 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())

      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

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

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

   if (RainPrediction > 20  ) then
      verw = 3
      RainPredictionText=('('..round(RainmmHour, 1)..' mm) regen verwacht!')
   else 
      verw = 2
      RainPredictionText=('Voorlopig blijft het droog!')
   end
   
   commandArray[2] = {['UpdateDevice'] = RainTextIDX .. '|0|' .. tostring(RainPredictionText)}

return commandArray