Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
GitHub4Eddy committed Feb 19, 2022
1 parent cebf22a commit 451ce33
Showing 1 changed file with 1 addition and 0 deletions.
1 change: 1 addition & 0 deletions Buienradar_Rain-13.fqa
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"Buienradar Rain","type":"com.fibaro.multilevelSensor","apiVersion":"1.2","initialProperties":{"viewLayout":{"$jason":{"body":{"header":{"style":{"height":"0"},"title":"quickApp_device_719"},"sections":{"items":[{"components":[{"name":"labelBuienradar","style":{"weight":"1.2"},"text":"Buienradar Rain ","type":"label"},{"style":{"weight":"0.5"},"type":"space"}],"style":{"weight":"1.2"},"type":"vertical"},{"components":[{"name":"labelRainInfo","style":{"weight":"1.2"},"text":"Rain info","type":"label"},{"style":{"weight":"0.5"},"type":"space"}],"style":{"weight":"1.2"},"type":"vertical"}]}},"head":{"title":"quickApp_device_719"}}},"uiCallbacks":[],"quickAppVariables":[{"name":"intervalR","type":"string","value":"60"},{"name":"intervalD","type":"string","value":"300"},{"name":"maxLines","type":"string","value":"26"},{"name":"debugLevel","type":"string","value":"1"},{"name":"latitude","type":"string","value":"50"},{"name":"longitude","type":"string","value":"5"},{"name":"iconR","value":"0"},{"name":"iconE","value":"0"},{"name":"iconD","value":"0"}],"typeTemplateInitialized":true},"files":[{"name":"main","isMain":true,"isOpen":true,"content":"-- QuickApp BUIENRADAR RAIN \n\n-- This QuickApp predicts the rain in a part of Europe with data from the Buienradar, two hours in advance\n-- The value of this QuickApp represents the minutes until rain\n-- If there is no rain expected, the value is set to 0\n-- If it rains, the value is set to 999 and the amount of rain (mm/h) is shown\n-- Buienradar updates every 5 minutes with intervals of 5 minutes until 2 hours in advance. If rain is expected within the first predicted 5 minutes or less, the QuickApp assumes it is raining. \n-- If rain is expected or it rains, the interval for checking the Buienradar data (default without rain 300 seconds, equal to the Buienradar updates) is speed up (default 60 seconds) so the QuickApp value is updated more often\n-- With the value updated in this QuickApp, you are able to build and use your own scenes to notify, to close or open sunscreens, to close or open windows, etcetera \n\n\n-- Version 1.3 (19th February 2022)\n-- Added extra debug lines\n-- Small change in buildup labels\n\n\n-- Version 1.2 (8th January 2022)\n-- Buienradar changed the response with decimals and without leading zero's. Added some code to handle that. \n\n-- Version 1.1 (19th March 2021)\n-- Added Child Device for rainfall mm/h\n-- Added Quickapp variable for debug level (1=some, 2=few, 3=all). Recommended default value is 1. debuglevel 4 = Rain expected simalation. debugLevel = 5 Raining simulation\n-- Freed up some space (3 positions) in the presentation of the amount of rain \n-- Increased the default value of the maximum lines (maxLines) from 23 to 26\n-- Changed the unit in case of rain to empty\n\n-- Version 1.0 (25th October 2020)\n-- Added the possibility to change the icon according to rain, rain expected or dry. Three not mandatory quickapp variables are added to fill in with the icon number for rain, rain expected and dry. \n\n-- Version 0.3 (26th September 2020)\n-- Build an extra check for an incomplete Buienradar response (sometimes less than two hours)\n-- Added global variable maxLines to arrange the maximum amount of lines to indicate the amount of rain (one line for every 0.10mm rain) to fit the screen of your mobile device\n-- Decreased the default lines from 25 to 23 to show it right on an iPhone\n\n-- Version 0.2 (4th September 2020)\n-- Ready for the new Mobile App 1.9: Added visual level of rain (forecast) with thanks to @tinman from forum.fibaro.com\n-- Added warning for latitude and logitude settings where Buienradar Rain has (no) coverage\n\n-- Version 0.1 (15th August 2020)\n-- Initial version\n\n-- JSON data copyright: (C)opyright Buienradar / RTL. All rights reserved. \n-- JSON data terms: Deze feed mag vrij worden gebruikt onder voorwaarde van bronvermelding buienradar.nl inclusief een hyperlink naar https://www.buienradar.nl. Aan de feed kunnen door gebruikers of andere personen geen rechten worden ontleend.\n\n-- The value 000 indicates no rain (dry), the value 255 indicates heavy rain. \n-- Used formula for converting to the rain intensity in the unit millimetre per hour (mm/h): Rain intensity = 10^(value-109)/32)\n-- Example: a value of 77 is equal to a rain intensity of 0,1 ㎜/𝚑.\n\n-- Variables mandatory:\n-- intervalR = Number in seconds to update the data when rain expected or raining (must be different to IntervalD)\n-- intervalD = Number in seconds to update the data when no rain expected, Buienradar is updated every 300 seconds\n-- latitude = latitude of your location (Default is the latitude of your HC3)\n-- longitude = longitude of your location (Default is the longitude of your HC3)\n-- maxLines = number of | to indicate the amount of rain (one line for every 0.10mm rain)\n-- iconR = icon number for rain\n-- iconE = icon for rain expected\n-- iconD = icon number for dry\n\n\n-- Below here no changes are needed\n\n\nclass 'brRainfall'(QuickAppChild)\nfunction brRainfall:__init(dev)\n QuickAppChild.__init(self,dev)\n --self:trace(\"Buienradar brRainfall QuickappChild initiated, deviceId:\",self.id)\nend\nfunction brRainfall:updateValue(data) \n self:updateProperty(\"value\",tonumber(rainfall))\n self:updateProperty(\"unit\", \"mm/h\")\n self:updateProperty(\"log\", \"\")\nend\n\n\nlocal function getChildVariable(child,varName)\n for _,v in ipairs(child.properties.quickAppVariables or {}) do\n if v.name==varName then return v.value end\n end\n return \"\"\nend\n\n\n-- QuickApp functions\n\n\nfunction QuickApp:updateChildDevices() -- Update Child Devices\n for id,child in pairs(self.childDevices) do \n child:updateValue(data) \n end\nend\n\n\nfunction QuickApp:logging(level,text) -- Logging function for debug\n if tonumber(debugLevel) >= tonumber(level) then \n self:debug(text)\n end\nend\n\n\nfunction QuickApp:checkTestData() -- Test settings\n self:logging(3,\"QuickApp:checkTestData\")\n if debugLevel == 4 then\n apiResult = \"000|23:45 077|23:50 099|23:55 110|00:00 130|00:05 087|00:10 012|00:15 000|00:20 077|00:25 077|00:30 086|00:35 099|00:40 110|00:45 254|00:50 130|00:55 125|01:00 110|01:05 087|01:10 077|01:15 000|01:20 000|01:25 000|01:30 000|01:35 077|01:40\" -- Rain expected\n elseif debugLevel == 5 then\n apiResult = string.gsub(apiResult,\"000\",\"099\") -- Raining\n end\nend\n\n\nfunction QuickApp:lines(response) -- Setup for rain forecast view in labels\n self:logging(3,\"QuickApp:lines\")\n local mmh, amount, time, labelText, lines = \"\", \"\", \"\", \"\",\"\"\n local pos, i, numLines = 0, 1, 0\n local text = response:gsub(\" \", \", \")\n pos = string.find(text,\"|\")\n while pos ~= nil do -- Buienradar response covers sometimes less than 2 hours\n numLines = 0\n lines = \"\"\n amount = text:sub(pos-3,pos-1)\n time = text:sub(pos+1,pos+5)\n if amount == \"000\" then\n mmh = \"0.00\"\n else\n mmh = string.format(\"%.2f\",10^((tonumber(amount)-109)/32)) -- Calculate rain in milimeters / hour\n --self:logging(3,\"mmh: \" ..mmh)\n end\n numLines = math.floor(tonumber(mmh)*10)\n if tonumber(mmh) > (maxLines)/10 then\n if tonumber(mmh) > 9.9 then\n mmh = \"9.9+\"\n end\n numLines = maxLines+1\n end\n for i=1,numLines do\n lines = lines ..\"|\"\n end\n if lines:len() > maxLines then -- Add a \"+\" if lines is longer than maxLines\n lines = lines:sub(1,maxLines) ..\"+\"\n end\n self:logging(3,\"time: \" ..time ..\" mmh: \" ..mmh ..\" \" ..lines)\n labelText = labelText ..time ..\" \"..mmh ..\" ㎜/𝚑 \" ..lines ..\"\\n\"\n text = text:gsub(amount..\"|\", mmh ..\" \",1) \n pos = string.find(text,\"|\")\n end\n return labelText\nend\n\n\nfunction QuickApp:processRainData()\n self:logging(3,\"QuickApp:processRainData\")\n --local rainForecast = self:lines(apiResult) -- v1.2 \n --self:logging(3,\"rainForecast: \" ..rainForecast) -- v1.2 \n self:logging(3,\"apiResult 1: \" ..apiResult) -- v1.2 \n apiResult = apiResult:gsub(\",(.-)|\", \"|\") -- v1.2 Erase the komma and all decimals between the komma and pipeline character (Buienradar changed response since January 2022)\n self:logging(3,\"apiResult 2: \" ..apiResult) --v1.2 \n apiResult = apiResult:gsub(\"%s(%d%d)|\", function(s) return \" 0\"..s..\"|\" end) -- v1.2 Add a leading zero to all two digit rain data (Buienradar changed response since January 2022)\n if string.find(apiResult, \"|\" ) < 4 then -- v1.2 Add a leading zero in the first value if needed (Buienradar changed response since January 2022)\n apiResult = \"0\" ..apiResult --v1.2 \n end -- v1.2 \n self:logging(3,\"apiResult 3: \" ..apiResult) -- v1.2 \n local rainForecast = self:lines(apiResult) -- v1.2 Setup lines for labels\n self:logging(3,\"rainForecast: \" ..rainForecast) -- v1.2 \n apiResult = apiResult:gsub(\"000|\", \"\") -- Erase all non rain data\n self:logging(3,\"apiResult 4: \" ..apiResult) -- v1.2 \n local pos = string.find(apiResult, \"|\" ) -- Search for remaining rain data\n if pos ~= nil then -- There is rain (expected)\n self:logging(3,\"There is rain (expected)\")\n local rTime = apiResult:sub(pos+1,pos+5) -- Time expected rain\n local rTimeHour = tonumber(rTime:sub(1,2))\n local rTimeMinute = tonumber(rTime:sub(4,5))\n local currentTime = os.date(\"%H:%M\")\n local cTimeHour = tonumber(currentTime:sub(1,2))\n local cTimeMinute = tonumber(currentTime:sub(4,5))\n rainfall = \"0.00\"\n rainIntensity = string.format(\"%.2f\",10^((apiResult:sub(pos-4,pos-1)-109)/32)) -- Calculate rain intensity in milimeters / hour\n if rTimeHour < cTimeHour then -- Current time before and rain time after 24:00\n rTimeHour = rTimeHour + 24\n end\n local rMinute = (rTimeHour-cTimeHour)*60+(rTimeMinute-cTimeMinute) -- Minutes until rain\n interval = intervalR -- Speed up interval to intervalR when it rains\n if rMinute <= 5 then -- It is raining\n self:logging(3,\"It is raining\")\n rainfall = rainIntensity\n self:logging(2, \"It rains \" ..rainIntensity ..\" ㎜/𝚑 (\" ..rTime ..\")\")\n rainForecast = \"It rains \" ..rainIntensity ..\" ㎜/𝚑 (\" ..rTime ..\")\\n\\n\" ..rainForecast\n self:updateView(\"labelRainInfo\", \"text\", rainForecast)\n self:updateProperty(\"value\", 999)\n self:updateProperty(\"unit\", \"\")\n self:updateProperty(\"log\", \"Rain \" ..rainIntensity ..\" ㎜/𝚑 (\" ..rTime ..\")\")\n self:setIcon(\"rain\")\n else -- Rain expected\n self:logging(3,\"Rain expected\")\n rainfall = \"0.00\"\n self:logging(2, \"Rain expected in \" ..rMinute ..\" minutes at: \" ..rTime)\n rainForecast = \"Rain expected in \" ..rMinute ..\" minutes at: \" ..rTime ..\"\\n\\n\" ..rainForecast\n self:updateView(\"labelRainInfo\", \"text\", rainForecast)\n self:updateProperty(\"value\", rMinute)\n self:updateProperty(\"unit\", \" min\")\n self:updateProperty(\"log\", \"Rain at \" ..rTime)\n self:setIcon(\"expected\")\n end\n else -- No rain is expected\n self:logging(3,\"No rain expected\")\n rainfall = \"0.00\"\n if interval == intervalR then -- From rain (expected) to no rain expected\n self:logging(2, \"No more rain expected\")\n end\n interval = intervalD -- Decrease interval to intervalD when no rain expected \n local lastTime = apiResult:sub(apiResult:len()-6,apiResult:len())\n self:updateView(\"labelRainInfo\", \"text\", \"No rain expected until \" ..lastTime)\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"unit\", \"\")\n self:updateProperty(\"log\", \"No rain until \" ..lastTime) \n self:setIcon(\"dry\")\n end\n self:updateView(\"labelBuienradar\", \"text\", \" Buienradar Rain - LAT: \" ..latitude ..\" / \" ..\"LON: \" ..longitude) \n self:logging(2, \"Rainfall: \" ..rainfall) \n \n --for id,child in pairs(self.childDevices) do -- Update Child Devices\n -- child:updateValue(data) \n --end\nend\n\n\nfunction QuickApp:getRainData()\n self:logging(3,\"QuickApp:getRainData\")\n self.http:request(url, {\n options={\n headers = {Accept = \"application/json\"}, method = 'GET'}, success = function(response)\n self:logging(3, \"response status:\" ..response.status) \n self:logging(3, \"url: \" ..url)\n apiResult = response.data\n self:logging(3, \"apiResult: \" ..apiResult) \n \n if apiResult ~= nil and apiResult ~= \"\" then\n self:checkTestData() -- Check for test settings\n self:processRainData() -- Process the rain data in Views and Properties\n self:updateChildDevices() -- Update the child devices\n else\n self:warning(\"Temporarily no data from Buienradar Rain\")\n end\n\n end,\n error = function(error)\n self:error('error: ' .. json.encode(error))\n self:updateProperty(\"log\", \"error: \" ..json.encode(error))\n end\n}) \n fibaro.setTimeout(interval*1000, function() -- Checks every [interval] seconds for new data\n self:getRainData()\n end)\nend\n\n\nfunction QuickApp:getQuickAppVariables()\n url = \"https://br-gpsgadget.azurewebsites.net/data/raintext\"\n intervalR = tonumber(self:getVariable(\"intervalR\"))\n intervalD = tonumber(self:getVariable(\"intervalD\"))\n latitude = tonumber(self:getVariable(\"latitude\"))\n longitude = tonumber(self:getVariable(\"longitude\"))\n maxLines = tonumber(self:getVariable(\"maxLines\"))\n iconR = tonumber(self:getVariable(\"iconR\"))\n iconE = tonumber(self:getVariable(\"iconE\"))\n iconD = tonumber(self:getVariable(\"iconD\"))\n debugLevel = tonumber(self:getVariable(\"debugLevel\"))\n\n if intervalR == \"\" or intervalR == nil then -- Check existence of the mandatory variables, if not, create them with default values\n intervalR = \"60\" -- Default intervalR (rain expected or raining) is 60 seconds\n self:setVariable(\"intervalR\", intervalR)\n self:trace(\"Added QuickApp variable intervalR with default value \" ..intervalR)\n intervalR = tonumber(intervalR)\n end\n if intervalD == \"\" or intervalD == nil then\n intervalD = \"300\" -- Default intervalD (dry, no rain) is 300 seconds\n self:setVariable(\"intervalD\", intervalD)\n self:trace(\"Added QuickApp variable intervalD with default value \" ..intervalD)\n intervalD = tonumber(intervalD)\n end\n if latitude == 0 or latitude == nil then \n latitude = string.format(\"%.2f\",api.get(\"/settings/location\")[\"latitude\"]) -- Default latitude of your HC3\n self:setVariable(\"latitude\", latitude)\n self:trace(\"Added QuickApp variable latitude with default value \" ..latitude)\n end \n if longitude == 0 or longitude == nil then\n longitude = string.format(\"%.2f\",api.get(\"/settings/location\")[\"longitude\"]) -- Default longitude of your HC3\n self:setVariable(\"longitude\", longitude)\n self:trace(\"Added QuickApp variable longitude with default value \" ..longitude)\n end\n if maxLines == 0 or maxLines == nil then\n maxLines = \"26\" -- Default maxLines is 26 lines\n self:setVariable(\"maxLines\", maxLines)\n self:trace(\"Added QuickApp variable maxLines with default value \" ..maxLines)\n maxLines = tonumber(maxLines)\n end\n if iconR == \"\" or iconR == nil then \n iconR = \"0\" -- Default iconR (icon for rain) is 0 (no icon)\n self:setVariable(\"iconR\", iconR)\n self:trace(\"Added QuickApp variable iconR with default value \" ..iconR)\n iconR = tonumber(iconR)\n end\n if iconE == \"\" or iconE == nil then \n iconE = \"0\" -- Default iconE (icon for rain expected) is 0 (no icon)\n self:setVariable(\"iconE\", iconE)\n self:trace(\"Added QuickApp variable iconE with default value \" ..iconE)\n iconE = tonumber(iconE)\n end\n if iconD == \"\" or iconD == nil then \n iconD = \"0\" -- Default iconD (icon for dry, no rain) is 0 (no icon)\n self:setVariable(\"iconD\", iconD)\n self:trace(\"Added QuickApp variable iconD with default value \" ..iconD)\n iconD = tonumber(iconD)\n end\n if debugLevel == \"\" or debugLevel == nil then\n debugLevel = \"1\" -- Default value for debugLevel response in seconds\n self:setVariable(\"debugLevel\",debugLevel)\n self:trace(\"Added QuickApp variable debugLevel\")\n debugLevel = tonumber(debugLevel)\n end\n \n if maxLines > 99 then\n maxLines = 99 -- Maximum amount of lines is 99\n end\n\n interval = intervalD\n latitude = string.format(\"%.2f\",latitude) -- double check, to prevent 404 response\n longitude = string.format(\"%.2f\",longitude) -- double check, to prevent 404 response\n self:setIcon(\"dry\")\n\n url = url ..\"?lat=\" ..latitude ..\"&lon=\" ..longitude -- Combine webaddress and location info\n\n if tonumber(latitude) < 50 or tonumber(latitude) > 54 or tonumber(longitude) < 1 or tonumber(longitude) > 10 then -- Check for coverage of Buitenradar Rain (latitude 50-54 and longitude 1-10)\n self:warning(\"Current latitude = \"..latitude ..\" and longitude = \" ..longitude)\n self:warning(\"Buienradar Rain only works for latitude 50-54 and longitude 1-10\")\n self:warning(\"Check this url for response: \"..url) \n end\nend\n\n\nfunction QuickApp:setIcon(txt)\n if iconR ~= 0 and iconE ~= 0 and iconD ~= 0 then \n if txt == \"rain\" then \n self:updateProperty(\"deviceIcon\", iconR) -- set icon to rain\n elseif txt == \"expected\" then\n self:updateProperty(\"deviceIcon\", iconE) -- set icon to rain expected\n else \n self:updateProperty(\"deviceIcon\", iconD) -- set icon to dry\n end\n end\nend\n\n\nfunction QuickApp:setupChildDevices() -- Setup Child Devices\n local cdevs = api.get(\"/devices?parentId=\"..self.id) or {} -- Pick up all Child Devices\n function self:initChildDevices() end -- Null function, else Fibaro calls it after onInit()...\n\n if #cdevs == 0 then -- If no Child Devices, create them\n local initChildData = { \n {className=\"brRainfall\", name=\"Rainfall\", type=\"com.fibaro.multilevelSensor\", value=0, unit=\"mm/h\"},\n }\n for _,c in ipairs(initChildData) do\n local child = self:createChildDevice(\n {name = c.name,\n type=c.type,\n value=c.value,\n unit=c.unit,\n initialInterfaces = {},\n },\n _G[c.className] -- Fetch class constructor from class name\n )\n child:setVariable(\"className\",c.className) -- Save class name so we know when we load it next time\n end \n else \n for _,child in ipairs(cdevs) do\n local className = getChildVariable(child,\"className\") -- Fetch child class name\n local childObject = _G[className](child) -- Create child object from the constructor name\n self.childDevices[child.id]=childObject\n childObject.parent = self -- Setup parent link to device controller \n end\n end\nend\n\n\nfunction QuickApp:onInit()\n __TAG = fibaro.getName(plugin.mainDeviceId) ..\" ID:\" ..plugin.mainDeviceId\n self:debug(\"OnInit\") \n \n self:setupChildDevices()\n \n if not api.get(\"/devices/\"..self.id).enabled then\n self:warning(\"Device\", fibaro.getName(plugin.mainDeviceId), \"is disabled\")\n return\n end\n \n self:getQuickAppVariables() \n self.http = net.HTTPClient({8*1000})\n self:getRainData()\nend\n "}]}

0 comments on commit 451ce33

Please sign in to comment.