Re: Is it gonna rain within the next X minutes?
Posted: Saturday 25 July 2015 12:20
Yes Jos. I already found it. The following line is missing in the script:
Code: Select all
commandArray = {}
Open source Home Automation System
https://forum.domoticz.com/
Code: Select all
commandArray = {}
When checking today's weather with the severe storm we have right now the reported value is 74, I think 70 is way to high. But I will investigate what is best for my situation.Hansbit wrote:With lower values to trigger for rain you'll get too many false positives. Even on sunny days with clear blue sky, Buienrader sometimes reports values like 35 or 40.jjnj wrote:Why a threshold for 70? Then it would already be raining right below 70? So that would be to late
Code: Select all
regenmm = 10 ^ ((regen - 109) / 32)
print('Regen verwacht: '..regenmm..' mm/uur binnen '..minuten..' minuten.')
Code: Select all
read = os.execute('curl -s -o '..tempfilename..' "'..url..'"')
print('curl -s -o '..tempfilename..' "'..url..'"');
You don't need te create the tempfile if the script is working.emke wrote:I can't get the os.execute command working. I created an tempfile and chmod it to 777 but it won't get updated. If i execute the curl command in the shell it's working. I also can't find a way to get some logging why the os.execute isn't working. What can i try to get working?
Code: Select all
read = os.execute('curl -s -o '..tempfilename..' "'..url..'"') print('curl -s -o '..tempfilename..' "'..url..'"');
Code: Select all
-- function to round numbers
function round(num, idp)
return tonumber(string.format("%." .. (idp or 0) .. "f", num))
end
-- RAIN ACTION SCRIPT
commandArray = {}
-- time variables
interval_min = 5
time = os.date("*t")
if ((time.min % interval_min)==0) then
----- rain variables ------
minutes=5
threshold=0.25
----- rain calculations ------
rain = IsItGonnaRain(minutes)
rainavg = 10^((rain-109)/32)
rainmmh = round(rainavg, 2)
----- rain actions ------
if rainmmh > threshold then
if (otherdevices['Canopy'] ~= 'Open') then
print(rainmmh..' mm/h rain expected in '..minutes..' minutes → switch canopy off!')
commandArray['Canopy']='Off'
else
print(rainmmh..' mm/h rain expected in '..minutes..' minutes, canopy is already off → all clear and dry!')
end
else
print(rainmmh..' mm/h rain expected in '..minutes..' minutes.')
end
end
return commandArray
I follow this list but I don't get it work. In the log I see that the script is working.Mediacj wrote: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
so that part is working fine. But now the virtual sensor is the part that goes wrong.2016-08-27 13:27:43.463 (Rain expected) Lighting 1 (Rain expected)
2016-08-27 13:30:00.724 LUA: Regen verwacht: 0 mm binnen 20 minuten.
2016-08-27 13:45:00.438 LUA: Regen verwacht: 0 mm binnen 20 minuten.
2016-08-27 14:00:00.639 LUA: Regen verwacht: 0 mm binnen 20 minuten.
2016-08-27 14:15:00.289 LUA: Regen verwacht: 0 mm binnen 20 minuten.
2016-08-27 14:30:00.516 LUA: Regen verwacht: 0 mm binnen 20 minuten.
2016-08-27 14:45:00.704 LUA: Regen verwacht: 0 mm binnen 20 minuten
I'm not sure what you meen? If you meen lon/lat? Yes I change that.jvdz wrote:Did you update the script with the proper Device to update?
Jos
Code: Select all
commandArray['UpdateDevice'] = '125|'..tostring(regen)..'|'..tostring(verw)
return commandArray
YES! it works! U used the script from the wiki page. But that line isn't in the script. So i added it to the script and it is working now!jvdz wrote:That dummy device has an IDX number which needs to changed in the script as well!
Look at these lines:Change 125 for the IDX of your dummy device.Code: Select all
commandArray['UpdateDevice'] = '125|'..tostring(regen)..'|'..tostring(verw) return commandArray
Jos
Code: Select all
-- =============================================================================================================
-- IsItGonnaRain( int minutesinfuture)
-- returns: int avarage rainfall for the next minutesinfuture
-- =============================================================================================================
-- Function to get rain prediction from Buienradar.nl (dutch)
-- Original script here: https://www.domoticz.com/wiki/Is_it_gonna_rain
--
-- 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)
----------------------------------------------------------------------------------------------------------------
-- Marco van Wijngaarden
-- 30-08-2016 v1.0 Adopted and updated the above scripts
-- 30-08-2016 v1.1 Updated the request URL, apparently buienrader is redirecting to different url
-- 30-08-2016 v1.2 Updated CURL to follow redirect and reverted (back to documented) request URL
--
----------------------------------------------------------------------------------------------------------------
-- Buienradar.nl --
---------------------
-- Gratis Weerdata --
--
-- Buienradar stelt gratis weerdata beschikbaar voor particulieren en bedrijven (website/intranet).
-- Het gebruik van onderstaande weerdata is alleen toegestaan voor niet-commerciële doeleinden.
-- Het gebruik voor mobiele toepassingen of commerciële doeleinden vereist toestemming van Buienradar, zie ook de Disclaimer.
-- Vraag hier toestemming aan voor het gebruik van de weerdata: http://www.buienradar.nl/overbuienradar/contact
-- Vragen, suggesties of een leuk idee? Neem contact met ons op en bouw mee aan Buienradar!
--
------------------------------------------------------------
-- Buienradar widget - Neerslagdata op basis van coördinaten
------------------------------------------------------------
--
-- Op basis van de door u gewenste coördinaten (latitude en longitude) kunt u de neerslag tot twee uur vooruit ophalen in tekstvorm.
-- De data wordt iedere 5 minuten geüpdatet.
-- Op deze pagina kunt u de neerslag in tekst vinden: http://gps.buienradar.nl/getrr.php?lat=51&lon=3
-- De waarde 0 geeft geen neerslag aan (droog), de waarde 255 geeft zware neerslag aan.
-- Gebruik de volgende formule voor het omrekenen naar de neerslagintensiteit in de eenheid millimeter per uur (mm/u):
-- Neerslagintensiteit = 10^((waarde-109)/32)
-- Ter controle: een waarde van 77 is gelijk aan een neerslagintensiteit van 0,1 mm/u.
--
-- =============================================================================================================
-- config ------------------------------------------------------------------------------------------------------
-- =============================================================================================================
--
-- Set your local position (latitude and longitude)
local latitude = uservariables['latitude'] -- your home latitude, set as a user variable
local longitude = uservariables['longitude'] -- your home longtitude, set as a user variable
-- timewindow for prediction
local minutesinfuture = 15 -- (int) minutes in future to calculate rain
-- threshold for switch (when do we actually call it rain and want to act accordingly)
local switchthreshold = 70 -- (int) value to toggle virtual switch
-- Rain switch (ON when rain above threshold, else OFF)
local rainswitchname = "Regen verwacht" -- (str) name for switch to toggle
-- Virtual device (txt) displays textual result
local idxRegenmmUur = 113 -- IDX for virtual (text) sensor
-- Show results in log
local debug = 1 -- 1 = ON or 0 = OFF
-- NMA notifications (only during the day)
local notify = false -- (bool) set 'false' or 'true'
-- URL for data rewquest
local requesturl = "http://gps.buienradar.nl/getrr.php"
-- redirects to "http://gadgets.buienradar.nl/data/raintext"
-- Where do we store the data (tmp) file
local tempfilename = "/home/pi/domoticz/scripts/tmp/rain.tmp"
-- default to activate script (set 'false' to run once every 5 minutes or 'true' to run every minute)
local active = false -- (bool) set 'false' or 'true'
--
-- =============================================================================================================
--
-- No edit required below this line
--
-- =============================================================================================================
--
-- execute (activate) every 5 minutes
local time = os.date("*t")
if ((time.min % 5)==0) then
-- set to active
active = true
end
--
-- =============================================================================================================
-- Functions ---------------------------------------------------------------------------------------------------
-- =============================================================================================================
-- function to split a string --
function splitString(str, delim, maxNb)
-- Eliminate bad cases...
if string.find(str, delim) == nil then
return { str }
end
if maxNb == nil or maxNb < 1 then
maxNb = 0 -- No limit
end
local result = {}
local pat = "(.-)" .. delim .. "()"
local nb = 0
local lastPos
for part, pos in string.gmatch(str, pat) do
nb = nb + 1
result[nb] = part
lastPos = pos
if nb == maxNb then break end
end
-- Handle the last field
if nb ~= maxNb then
result[nb + 1] = string.sub(str, lastPos)
end
return result
end
-- function to request rain data
function IsItGonnaRain(requesturl,latitude,longitude,tempfilename,minutesinfuture,debug)
local averagerain = 0
local totalrain = 0
local rainlines = 0
-- construct the request URL
local url = requesturl..'?lat='..latitude..'&lon='..longitude
-- print to log
if (debug == 1) then print("| Request URL .............. : " .. url) end
-- now get the data
local trigger_action = 'curl -Lo '..tempfilename..' "'..url..'"'
-- CURL options: -s for Silent (no error messages)
-- -o for Write output to file instead of stdout.
-- -L Follow redirects if the server reports that the requested page has moved (indicated with a Location: header and a 3XX response code)
handle = os.execute(trigger_action)
-- print request result to log
if (debug == 1) then
if handle then
print("| CURL Data request ........ : Success")
else
print("! CURL Data request ........ : Failed")
end
end
-- open file and process data
file = io.open(tempfilename, "r")
-- count datalines
local linenbr = 0
-- now analyse the received lines
while true do
line = file:read("*line")
if not line then break end
-- count received lines
linenbr = linenbr+1
-- line/data format is like 000|15:30 per line, we need to split the string
raindata = splitString(line,"|")
rain = tonumber(raindata[1])
linetime = raindata[2]
-- Linetime2 holds the full date calculated from the time on each 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')}
-- calculate the time difference between data/line and os time
difference = os.difftime (linetime2,os.time())
-- When a line entry has a time in the future AND is within the given range, then add/totalize the rainfall
if ((difference >= 0) and (difference <= minutesinfuture*60)) then
-- print (relevant) data to log
if (debug == 1) then print("| Rain data (line) ......... : " .. line) end
-- calculate totals
totalrain = totalrain+rain
rainlines = rainlines+1
end
end
-- close the file
file:close()
-- Returned value is average rain fall for next (int) 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)
averagerain = totalrain/rainlines
-- print summary to log
if (debug == 1) then
print("| Rain data received # lines : " .. linenbr)
print("| In timerange # lines ..... : " .. rainlines)
print("| Total rain ............... : " .. totalrain)
print("| Average rain calculated .. : " .. averagerain)
end
return(averagerain)
end
-- Functions to round a number to the given number of decimal places
-- returns result as string (text)
function round(num, idp)
return string.format("%." .. (idp or 0) .. "f", num)
end
-- returns result as a number
function round2number(num, idp)
return tonumber(string.format("%." .. (idp or 0) .. "f", num))
end
-- Note: If the number is rounded in order to be printed (as text) use function "round" (removed the tonumber function)
-- Converting to number then back to string would reintroduce rounding errors, so for numbers use "round2number" function
-- =============================================================================================================
-- Process -----------------------------------------------------------------------------------------------------
-- =============================================================================================================
commandArray = {}
-- start numbering at 1
indexArray=1
-- executes when active (every 5 minutes)
if (active) then
-- when debugging set to 1, writing to log starts here
if (debug == 1) then
print("+--------------------------------------------------+")
print("| =============== IS IT GONNA RAIN =============== |")
print("+--------------------------------------------------+")
end
-- rain variables
local regen = 0
local regenmmUur = 0
local rainstr = ""
-- execute function (for given future minutes)
regen = IsItGonnaRain(requesturl,latitude,longitude,tempfilename,minutesinfuture,debug)
-- round result
if (regen > 0) then
regen = round2number(regen, 0)
end
-- convert rain to mm/uur
if (regen > 0) then
regenmmUur = 10^((regen-109)/32)
regenmmUur = round(regenmmUur, 3)
end
-- textual result
if (regen > 0) then
rainstr = tostring("Regen verwacht: "..regen.." (".. regenmmUur.." mm/uur) binnen "..minutesinfuture.." minuten")
else
rainstr = tostring("Geen regen verwacht binnen komende "..minutesinfuture.." minuten")
end
-- write value to virtual (text) sensor
if ((idxRegenmmUur) and (regenmmUur)) then
commandArray[indexArray] = {['UpdateDevice'] = tostring(idxRegenmmUur)..'|0|'..rainstr}
indexArray=indexArray+1
end
-- when debugging set to 1, write to log
if (debug == 1) then
print("| Rain text ................ : " .. rainstr)
end
-- toggle switch ON
if regen > switchthreshold and otherdevices[rainswitchname]=='Off' then
-- send notification during the day
if (timeofday['Daytime']) and (notify) then
commandArray[indexArray] = {['SendNotification']=rainstr}
indexArray=indexArray+1
end
-- change switch to ON
commandArray[indexArray] = {[rainswitchname]='On'}
indexArray=indexArray+1
end
-- toggle switch OFF
if regen == 0 and otherdevices[rainswitchname] =='On' then
-- send notification during the day
if (timeofday['Daytime']) and (notify) then
commandArray[indexArray] = {['SendNotification']=rainstr}
indexArray=indexArray+1
end
-- change switch to OFF
commandArray[indexArray] = {[rainswitchname]='Off'}
indexArray=indexArray+1
end
-- logging end
if (debug == 1) then
print("+--------------------------------------------------+")
print("| --------------------- END ---------------------- |")
print("+--------------------------------------------------+")
end
end
return commandArray