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
-- 14-11-2016 v0.4 changed lat/lon to max 2 decmals after comma
-- 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.06'   -- example lat/lon for Den Haag
  lon='4.39'  -- NOTE: lat and lon should have max 2 decimals after comma to function (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
  -- isn't working sice 2016/08/29: url is changed in:
  url='http://gadgets.buienradar.nl/data/raintext?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

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