Re: buienradar lua script
Posted: Thursday 23 August 2018 10:53
nice



Code: Select all
-- BuienRadar Module
--
-- curl in os required!!
-- create dummy text device from dummy hardware 'Buien Radar'
-- create dummy rain sensor from dummy hardware 'BuienRadarMeter'
-- create dummy switch from dummy hardware for triggering screens etc based on rain
-- add as time based lua script
-- set your longitude & latitude below!
-- 2017-12-27 working version
-- 2017-12-28 trying to get the rain device working .. missing documentation ..
-- 2017-12-30 isolated the bug, i was overwriting the updatedevice .. should be ok now
-- 2018-03-28 updated buienradar url
-- 2018-04-02 added follow redirect for curl & fixed typo as tipped by gizmocuz
commandArray = {}
local myBuienRadarDevice='Buien Radar'
local myBuienRadarMeter='BuienRadarMeter'
local myBuienRadarFlg='flgBuienRadar'
-- longitude latitude
local lat='51.59'
local lon='4.77'
time = os.date("*t")
if time.min % 5 == 0 then
print('BuienRadar module')
function os.capture(cmd, rep) -- execute command to get site
-- rep is nr of repeats if result is empty
r = rep or 1
local s = ""
while ( s == "" and r > 0) do
r = r-1
local f = assert(io.popen(cmd, 'r'))
s = assert(f:read('*a'))
f:close()
end
if ( rep - r > 1 ) then
print("os.capture needed more than 1 call: " .. rep-r)
end
return s
end
-- get data from buienradar
local command = "curl --max-time 5 -L -s 'http://gpsgadget.buienradar.nl/data/raintext?lat=" .. lat .. "&lon=" .. lon .. "'"
-- print("command: " .. command)
local tmp = os.capture(command, 3)
-- print('buienRadar data:\n' .. tmp)
if ( tmp == "" ) then
print("buienRadar: Empty result from curl command")
else
-- analyse data
-- to mm/h 10^((waarde-109)/32)
function tomm(r)
return 10^((r-109)/32)
end
-- to string formatted
function tos(r, c)
c = c or 1
return string.format("%." .. c .. "f", r)
end
local c=0
local rainNow=0
local rainNowAvg = 0
local rainSoon = 0
local rainTime = ""
local rainMax = 0
for k,v in tmp:gmatch('(.-)|(.-)\r?\n') do
-- k is rain value, v is time
kn = tonumber(k)
if c<=1 then
if rainNow < kn then
rainNow = kn
end
if kn > 0 then
rainNowAvg = rainNowAvg + tomm(kn)/2
end
end
if c<=3 and rainSoon < kn then
rainSoon = kn
end
if rainTime == "" and kn > 0 then
rainTime = v
end
if kn > rainMax then
rainMax = kn
end
c = c+1
end
-- if c = 0 no data found!
if ( c == 0 ) then
print("buienRadar: Unparsable result from curl command")
else
if rainNow>0 then
tmp = "now; " .. tos(tomm(rainNow)) .. "mm/h"
if rainMax > rainNow then
tmp = tmp .. " upto " .. tos(tomm(rainMax)) .. "mm/h"
end
elseif rainSoon>0 then
tmp = "soon in 15mins; " .. tos(tomm(rainSoon)) .. "mm/h"
if rainMax > rainSoon then
tmp = tmp .. " upto " .. tos(tomm(rainMax)) .. "mm/h"
end
elseif rainTime ~= "" then
tmp = "expected @ " .. rainTime .. "; upto " .. tos(tomm(rainMax)) .. "mm/h"
else tmp = "No rain"
end
-- calculate totalrainfall using rainNowAvg as average of 2 next reports
-- print("buienRadarMeterOld: " .. otherdevices_svalues[myBuienRadarMeter])
local rainTot = tonumber(otherdevices_svalues[myBuienRadarMeter]:match("[^;]+;([^;]+)")) + rainNowAvg/12 -- /12 to acount for 5min measurements ?? ..
-- print("buienRadarDebug: rainNow=" .. tos(tomm(rainNow)) .. " rainNowAvg=" .. tos(rainNowAvg) .. " rainSoon=" ..
-- tos(tomm(rainSoon)) .. " rainTot=" .. tos(rainTot,2) .. " rainTime=" .. rainTime .. " rainMax=" .. tos(tomm(rainMax)))
local cmd = otherdevices_idx[myBuienRadarMeter] .. "|0|" .. tos(tomm(rainNow)*100,0) .. ";" .. tos(rainTot,2)
-- print("buienRadar: " .. cmd)
table.insert(commandArray, { ['UpdateDevice'] = cmd } ) -- table.insert needed to avoid overwriting with next updatedevice
-- write to text device
if otherdevices[myBuienRadarDevice] ~= tmp then
table.insert(commandArray, { ['UpdateDevice'] = otherdevices_idx[myBuienRadarDevice] .. '|0|' .. tmp })
-- trigger based when rainNow or rainSoon
if ( rainNow>0 or rainSoon>0 ) then
if otherdevices[myBuienRadarFlg] == "Off" then
commandArray[myBuienRadarFlg] = "On"
end
elseif otherdevices[myBuienRadarFlg] == "On" then
commandArray[myBuienRadarFlg] = "Off"
end
end
end -- unparsable
end -- empty result
end
return commandArray
Interesting, could you tell me how to set that up?jvdz wrote:I am running a buienradar LUA script as well, but am not running it with the Domoticz event systems as these type of script have to go to the internet to grab the information, so will slow down the single threaded process. So I am running it with crontab and use the JSON/API interface to update the Domoticz devices to avoid these issues and potential slowness of the event system.
Jos
Sure: this is the script I run via crontab and the info is in it. Let me know when you have questions.
Code: Select all
-------------------------------------------------------------------
--- Get rain info from buienradar for the next xx minutes
--- This is the crontab entry I have which creates the log file in /var/tmp. remember to have this cleaned regularly which I do daily.
--- Crontab task: */5 * * * * sudo lua /home/pi/domoticz/scripts/buienradar_rainprediction.lua >> /var/tmp/BRP.log
-- Start config ---------------------------------------------------------
lat='52.??'
lon='4.??'
-- use information for the next xx minutes to calculate the percentage for prediction
minutesinfuture=15
-- Domoticz server url
domoticzurl="http://192.168.xx.xx:8080"
-- IDX dummy rain device
DEVIDX=111
-- IDX dummy General Percentage device
PDEVIDX=222
debug=true
-- can be anywhere writeable
tempfilename = '/var/tmp/rain.tmp'
-- END config ---------------------------------------------------------
url='http://gadgets.buienradar.nl/data/raintext?lat='..lat..'&lon='..lon
if debug then print(url) end
read = os.execute('curl -Lo '..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
linetime=string.sub(tostring(line), 5, 9)
-- 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 >= 20) and (difference<=minutesinfuture*60)) then
rain=tonumber(string.sub(tostring(line), 0, 3))
totalrain = totalrain+rain
rainlines=rainlines+1
if debug then print('Rain in timerange: '..rain .. ' Total rain now: '..totalrain .. ' difference:' .. difference .. ' Line:' ..line ) 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)
if rainlines == 0 then
averagerain=0
else
averagerain=math.ceil(totalrain/rainlines)
end
function round(num, idp)
return tonumber(string.format("%." .. (idp or 0) .. "f", num))
end
-- Calculate the mm/h
calcmmh = round(10^((averagerain -109)/32),2)
if debug then print(os.date() .. " averagerain:" .. averagerain .. " calcmmh:" .. calcmmh) end
-- Update Domotics Device
url=domoticzurl..'/json.htm?type=command¶m=udevice&idx=' .. DEVIDX .. '&nvalue=0&svalue=' .. calcmmh .. ';' .. calcmmh
if debug then print(url) end
read = os.execute('curl -s "'..url..'"')
if debug then print(read) end
-- Update percentage regenkans Domotics Device
result = round(averagerain*0.392156862745098,2)
url=domoticzurl..'/json.htm?type=command¶m=udevice&idx=' .. PDEVIDX .. '&nvalue=0&svalue=' .. result
if debug then print(url) end
read = os.execute('curl -s "'..url..'"')
if debug then print(read) end
if debug then print('==> Rain chance: '..result .. '%') end
if debug then print('------------------------------------------------------------------------------------------------------------------------------------------') end
You created 2 rain devices but you need 1 rain device and 1 percentage device:
Code: Select all
000|14:30
000|14:35
000|14:40
000|14:45
113|14:50
131|14:55
132|15:00
132|15:05
133|15:10
134|15:15
135|15:20
131|15:25
092|15:30
092|15:35
000|15:40
077|15:45
092|15:50
092|15:55
099|16:00
077|16:05
000|16:10
000|16:15
000|16:20
000|16:25