-
Notifications
You must be signed in to change notification settings - Fork 1
/
Tibber_Monitor-30.fqa
1 lines (1 loc) · 109 KB
/
Tibber_Monitor-30.fqa
1
{"name":"Tibber Monitor","type":"com.fibaro.genericDevice","apiVersion":"1.2","initialProperties":{"viewLayout":{"$jason":{"body":{"header":{"style":{"height":"0"},"title":"quickApp_device_595"},"sections":{"items":[{"components":[{"name":"label","style":{"weight":"1.2"},"text":"Label","type":"label","visible":true},{"style":{"weight":"0.5"},"type":"space"}],"style":{"weight":"1.2"},"type":"vertical"}]}},"head":{"title":"quickApp_device_595"}}},"uiCallbacks":[],"quickAppVariables":[{"name":"token","type":"string","value":"5K4MVS-OjfWhK_4yrjOlFe1F6kJXPVf7eQYggo8ebAE"},{"name":"homeNr","type":"string","value":"1"},{"name":"extraCost","type":"string","value":"0"},{"name":"secondsH","type":"string","value":"300"},{"name":"httpTimeout","type":"string","value":"10"},{"name":"debugLevel","type":"string","value":"1"},{"name":"GlobVarLevel","type":"string","value":"false"},{"name":"GlobVarPerc","type":"string","value":"false"},{"name":"setEnergyPanel","type":"string","value":"false"},{"name":"currentPrice","type":"string","value":"false"},{"name":"language","type":"string","value":"en"},{"name":"workaroundE01","type":"string","value":3.73},{"name":"workaroundC01","type":"string","value":2.288867875},{"name":"workaroundPnn","type":"string","value":0.9104000000000001},{"name":"workaroundP23","type":"string","value":0.7138}],"typeTemplateInitialized":true},"files":[{"name":"main","isMain":true,"isOpen":false,"content":"-- Quickapp Tibber Monitor main\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\nlocal function setColor(level) -- Set the color 🟢🟡🟠🔴🟣 based on the Tibber Price Level with setColor(pricelevel) \n if level == \"VERY CHEAP\" then\n return \"🟢\"\n elseif level == \"CHEAP\" then\n return \"🟡\"\n elseif level == \"NORMAL\" then \n return \"🟠\"\n elseif level == \"EXPENSIVE\" then \n return \"🔴\"\n else -- VERY EXPENSIVE and all others\n return \"🟣\"\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:setGlobalVariable(tag,res) -- Fill the Global Variables\n if api.get(\"/globalVariables/\"..tag) == nil then\n local responseData, status = api.post(\"/globalVariables/\",{value=(json.encode(res)),name=tag})\n self:trace(\"Global Variable created: \" ..tag ..\" / status: \" ..status) \n else\n local responseData, status = api.put(\"/globalVariables/\"..tag,{value=(json.encode(res))})\n end\nend\n\n\nfunction QuickApp:deleteGlobalVariable(tag) -- Delete the Global Variables\n if api.get(\"/globalVariables/\"..tag) then\n local responseData, status = api.delete(\"/globalVariables/\"..tag) \n self:trace(\"Global Variable deleted: \" ..tag ..\" / status: \" ..status)\n end\nend\n\n\nfunction QuickApp:updateChildDevices() -- Update Child Devices\n for id,child in pairs(self.childDevices) do \n child:updateValue(data) \n end\n self:logging(2,\"getValues() - Return to getValues())\")\nend\n\n\nfunction QuickApp:updateEnergyPanel() -- Update the Energy Panel price\n if setEnergyPanel then -- Insert prices in Energy Panel only if turned on\n self:logging(3,\"updateEnergyPanel() - Update the Energy Panel price\")\n local price = 0\n if currentPrice then \n price = tonumber(data.totalPrice) -- Use current Price for Energy Panel\n else\n price = tonumber(self:getVariable(\"workaroundPnn\")) -- Use previous hour Price for Energy Panel\n end\n self:logging(3,\"updateEnergyPanel\")\n local billingTariff = api.get(\"/energy/billing/tariff\") -- Get the current Tariff from the Energy Panel\n billingTariff.rate = price -- Replace billingTariff.rate with current (previous hour) kWh price\n local responseData, status = api.put(\"/energy/billing/tariff\", billingTariff) -- Write the new Tariff in the Energy Panel\n end\n self:updateChildDevices() \nend\n\n\nfunction QuickApp:updateProperties() -- Update the properties\n self:logging(3,\"updateProperties() - Update the properties\")\n --self:updateProperty(\"value\", 0) -- For future use\n --self:updateProperty(\"unit\", \"\") -- For future use\n self:updateProperty(\"log\", data.startsAt)\n --self:logging(2,\"getValues() - Return to getValues() and wait for the interval of \" ..interval ..\" seconds\")\n self:updateEnergyPanel()\nend\n\n\nfunction QuickApp:updateLabels() -- Update the labels\n self:logging(3,\"updateLabels() - Update the labels\")\n\n local labelText = \"\"\n if debugLevel == 4 then\n labelText = labelText ..translation[\"SIMULATION MODE\"] ..\"\\n\\n\"\n end\n \n labelText = labelText ..translation[\"Hourly Energy\"] ..\":\" ..\"\\n\"\n for n in pairs(jsonEnergy or {}) do\n labelText = labelText ..jsonEnergy[n].hour ..\" \" ..string.format(\"%.2f\",jsonEnergy[n].consumption) ..\" \" ..jsonEnergy[n].unit ..\" \" ..string.format(\"%.4f\",jsonEnergy[n].cost) ..\" \" ..data.currency ..\"\\n\"\n end\n labelText = labelText ..\"\\n\"\n \n labelText = labelText ..translation[\"Daily Energy\"] ..\": \" ..string.format(\"%.2f\",data.dEnergy) ..\" \" ..\"kWh\" ..\" \" ..string.format(\"%.2f\",data.dCost+(extraCost*data.dEnergy)) ..\" \" ..data.currency ..\"\\n\"\n labelText = labelText ..translation[\"Monthly Energy\"] ..\": \" ..string.format(\"%.2f\",data.mEnergy) ..\" \" ..\"kWh\" ..\" \" ..string.format(\"%.2f\",data.mCost+(extraCost*data.mEnergy)) ..\" \" ..data.currency ..\"\\n\"\n labelText = labelText ..translation[\"Yearly Energy\"] ..\": \" ..string.format(\"%.2f\",data.yEnergy) ..\" \" ..\"kWh\" ..\" \" ..string.format(\"%.2f\",data.yCost+(extraCost*data.yEnergy)) ..\" \" ..data.currency ..\"\\n\"\n labelText = labelText ..translation[\"Total Energy\"] ..\": \" ..string.format(\"%.2f\",data.tEnergy) ..\" \" ..\"kWh\" ..\" \" ..string.format(\"%.2f\",data.tCost+(extraCost*data.tEnergy)) ..\" \" ..data.currency ..\"\\n\\n\"\n\n labelText = labelText ..translation[\"Actual Price\"] ..\": \" ..string.format(\"%.4f\",data.totalPrice) ..\" \" ..data.currency ..\" (\" ..translation[data.level] ..\")\" ..\"\\n\"\n labelText = labelText ..translation[\"Nord Pool Spot price\"] ..\": \" ..string.format(\"%.4f\",data.spotPrice) ..\" \" ..data.currency ..\"\\n\" \n labelText = labelText ..translation[\"Tax\"] ..\": \" ..string.format(\"%.2f\",data.tax) ..\" \" ..data.currency ..\"\\n\" \n labelText = labelText ..translation[\"Extra cost\"] ..\": \" ..string.format(\"%.2f\",extraCost) ..\" \" ..data.currency ..\"\\n\"\n labelText = labelText ..translation[\"Last update\"] ..\": \" ..data.startsAt ..\"\\n\\n\"\n\n labelText = labelText ..translation[\"TODAY Prices\"] ..\":\" ..\"\\n\"\n labelText = labelText ..(data.minStartsAtTod or \"\") ..\" \" ..translation[\"Min\"] ..\": \" ..string.format(\"%.4f\",(data.minPriceTod or 0)) ..\" \" ..data.currency ..\" (\" ..(data.minPercentageTod or 0) ..\"% \" ..(translation[data.minLevelTod] or \"\") ..\")\" ..\"\\n\"\n labelText = labelText ..(data.maxStartsAtTod or \"\") ..\" \" ..translation[\"Max\"] ..\": \" ..string.format(\"%.4f\",(data.maxPriceTod or 0)) ..\" \" ..data.currency ..\" (\" ..(data.maxPercentageTod or 0) ..\"% \" ..(translation[data.maxLevelTod] or \"\") ..\")\" ..\"\\n\"\n labelText = labelText ..translation[\"Average\"] ..\": \" ..string.format(\"%.4f\",(data.avgPriceTod or 0)) ..\" \" ..data.currency ..\"\\n\\n\"\n\n for n in pairs(jsonPricesTod or {}) do\n labelText = labelText ..setColor(jsonPricesTod[n].level) ..jsonPricesTod[n].hour ..\" \" ..string.format(\"%.4f\",jsonPricesTod[n].total) ..\" \" ..data.currency ..\" (\" ..jsonPricesTod[n].percentage ..\"% \" ..translation[jsonPricesTod[n].level] ..\")\" ..\"\\n\"\n end\n \n labelText = labelText ..\"\\n\" ..translation[\"TOMORROW Prices\"] ..\":\" ..\"\\n\"\n if jsonPricesTom[1] then -- Check if the Tomorrow prices are available\n labelText = labelText ..(data.minStartsAtTom or \"\") ..\" \" ..translation[\"Min\"] ..\": \" ..string.format(\"%.4f\",(data.minPriceTom or 0)) ..\" \" ..data.currency ..\" (\" ..(data.minPercentageTom or 0) ..\"% \" ..(translation[data.minLevelTom] or \"\") ..\")\" ..\"\\n\"\n labelText = labelText ..(data.maxStartsAtTom or \"\") ..\" \" ..translation[\"Max\"] ..\": \" ..string.format(\"%.4f\",(data.maxPriceTom or 0)) ..\" \" ..data.currency ..\" (\" ..(data.maxPercentageTom or 0) ..\"% \" ..(translation[data.maxLevelTom] or \"\") ..\")\" ..\"\\n\"\n labelText = labelText ..translation[\"Average\"] ..\": \" ..string.format(\"%.4f\",(data.avgPriceTom or 0)) ..\" \" ..data.currency ..\"\\n\\n\"\n\n for n in pairs(jsonPricesTom or {}) do\n labelText = labelText ..setColor(jsonPricesTom[n].level) ..jsonPricesTom[n].hour ..\" \" ..string.format(\"%.4f\",jsonPricesTom[n].total) ..\" \" ..data.currency ..\" (\" ..jsonPricesTom[n].percentage ..\"% \" ..translation[jsonPricesTom[n].level] ..\")\" ..\"\\n\"\n end\n else\n labelText = labelText ..translation[\"Not yet available\"] \n end\n labelText = labelText ..\"\\n\\n\"\n\n self:updateView(\"label\", \"text\", labelText)\n self:logging(2,\"Label: \" ..labelText)\n self:updateProperties()\nend\n\n\nfunction QuickApp:calculatePrices(jsonTable) -- Calculate the prices\n self:logging(3,\"calculatePrices() - Calculate the prices\")\n \n local pattern = \"(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).(%d+)+(%d+):(%d+)\" --2021-12-23T17:00:00.000+01:00\n local runyear, runmonth, runday, runhour, runminute, runseconds = data.startsAt:match(pattern)\n local convertedTimestamp = os.time({year = runyear, month = runmonth, day = runday, hour = runhour, min = runminute, sec = runseconds})\n data.startsAt = os.date(\"%d-%m-%Y %H:%M\", convertedTimestamp)\n \n -- TODAY Price calculations \n \n data.avgPriceTod = 0 \n local hAmountTod = 0\n for hour in pairs(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today or {}) do -- Get the average price TODAY\n data.avgPriceTod = data.avgPriceTod + jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[hour].total\n hAmountTod = hAmountTod+1\n self:logging(3, \"hour: \" ..hour ..\" Today price: \" ..jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[hour].total ..\" data.avgPriceTod: \" ..data.avgPriceTod ..\" hAmountTod: \" ..hAmountTod)\n end\n data.avgPriceTod = tonumber(data.avgPriceTod) / hAmountTod -- Calculate the Today average price \n self:logging(3,\"data.avgPriceTod: \" ..data.avgPriceTod ..\" for: \" ..hAmountTod ..\" prices\")\n\n if jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today then \n for hour in pairs(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today or {}) do -- Insert all TODAYS prices to table jsonPricesTod\n table.insert(jsonPricesTod,{hour = string.format(\"%02d\",hour-1)..\":00\", total = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[hour].total, percentage = string.format(\"%.2f\",((jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[hour].total-data.avgPriceTod)/data.avgPriceTod)*100), level = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[hour].level:gsub(\"_\", \" \"), startsAt = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[hour].startsAt})\n end\n else --If Today prices are not there, set them all to zero\n jsonPricesTod = '[{\"total\":0,\"level\":\" \",\"startsAt\":\"\",\"percentage\":\"N/A\",\"hour\":\"00:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"01:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"02:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"03:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"04:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"05:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"06:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"07:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"08:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"09:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"10:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"11:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"12:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"13:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"14:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"15:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"16:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"17:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"18:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"19:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"20:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"21:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"22:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"23:00\"}]'\n end\n self:logging(3,\"Today Prices: \" ..json.encode(jsonPricesTod))\n\n for i=1,24 do -- Initialise the Global Variables for TODAY price levels\n if GlobVarLevel then \n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_level_h\" ..string.format(\"%02d\",i-1), \"\") -- Set global variables for Level\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_level_h\" ..string.format(\"%02d\",i-1), \"\") -- Delete global variables for Level\n end\n if GlobVarPerc then \n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_percentage_h\" ..string.format(\"%02d\",i-1), \"\") -- Set global variables for Percentage\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_percentage_h\" ..string.format(\"%02d\",i-1), \"\") -- Delete global variables for Percentage\n end\n end\n local n = 1\n for n in pairs(jsonPricesTod or {}) do -- Get the levels for Global Variables \n if n > 24 then -- Maximum 24 Global variables, just in case\n break\n end\n if GlobVarLevel then \n self:logging(3, \"Globalvar: tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_level_h\" ..string.format(\"%02d\",n-1) ..\" \" ..jsonPricesTod[n].level)\n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_level_h\" ..string.format(\"%02d\",n-1), jsonPricesTod[n].level) -- Set global variables for Level\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_level_h\" ..string.format(\"%02d\",n-1), jsonPricesTod[n].level) -- Delete global variables for Level\n end\n if GlobVarPerc then \n self:logging(3, \"Globalvar: tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_percentage_h\" ..string.format(\"%02d\",n-1) ..\" \" ..jsonPricesTod[n].percentage)\n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_percentage_h\" ..string.format(\"%02d\",n-1), jsonPricesTod[n].percentage) -- Set global variables for Percentage\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_today_percentage_h\" ..string.format(\"%02d\",n-1), jsonPricesTod[n].percentage) -- Delete global variables for Percentage\n end\n end\n\n data.minPriceTod = 999 -- Return to initial value to force new lowest Today price\n data.maxPriceTod = 0 -- Return to initial value to force new highest Today price\n for n in pairs(jsonPricesTod or {}) do -- Get the minimum and maximum Today price, percentage, level and hour\n if tonumber(jsonPricesTod[n].total) <= data.minPriceTod then\n data.minPriceTod = tonumber(jsonPricesTod[n].total)\n data.minPercentageTod = jsonPricesTod[n].percentage\n data.minLevelTod = jsonPricesTod[n].level\n data.minStartsAtTod = jsonPricesTod[n].hour\n end\n if tonumber(jsonPricesTod[n].total) >= data.maxPriceTod then\n data.maxPriceTod = tonumber(jsonPricesTod[n].total)\n data.maxPercentageTod = jsonPricesTod[n].percentage\n data.maxLevelTod = jsonPricesTod[n].level \n data.maxStartsAtTod = jsonPricesTod[n].hour\n end \n end\n \n -- TOMORROW Price calculations \n \n data.avgPriceTom = 0 \n local hAmountTom = 0\n for hour in pairs(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow or {}) do -- Get the average price TOMORROW\n data.avgPriceTom = data.avgPriceTom + jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow[hour].total\n hAmountTom = hAmountTom+1\n self:logging(3, \"hour: \" ..hour ..\" Tomorrow price: \" ..jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow[hour].total ..\" data.avgPriceTom: \" ..data.avgPriceTom ..\" hAmountTom: \" ..hAmountTom)\n end\n data.avgPriceTom = tonumber(data.avgPriceTom) / hAmountTom -- Calculate the Today average price \n self:logging(3,\"data.avgPriceTom: \" ..data.avgPriceTom ..\" for: \" ..hAmountTom ..\" prices\")\n if jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow then\n for hour in pairs(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow or {}) do -- Insert all TOMORROW prices to table jsonPricesTom\n table.insert(jsonPricesTom,{hour = string.format(\"%02d\",hour-1)..\":00\", total = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow[hour].total, percentage = string.format(\"%.2f\",((jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow[hour].total-data.avgPriceTom)/data.avgPriceTom)*100), level = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow[hour].level:gsub(\"_\", \" \"), startsAt = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.tomorrow[hour].startsAt})\n end\n else -- If Tomorrow prices are not there, set them all to zero\n jsonPricesTom = '[{\"total\":0,\"level\":\" \",\"startsAt\":\"\",\"percentage\":\"N/A\",\"hour\":\"00:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"01:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"02:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"03:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"04:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"05:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"06:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"07:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"08:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"09:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"10:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"11:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"12:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"13:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"14:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"15:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"16:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"17:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"18:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"19:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"20:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"21:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"22:00\"},{\"total\":0,\"level\":\" \",\"startsAt\":\" \",\"percentage\":\"N/A\",\"hour\":\"23:00\"}]'\n end\n self:logging(3,\"Tomorrow Prices: \" ..json.encode(jsonPricesTom))\n \n for i=1,24 do -- Initialise the Global Variables for TOMORROW price levels\n if GlobVarLevel then \n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_level_h\" ..string.format(\"%02d\",i-1), \"\") -- Set global variables for Level\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_level_h\" ..string.format(\"%02d\",i-1), \"\") -- Delete global variables for Level\n end\n if GlobVarPerc then \n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_percentage_h\" ..string.format(\"%02d\",i-1), \"\") -- Set global variables for Percentage\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_percentage_h\" ..string.format(\"%02d\",i-1), \"\") -- Delete global variables for Percentage\n end\n end\n n = 1\n for n in pairs(jsonPricesTom or {}) do -- Get the levels for Global Variables \n if n > 24 then -- Maximum 24 Global variables, just in case\n break\n end\n if GlobVarLevel then \n self:logging(3, \"Globalvar: tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_level_h\" ..string.format(\"%02d\",n-1) ..\" \" ..jsonPricesTom[n].level)\n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_level_h\" ..string.format(\"%02d\",n-1), jsonPricesTom[n].level) -- Set global variables for Level\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_level_h\" ..string.format(\"%02d\",n-1), jsonPricesTom[n].level) -- Delete global variables for Level\n end\n if GlobVarPerc then \n self:logging(3, \"Globalvar: tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_percentage_h\" ..string.format(\"%02d\",n-1) ..\" \" ..jsonPricesTom[n].percentage)\n self:setGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_percentage_h\" ..string.format(\"%02d\",n-1), jsonPricesTom[n].percentage) -- Set global variables for Percentage\n else\n self:deleteGlobalVariable(\"tibber_monitor_\" ..plugin.mainDeviceId ..\"_tomorrow_percentage_h\" ..string.format(\"%02d\",n-1), jsonPricesTom[n].percentage) -- Delete global variables for Percentage\n end\n end\n \n data.minPriceTom = 999 -- Return to initial value to force new lowest Tomorrow price\n data.maxPriceTom = 0 -- Return to initial value to force new highest Tomorrow price\n for n in pairs(jsonPricesTom or {}) do -- Get the minimum and maximum Tomorrow price, percentage, level and hour\n if tonumber(jsonPricesTom[n].total) <= data.minPriceTom then\n data.minPriceTom = tonumber(jsonPricesTom[n].total)\n data.minPercentageTom = jsonPricesTom[n].percentage\n data.minLevelTom = jsonPricesTom[n].level\n data.minStartsAtTom = jsonPricesTom[n].hour\n end\n if tonumber(jsonPricesTom[n].total) >= data.maxPriceTom then\n data.maxPriceTom = tonumber(jsonPricesTom[n].total)\n data.maxPercentageTom = jsonPricesTom[n].percentage\n data.maxLevelTom = jsonPricesTom[n].level \n data.maxStartsAtTom = jsonPricesTom[n].hour\n end \n end\n \n if os.date(\"%H\") == \"00\" then -- Workaround for previous hour price for Energy Panel\n self:setVariable(\"workaroundPnn\",tonumber(self:getVariable(\"workaroundP23\"))) -- Save the 23h price\n else\n self:setVariable(\"workaroundP23\",tonumber(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[23].total)) -- Save the 23h price\n self:setVariable(\"workaroundPnn\",tonumber(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.today[tonumber(os.date(\"%H\"))].total)) -- Save the hour-1 price\n end\n \n self:logging(3,\"data: \" ..json.encode(data))\n self:updateLabels()\nend\n\n\nfunction QuickApp:getValuesTotal(jsonTable) -- Get Total values from json file \n self:logging(3,\"getValuesTotal() - Get Total values from json file\")\n data.tEnergy = 0\n data.tCost = 0\n for year in pairs(jsonTable.data.viewer.homes[homeNr].yearly.nodes or {}) do -- Sum all years energy\n self:logging(3,\"year: \" ..tostring(year) ..\" Consumption: \" ..jsonTable.data.viewer.homes[homeNr].yearly.nodes[year].consumption ..\" Cost: \" ..jsonTable.data.viewer.homes[homeNr].yearly.nodes[year].cost)\n data.tEnergy = data.tEnergy + tonumber(jsonTable.data.viewer.homes[homeNr].yearly.nodes[year].consumption)\n data.tCost = data.tCost + tonumber(jsonTable.data.viewer.homes[homeNr].yearly.nodes[year].cost)\n end\n data.tEnergy = tonumber(data.tEnergy + data.yEnergy) -- Add last year values\n data.tCost = tonumber(data.tCost + data.yCost)\n self:logging(3,\"data.tEnergy: \" ..tostring(data.tEnergy) ..\" data.tCost: \" ..tostring(data.tCost))\n self:calculatePrices(jsonTable)\nend\n\n\nfunction QuickApp:getValuesYearly(jsonTable) -- Get Yearly values from json file \n self:logging(3,\"getValuesYearly() - Get Yearly values from json file\")\n data.yEnergy = 0\n data.yCost = 0\n for month in pairs(jsonTable.data.viewer.homes[homeNr].monthly.nodes or {}) do -- Sum all months energy of the year\n self:logging(3,\"month: \" ..tostring(month) ..\" Consumption: \" ..jsonTable.data.viewer.homes[homeNr].monthly.nodes[month].consumption ..\" Cost: \" ..jsonTable.data.viewer.homes[homeNr].monthly.nodes[month].cost)\n data.yEnergy = data.yEnergy + tonumber(jsonTable.data.viewer.homes[homeNr].monthly.nodes[month].consumption)\n data.yCost = data.yCost + tonumber(jsonTable.data.viewer.homes[homeNr].monthly.nodes[month].cost)\n end\n data.yEnergy = tonumber(data.yEnergy + data.mEnergy) -- Add last month values\n data.yCost = tonumber(data.yCost + data.mCost)\n self:logging(3,\"data.yEnergy: \" ..tostring(data.yEnergy) ..\" data.yCost: \" ..tostring(data.yCost))\n self:getValuesTotal(jsonTable)\nend\n\n\nfunction QuickApp:getValuesMonthly(jsonTable) -- Get Monthly values from json file \n self:logging(3,\"getValuesMonthly() - Get Monthly values from json file\")\n data.mEnergy = 0\n data.mCost = 0\n for day in pairs(jsonTable.data.viewer.homes[homeNr].daily.nodes or {}) do -- Sum all days energy of the month\n self:logging(3,\"day: \" ..tostring(day) ..\" Consumption: \" ..jsonTable.data.viewer.homes[homeNr].daily.nodes[day].consumption ..\" Cost: \" ..jsonTable.data.viewer.homes[homeNr].daily.nodes[day].cost)\n data.mEnergy = data.mEnergy + tonumber(jsonTable.data.viewer.homes[homeNr].daily.nodes[day].consumption)\n data.mCost = data.mCost + tonumber(jsonTable.data.viewer.homes[homeNr].daily.nodes[day].cost)\n end\n data.mEnergy = tonumber(data.mEnergy + data.dEnergy) -- Add last days values\n data.mCost = tonumber(data.mCost + data.dCost)\n self:logging(3,\"data.mEnergy: \" ..tostring(data.mEnergy) ..\" data.mCost: \" ..tostring(data.mCost))\n self:getValuesYearly(jsonTable)\nend\n\n\nfunction QuickApp:getValuesDaily(jsonTable) -- Get Daily values from json file \n self:logging(3,\"getValuesDaily() - Get Daily values from json file\")\n data.dEnergy = 0\n data.dCost = 0\n data.hEnergy = 0\n data.hCost = 0\n local loopCheck = 0\n for hour in pairs(jsonTable.data.viewer.homes[homeNr].hourly.nodes or {}) do -- Sum all hours energy of the day and insert energy in jsonEnergy\n \n table.insert(jsonEnergy, {hour = string.format(\"%02d\",hour-1)..\":00\", consumption = jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption, cost = jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].cost, unit = jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumptionUnit}) -- Insert hourly energy usage into jsonEnergy\n \n loopCheck = 1 -- Set loopCheck to 1 to know the loop worked (probably not between 00:00 and 01:00 because of an empty jsonTable.data.viewer.homes[homeNr].hourly.nodes)\n if hour == 1 then -- Workaround check for null value 00-01 hour consumption\n if jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption == 0 then\n self:logging(3, \"hour: \" ..hour ..\" Consumption (==0): \" ..self:getVariable(\"workaroundE01\") ..\" Cost: \" ..self:getVariable(\"workaroundC01\"))\n data.dEnergy = tonumber(self:getVariable(\"workaroundE01\")) -- Use workaround value 00-01 hour energy\n data.dCost = tonumber(self:getVariable(\"workaroundC01\")) -- Use workaround value 00-01 hour cost\n self:logging(2,\"Got null value from Tibber API for 00-01 hour energy and cost, using stored values instead\")\n else -- No null value 00-01 hour, use the value from the Tibber API and set workaround value 00-01 hour consumption\n self:logging(3, \"hour: \" ..hour ..\" Consumption (<>0): \" ..jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption ..\" Cost: \" ..jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].cost)\n data.dEnergy = tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption) \n data.dCost = tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].cost)\n self:setVariable(\"workaroundE01\",jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption) \n self:setVariable(\"workaroundC01\",jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].cost) \n end\n else -- Not 00-01 hour, no workaround checks necessary \n self:logging(3, \"hour: \" ..hour ..\" Consumption (not 00-01 hour): \" ..tostring(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption) ..\" Cost: \" ..jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].cost)\n data.dEnergy = data.dEnergy + tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption)\n data.dCost = data.dCost + tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].cost)\n end\n if hour == 1 then \n data.hEnergy = tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].consumption) or 0 -- If first hour new day, current consumption will be zero\n data.hCost = tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour].cost) or 0 -- If first hour new day, current cost will be zero\n else \n data.hEnergy = tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour-1].consumption) or 0 -- Previous hour consumption because running hour will be zero\n data.hCost = tonumber(jsonTable.data.viewer.homes[homeNr].hourly.nodes[hour-1].cost) or 0 -- Previous hour cost because running hour will be zero\n end\n end\n if loopCheck == 0 then -- It is just after midnight, there was no loop, workaroundE01 and workaroundC01 needs to be reset to zero\n self:setVariable(\"workaroundE01\",\"0\")\n self:setVariable(\"workaroundC01\",\"0\")\n end\n \n self:logging(3,\"jsonEnergy: \" ..json.encode(jsonEnergy))\n\n self:logging(2, \"workaroundE01: \" ..self:getVariable(\"workaroundE01\") ..\" workaroundC01: \" ..self:getVariable(\"workaroundC01\") ..\" data.hEnergy: \" ..tostring(data.hEnergy) ..\" data.hCost: \" ..tostring(data.hCost) ..\" data.dEnergy: \" ..tostring(data.dEnergy) ..\" data.dCost: \" ..tostring(data.dCost))\n self:getValuesMonthly(jsonTable)\nend\n\n\nfunction QuickApp:getValues(jsonTable) -- Get the values from json file \n self:logging(3,\"getValues() - Get the values from json file \")\n \n jsonPricesTod = {}\n jsonPricesTom = {}\n jsonEnergy = {}\n \n data.totalPrice = tonumber(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.current.total or 0) -- The total price (energy + taxes)\n data.spotPrice = tonumber(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.current.energy or 0) -- Nord Pool spot price\n data.tax = tonumber(jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.current.tax or 0) -- The tax part of the price (guarantee of origin certificate, energy tax (Sweden only) and VAT)\n data.startsAt = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.current.startsAt or \"\" -- The start time of the price\n data.currency = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.current.currency or \"\" -- The price currency\n data.level = jsonTable.data.viewer.homes[homeNr].currentSubscription.priceInfo.current.level:gsub(\"_\", \" \") -- The price level compared to recent price values\n self:getValuesDaily(jsonTable)\nend\n\n\nfunction QuickApp:simData() -- Simulate Tibber Platform\n self:logging(3,\"simData() - Simulate Tibber Platform\")\n data = os.date(\"*t\")\n local apiResult = '{\"data\":{\"viewer\":{\"homes\":[{\"hourly\":{\"nodes\":[{\"from\":\"2023-04-10T00:00:00.000+02:00\",\"to\":\"2023-04-10T01:00:00.000+02:00\",\"cost\":2.1127347,\"unitPrice\":0.6543,\"unitPriceVAT\":0.13086,\"consumption\":3.229,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T01:00:00.000+02:00\",\"to\":\"2023-04-10T02:00:00.000+02:00\",\"cost\":1.5796228125,\"unitPrice\":0.6460625,\"unitPriceVAT\":0.1292125,\"consumption\":2.445,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T02:00:00.000+02:00\",\"to\":\"2023-04-10T03:00:00.000+02:00\",\"cost\":1.54106435,\"unitPrice\":0.664825,\"unitPriceVAT\":0.132965,\"consumption\":2.318,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T03:00:00.000+02:00\",\"to\":\"2023-04-10T04:00:00.000+02:00\",\"cost\":2.003935725,\"unitPrice\":0.685575,\"unitPriceVAT\":0.137115,\"consumption\":2.923,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T04:00:00.000+02:00\",\"to\":\"2023-04-10T05:00:00.000+02:00\",\"cost\":1.332887025,\"unitPrice\":0.7097375,\"unitPriceVAT\":0.1419475,\"consumption\":1.878,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T05:00:00.000+02:00\",\"to\":\"2023-04-10T06:00:00.000+02:00\",\"cost\":1.4337473,\"unitPrice\":0.7663,\"unitPriceVAT\":0.15326,\"consumption\":1.871,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T06:00:00.000+02:00\",\"to\":\"2023-04-10T07:00:00.000+02:00\",\"cost\":0.9455179875,\"unitPrice\":0.8102125,\"unitPriceVAT\":0.1620425,\"consumption\":1.167,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T07:00:00.000+02:00\",\"to\":\"2023-04-10T08:00:00.000+02:00\",\"cost\":0.02978315,\"unitPrice\":0.80495,\"unitPriceVAT\":0.16099,\"consumption\":0.037,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T08:00:00.000+02:00\",\"to\":\"2023-04-10T09:00:00.000+02:00\",\"cost\":0,\"unitPrice\":0.8267,\"unitPriceVAT\":0.16534,\"consumption\":0,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T09:00:00.000+02:00\",\"to\":\"2023-04-10T10:00:00.000+02:00\",\"cost\":0,\"unitPrice\":0.80155,\"unitPriceVAT\":0.16031,\"consumption\":0,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T10:00:00.000+02:00\",\"to\":\"2023-04-10T11:00:00.000+02:00\",\"cost\":0,\"unitPrice\":0.5076375,\"unitPriceVAT\":0.1015275,\"consumption\":0,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T11:00:00.000+02:00\",\"to\":\"2023-04-10T12:00:00.000+02:00\",\"cost\":0,\"unitPrice\":0.30965,\"unitPriceVAT\":0.06193,\"consumption\":0,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-10T12:00:00.000+02:00\",\"to\":\"2023-04-10T13:00:00.000+02:00\",\"cost\":0,\"unitPrice\":0.30525,\"unitPriceVAT\":0.06105,\"consumption\":0,\"consumptionUnit\":\"kWh\"}]},\"daily\":{\"nodes\":[{\"from\":\"2023-04-01T00:00:00.000+02:00\",\"to\":\"2023-04-02T00:00:00.000+02:00\",\"cost\":54.433290825,\"unitPrice\":0.649283,\"unitPriceVAT\":0.129857,\"consumption\":83.836,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-02T00:00:00.000+02:00\",\"to\":\"2023-04-03T00:00:00.000+02:00\",\"cost\":44.405446125,\"unitPrice\":0.794871,\"unitPriceVAT\":0.158974,\"consumption\":55.865,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-03T00:00:00.000+02:00\",\"to\":\"2023-04-04T00:00:00.000+02:00\",\"cost\":51.806174375,\"unitPrice\":1.434995,\"unitPriceVAT\":0.286999,\"consumption\":36.102,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-04T00:00:00.000+02:00\",\"to\":\"2023-04-05T00:00:00.000+02:00\",\"cost\":84.6181242875,\"unitPrice\":1.655543,\"unitPriceVAT\":0.331109,\"consumption\":51.112,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-05T00:00:00.000+02:00\",\"to\":\"2023-04-06T00:00:00.000+02:00\",\"cost\":121.5749948625,\"unitPrice\":1.525542,\"unitPriceVAT\":0.305108,\"consumption\":79.693,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-06T00:00:00.000+02:00\",\"to\":\"2023-04-07T00:00:00.000+02:00\",\"cost\":87.99027765,\"unitPrice\":1.331834,\"unitPriceVAT\":0.266367,\"consumption\":66.067,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-07T00:00:00.000+02:00\",\"to\":\"2023-04-08T00:00:00.000+02:00\",\"cost\":63.549446975,\"unitPrice\":0.898378,\"unitPriceVAT\":0.179676,\"consumption\":70.738,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-08T00:00:00.000+02:00\",\"to\":\"2023-04-09T00:00:00.000+02:00\",\"cost\":49.836638425,\"unitPrice\":0.791322,\"unitPriceVAT\":0.158264,\"consumption\":62.979,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-04-09T00:00:00.000+02:00\",\"to\":\"2023-04-10T00:00:00.000+02:00\",\"cost\":27.7669614875,\"unitPrice\":0.865311,\"unitPriceVAT\":0.173062,\"consumption\":32.089,\"consumptionUnit\":\"kWh\"}]},\"monthly\":{\"nodes\":[{\"from\":\"2023-01-01T00:00:00.000+01:00\",\"to\":\"2023-02-01T00:00:00.000+01:00\",\"cost\":2553.0526192875,\"unitPrice\":1.148209,\"unitPriceVAT\":0.229642,\"consumption\":2223.508,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-02-01T00:00:00.000+01:00\",\"to\":\"2023-03-01T00:00:00.000+01:00\",\"cost\":1971.4661446375,\"unitPrice\":1.055717,\"unitPriceVAT\":0.211143,\"consumption\":1867.419,\"consumptionUnit\":\"kWh\"},{\"from\":\"2023-03-01T00:00:00.000+01:00\",\"to\":\"2023-04-01T00:00:00.000+02:00\",\"cost\":2034.4427701625,\"unitPrice\":1.06202,\"unitPriceVAT\":0.212404,\"consumption\":1915.635,\"consumptionUnit\":\"kWh\"}]},\"yearly\":{\"nodes\":[{\"from\":\"2018-01-01T00:00:00.000+01:00\",\"to\":\"2019-01-01T00:00:00.000+01:00\",\"cost\":3834.59033825,\"unitPrice\":0.735441,\"unitPriceVAT\":0.147088,\"consumption\":5214,\"consumptionUnit\":\"kWh\"},{\"from\":\"2019-01-01T00:00:00.000+01:00\",\"to\":\"2020-01-01T00:00:00.000+01:00\",\"cost\":14163.34488325,\"unitPrice\":0.60518,\"unitPriceVAT\":0.121036,\"consumption\":23403.52,\"consumptionUnit\":\"kWh\"},{\"from\":\"2020-01-01T00:00:00.000+01:00\",\"to\":\"2021-01-01T00:00:00.000+01:00\",\"cost\":4367.1817285375,\"unitPrice\":0.314652,\"unitPriceVAT\":0.06293,\"consumption\":13879.419,\"consumptionUnit\":\"kWh\"},{\"from\":\"2021-01-01T00:00:00.000+01:00\",\"to\":\"2022-01-01T00:00:00.000+01:00\",\"cost\":18724.9354599375,\"unitPrice\":0.957861,\"unitPriceVAT\":0.191572,\"consumption\":19548.706,\"consumptionUnit\":\"kWh\"},{\"from\":\"2022-01-01T00:00:00.000+01:00\",\"to\":\"2023-01-01T00:00:00.000+01:00\",\"cost\":26246.8039997125,\"unitPrice\":1.594865,\"unitPriceVAT\":0.318973,\"consumption\":16457.069,\"consumptionUnit\":\"kWh\"}]},\"currentSubscription\":{\"status\":\"running\",\"priceInfo\":{\"current\":{\"total\":0.2595,\"energy\":0.1136,\"tax\":0.1459,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T13:00:00.000+02:00\"},\"today\":[{\"total\":0.6543,\"energy\":0.4294,\"tax\":0.2249,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T00:00:00.000+02:00\"},{\"total\":0.6461,\"energy\":0.4228,\"tax\":0.2233,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T01:00:00.000+02:00\"},{\"total\":0.6648,\"energy\":0.4379,\"tax\":0.2269,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T02:00:00.000+02:00\"},{\"total\":0.6856,\"energy\":0.4545,\"tax\":0.2311,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T03:00:00.000+02:00\"},{\"total\":0.7097,\"energy\":0.4738,\"tax\":0.2359,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T04:00:00.000+02:00\"},{\"total\":0.7663,\"energy\":0.519,\"tax\":0.2473,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T05:00:00.000+02:00\"},{\"total\":0.8102,\"energy\":0.5542,\"tax\":0.256,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-10T06:00:00.000+02:00\"},{\"total\":0.805,\"energy\":0.55,\"tax\":0.255,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-10T07:00:00.000+02:00\"},{\"total\":0.8267,\"energy\":0.5674,\"tax\":0.2593,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-10T08:00:00.000+02:00\"},{\"total\":0.8016,\"energy\":0.5472,\"tax\":0.2544,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-10T09:00:00.000+02:00\"},{\"total\":0.5076,\"energy\":0.3121,\"tax\":0.1955,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T10:00:00.000+02:00\"},{\"total\":0.3096,\"energy\":0.1537,\"tax\":0.1559,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T11:00:00.000+02:00\"},{\"total\":0.3052,\"energy\":0.1502,\"tax\":0.155,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T12:00:00.000+02:00\"},{\"total\":0.2595,\"energy\":0.1136,\"tax\":0.1459,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T13:00:00.000+02:00\"},{\"total\":0.1425,\"energy\":0.02,\"tax\":0.1225,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T14:00:00.000+02:00\"},{\"total\":0.1489,\"energy\":0.0251,\"tax\":0.1238,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T15:00:00.000+02:00\"},{\"total\":0.1769,\"energy\":0.0475,\"tax\":0.1294,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T16:00:00.000+02:00\"},{\"total\":0.4805,\"energy\":0.2904,\"tax\":0.1901,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T17:00:00.000+02:00\"},{\"total\":0.6651,\"energy\":0.4381,\"tax\":0.227,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T18:00:00.000+02:00\"},{\"total\":0.7534,\"energy\":0.5087,\"tax\":0.2447,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-10T19:00:00.000+02:00\"},{\"total\":0.6308,\"energy\":0.4107,\"tax\":0.2201,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T20:00:00.000+02:00\"},{\"total\":0.4896,\"energy\":0.2977,\"tax\":0.1919,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-10T21:00:00.000+02:00\"},{\"total\":0.3304,\"energy\":0.1703,\"tax\":0.1601,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T22:00:00.000+02:00\"},{\"total\":0.1601,\"energy\":0.0341,\"tax\":0.126,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-10T23:00:00.000+02:00\"}],\"tomorrow\":[{\"total\":0.1387,\"energy\":0.0169,\"tax\":0.1218,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-11T00:00:00.000+02:00\"},{\"total\":0.1316,\"energy\":0.0113,\"tax\":0.1203,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-11T01:00:00.000+02:00\"},{\"total\":0.1277,\"energy\":0.0082,\"tax\":0.1195,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-11T02:00:00.000+02:00\"},{\"total\":0.133,\"energy\":0.0124,\"tax\":0.1206,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-11T03:00:00.000+02:00\"},{\"total\":0.2069,\"energy\":0.0715,\"tax\":0.1354,\"currency\":\"SEK\",\"level\":\"VERY_CHEAP\",\"startsAt\":\"2023-04-11T04:00:00.000+02:00\"},{\"total\":0.5888,\"energy\":0.377,\"tax\":0.2118,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-11T05:00:00.000+02:00\"},{\"total\":0.6732,\"energy\":0.4446,\"tax\":0.2286,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T06:00:00.000+02:00\"},{\"total\":0.7805,\"energy\":0.5304,\"tax\":0.2501,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T07:00:00.000+02:00\"},{\"total\":0.8875,\"energy\":0.616,\"tax\":0.2715,\"currency\":\"SEK\",\"level\":\"EXPENSIVE\",\"startsAt\":\"2023-04-11T08:00:00.000+02:00\"},{\"total\":0.8672,\"energy\":0.5998,\"tax\":0.2674,\"currency\":\"SEK\",\"level\":\"EXPENSIVE\",\"startsAt\":\"2023-04-11T09:00:00.000+02:00\"},{\"total\":0.6858,\"energy\":0.4547,\"tax\":0.2311,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T10:00:00.000+02:00\"},{\"total\":0.5676,\"energy\":0.3601,\"tax\":0.2075,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-11T11:00:00.000+02:00\"},{\"total\":0.5571,\"energy\":0.3517,\"tax\":0.2054,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-11T12:00:00.000+02:00\"},{\"total\":0.5288,\"energy\":0.329,\"tax\":0.1998,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-11T13:00:00.000+02:00\"},{\"total\":0.4825,\"energy\":0.292,\"tax\":0.1905,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-11T14:00:00.000+02:00\"},{\"total\":0.5081,\"energy\":0.3124,\"tax\":0.1957,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-11T15:00:00.000+02:00\"},{\"total\":0.6196,\"energy\":0.4017,\"tax\":0.2179,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T16:00:00.000+02:00\"},{\"total\":0.7991,\"energy\":0.5453,\"tax\":0.2538,\"currency\":\"SEK\",\"level\":\"EXPENSIVE\",\"startsAt\":\"2023-04-11T17:00:00.000+02:00\"},{\"total\":0.7546,\"energy\":0.5097,\"tax\":0.2449,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T18:00:00.000+02:00\"},{\"total\":0.6941,\"energy\":0.4613,\"tax\":0.2328,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T19:00:00.000+02:00\"},{\"total\":0.6773,\"energy\":0.4479,\"tax\":0.2294,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T20:00:00.000+02:00\"},{\"total\":0.6572,\"energy\":0.4317,\"tax\":0.2255,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T21:00:00.000+02:00\"},{\"total\":0.6165,\"energy\":0.3992,\"tax\":0.2173,\"currency\":\"SEK\",\"level\":\"NORMAL\",\"startsAt\":\"2023-04-11T22:00:00.000+02:00\"},{\"total\":0.5713,\"energy\":0.363,\"tax\":0.2083,\"currency\":\"SEK\",\"level\":\"CHEAP\",\"startsAt\":\"2023-04-11T23:00:00.000+02:00\"}]}}}]}}}'\n \n local jsonTable = json.decode(apiResult) -- Decode the json string from api to lua-table \n \n self:getValues(jsonTable)\n\n local interval = (3600 + tonumber(self:getVariable(\"secondsH\"))) - (os.date(\"%M\") * 60 + os.date(\"%S\"))\n self:logging(3,\"SetTimeout \" ..interval ..\" seconds\")\n fibaro.setTimeout(interval*1000, function() \n self:simData()\n end)\nend\n\n\nfunction QuickApp:getData() -- Get the data from Tibber\n self:logging(3,\"getData() - Get the data from Tibber\")\n data = os.date(\"*t\")\n local url = \"https://api.tibber.com/v1-beta/gql\"\n local requestBody = '{\"query\": \"{viewer {homes {hourly: consumption(resolution: HOURLY, last: ' ..data.hour ..') {nodes {from to cost unitPrice unitPriceVAT consumption consumptionUnit}}daily: consumption(resolution: DAILY, last: ' ..data.day-1 ..') {nodes {from to cost unitPrice unitPriceVAT consumption consumptionUnit}}monthly: consumption(resolution: MONTHLY, last: ' ..data.month-1 ..') {nodes {from to cost unitPrice unitPriceVAT consumption consumptionUnit}}yearly: consumption(resolution: ANNUAL, last: ' ..data.year-2000 ..') {nodes {from to cost unitPrice unitPriceVAT consumption consumptionUnit}}currentSubscription {status priceInfo {current {total energy tax currency level startsAt}today {total energy tax currency level startsAt}tomorrow {total energy tax currency level startsAt}}}}}}\"}'\n \n self:logging(3,\"requestBody: \" ..requestBody)\n\n http:request(url, {\n options = {\n data = requestBody,\n method = \"POST\",\n headers = {\n [\"Content-Type\"] = \"application/json\",\n [\"Accept\"] = \"application/json\",\n [\"Authorization\"] = \"Bearer \" ..self:getVariable(\"token\") ,\n [\"User-Agent\"] = \"Tibber_Monitor/3.0 Fibaro/HC3 Firmware/\" ..api.get(\"/settings/info\").softVersion -- New Tibber user-agent\n }\n },\n success = function(response) \n self:logging(3,\"response status: \" ..response.status)\n self:logging(3,\"headers: \" ..response.headers[\"Content-Type\"])\n self:logging(3,\"Response data: \" ..response.data)\n\n if response.data == nil or response.data == \"\" or response.data == \"[]\" or response.status > 200 then -- Check for empty result\n self:warning(\"Temporarily no production data from Tibber Monitor\")\n return\n end\n\n response.data = response.data:gsub(\"null\", \"0\") -- clean up the response.data by replacing null with 0\n local jsonTable = json.decode(response.data) -- JSON decode from api to lua-table\n\n self:getValues(jsonTable)\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 \n local interval = (3600 + tonumber(self:getVariable(\"secondsH\"))) - (os.date(\"%M\") * 60 + os.date(\"%S\"))\n self:logging(3,\"SetTimeout \" ..interval ..\" seconds\")\n fibaro.setTimeout(interval*1000, function() \n self:getData()\n end)\nend\n\n\nfunction QuickApp:createVariables() -- Create all Variables \n --jsonTable = {}\n jsonPricesTod = {}\n jsonEnergy = {}\n data = {}\n data.hEnergy = 0 -- Hourly Energy usage\n data.hCost = 0 -- Hourly Energy cost\n data.dEnergy = 0 -- Daily Energy usage\n data.dCost = 0 -- Daily Energy cost\n data.mEnergy = 0 -- Monthly Energy usage\n data.mCost = 0 -- Monthly Energy cost\n data.yEnergy = 0 -- Yearly Energy usage\n data.yCost = 0 -- Yearly Energy cost\n data.tEnergy = 0 -- Total Energy usage\n data.tCost = 0 -- Total Energy cost\n data.minPriceTod = 0 -- Today Minimum Price\n data.minPercentageTod = 0 -- Today Mimimum Percentage\n data.minLevelTod = \"\" -- Today Mimimum Price Level\n data.minStartsAtTod = \"\" -- Today Minimum Price at hour\n data.maxPriceTod = 0 -- Today Maximum Price\n data.maxPercentageTod = 0 -- Today Maximum Percentage\n data.maxLevelTod = \"\" -- Today Price Level\n data.maxStartsAtTod = \"\" -- Today Maximum Price at hour\n data.avgPriceTod = 0 -- Today Average Price\n data.minPriceTom = 0 -- Tomorrow Minimum Price\n data.minPercentageTom = 0 -- Tomorrow Minimum Percentage\n data.minLevelTom = \"\" -- Tomorrow Price Level\n data.minStartsAtTom = \"\" -- Tomorrow Maximum Price at hour\n data.maxPriceTom = 0 -- Tomorrow Maximum Price\n data.maxPercentageTom = 0 -- Tomorrow Maximum Percentage\n data.maxLevelTom = \"\" -- Tomorrow Maximum Price Level\n data.maxStartsAtTom = \"\" -- Tomorrow Maximum Price at hour\n data.avgPriceTom = 0 -- Tomorrow Average Price\n data.totalPrice = 0 -- The total price (energy + taxes)\n data.spotPrice = 0 -- Nord Pool spot price (Gross Energy Price)\n data.tax = 0 -- The tax part of the price (guarantee of origin certificate, energy tax (Sweden only) and VAT)\n data.startsAt = \"\" -- The start time of the price\n data.currency = \"\" -- The price currency\n data.level = \"\" -- The price level compared to recent price values\n translation = i18n:translation(string.lower(self:getVariable(\"language\"))) -- Initialise the translation\nend\n\n\nfunction QuickApp:getQuickAppVariables() -- Get all Quickapp Variables or create them\n local token = self:getVariable(\"token\") \n homeNr = tonumber(self:getVariable(\"homeNr\"))\n extraCost = tonumber(self:getVariable(\"extraCost\")) \n local secondsH = tonumber(self:getVariable(\"secondsH\")) \n local httpTimeout = tonumber(self:getVariable(\"httpTimeout\")) \n debugLevel = tonumber(self:getVariable(\"debugLevel\"))\n GlobVarLevel = string.lower(self:getVariable(\"GlobVarLevel\"))\n GlobVarPerc = string.lower(self:getVariable(\"GlobVarPerc\"))\n setEnergyPanel = string.lower(self:getVariable(\"setEnergyPanel\"))\n currentPrice = string.lower(self:getVariable(\"currentPrice\"))\n local language = string.lower(self:getVariable(\"language\"))\n local workaroundE01 = tonumber(self:getVariable(\"workaroundE01\")) \n local workaroundC01 = tonumber(self:getVariable(\"workaroundC01\")) \n local workaroundPnn = tonumber(self:getVariable(\"workaroundPnn\")) \n local workaroundP23 = tonumber(self:getVariable(\"workaroundP23\")) \n\n -- Check existence of the mandatory variables, if not, create them with default values\n if token == \"\" or token == nil then\n token = \"5K4MVS-OjfWhK_4yrjOlFe1F6kJXPVf7eQYggo8ebAE\" -- This token is just an demo example, only for demo/test purposes\n self:setVariable(\"token\",token)\n self:trace(\"Added QuickApp variable with DEMO (!) token\")\n end\n if homeNr == \"\" or homeNr == nil then\n homeNr = \"1\"\n self:setVariable(\"homeNr\",homeNr)\n self:trace(\"Added QuickApp variable homeNr\")\n homeNr = tonumber(homeNr)\n end\n if extraCost == \"\" or extraCost == nil then\n extraCost = \"0\"\n self:setVariable(\"extraCost\",extraCost)\n self:trace(\"Added QuickApp variable extraCost\")\n extraCost = tonumber(extraCost)\n end\n if secondsH == \"0\" or secondsH == \"\" or secondsH == nil then\n secondsH = \"300\" -- Default 300 seconds after the whole hour\n self:setVariable(\"secondsH\",secondsH)\n self:trace(\"Added QuickApp variable secondsH\")\n end\n if httpTimeout == \"\" or httpTimeout == nil then\n httpTimeout = \"10\" -- Default http timeout \n self:setVariable(\"httpTimeout\",httpTimeout)\n self:trace(\"Added QuickApp variable httpTimeout\")\n --httpTimeout = tonumber(httpTimeout)\n end \n if debugLevel == \"\" or debugLevel == nil then\n debugLevel = \"1\" -- Default debug level\n self:setVariable(\"debugLevel\",debugLevel)\n self:trace(\"Added QuickApp variable debugLevel\")\n debugLevel = tonumber(debugLevel)\n end\n if GlobVarLevel == \"\" or GlobVarLevel == nil then \n GlobVarLevel = false -- Default GlobVarLevel is false (No use of Global Variables for Price LEVEL)\n self:setVariable(\"GlobVarLevel\",tostring(GlobVarLevel))\n self:trace(\"Added QuickApp variable GlobVarLevel\")\n end\n if GlobVarLevel == \"true\" then \n GlobVarLevel = true \n else\n GlobVarLevel = false\n end\n if GlobVarPerc == \"\" or GlobVarPerc == nil then \n GlobVarPerc = false -- Default GlobVarPerc is false (No use of Global Variables for Price PERCENTAGES)\n self:setVariable(\"GlobVarPerc\",tostring(GlobVarPerc))\n self:trace(\"Added QuickApp variable GlobVarPerc\")\n end\n if GlobVarPerc == \"true\" then \n GlobVarPerc = true \n else\n GlobVarPerc = false\n end\n if setEnergyPanel == \"\" or setEnergyPanel == nil then \n setEnergyPanel = false -- Default setEnergyPanel is false (No inserting prices in Energy Panel)\n self:setVariable(\"setEnergyPanel\",tostring(setEnergyPanel))\n self:trace(\"Added QuickApp variable setEnergyPanel\")\n end\n if setEnergyPanel == \"true\" then \n setEnergyPanel = true \n else\n setEnergyPanel = false\n end\n if currentPrice == \"\" or currentPrice == nil then \n currentPrice = false \n self:setVariable(\"currentPrice\",tostring(currentPrice))\n self:trace(\"Added QuickApp variable currentPrice\")\n end\n if currentPrice == \"true\" then \n currentPrice = true \n else\n currentPrice = false\n end\n if token == nil or token == \"\" or token == \"0\" then -- Check mandatory token \n self:error(\"Token is empty! Get your token from the Tibber website and copy the token to the quickapp variable\")\n self:warning(\"No token, switched to Simulation Mode\")\n debugLevel = 4 -- Simulation mode due to empty token\n end\n if language == \"\" or language == nil or type(i18n:translation(string.lower(self:getVariable(\"language\")))) ~= \"table\" then\n language = \"en\" \n self:setVariable(\"language\",language)\n self:trace(\"Added QuickApp variable language\")\n end\n if workaroundE01 == \"\" or workaroundE01 == nil then\n workaroundE01 = \"0\" \n self:setVariable(\"workaroundE01\",workaroundE01)\n self:trace(\"Added QuickApp variable workaroundE01 for Energy 00-01 hour\")\n end\n if workaroundC01 == \"\" or workaroundC01 == nil then\n workaroundC01 = \"0\" \n self:setVariable(\"workaroundC01\",workaroundC01)\n self:trace(\"Added QuickApp variable workaroundC01 for Cost 00-01 hour\")\n end\n if workaroundPnn == \"\" or workaroundPnn == nil then\n workaroundPnn = \"0\" \n self:setVariable(\"workaroundPnn\",workaroundPnn)\n self:trace(\"Added QuickApp variable workaroundPnn for Price Energy Panel\")\n end\n if workaroundP23 == \"\" or workaroundP23 == nil then\n workaroundP23 = \"0\" \n self:setVariable(\"workaroundP23\",workaroundP23)\n self:trace(\"Added QuickApp variable workaroundP23 for 23h Price Energy Panel\")\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=\"hEnergy\", name=\"Hour-1 Energy\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hCost\", name=\"Hour-1 Cost\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"dEnergy\", name=\"Daily Energy\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"dCost\", name=\"Daily Cost\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"mEnergy\", name=\"Monthly Energy\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"mCost\", name=\"Monthly Cost\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"yEnergy\", name=\"Yearly Energy\", type=\"com.fibaro.multilevelSensor\"}, \n {className=\"yCost\", name=\"Yearly Cost\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"tEnergy\", name=\"Total Energy\", type=\"com.fibaro.energyMeter\"}, -- Device for values Energy Panel\n {className=\"tCost\", name=\"Total Cost\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hPrice\", name=\"Current Price\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"minPriceTod\", name=\"Today Min Price\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"maxPriceTod\", name=\"Today Max Price\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"avgPriceTod\", name=\"Today Avg Price\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour01Tod\", name=\"Today 00:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour02Tod\", name=\"Today 01:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour03Tod\", name=\"Today 02:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour04Tod\", name=\"Today 03:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour05Tod\", name=\"Today 04:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour06Tod\", name=\"Today 05:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour07Tod\", name=\"Today 06:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour08Tod\", name=\"Today 07:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour09Tod\", name=\"Today 08:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour10Tod\", name=\"Today 09:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour11Tod\", name=\"Today 10:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour12Tod\", name=\"Today 11:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour13Tod\", name=\"Today 12:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour14Tod\", name=\"Today 13:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour15Tod\", name=\"Today 14:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour16Tod\", name=\"Today 15:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour17Tod\", name=\"Today 16:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour18Tod\", name=\"Today 17:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour19Tod\", name=\"Today 18:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour20Tod\", name=\"Today 19:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour21Tod\", name=\"Today 20:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour22Tod\", name=\"Today 21:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour23Tod\", name=\"Today 22:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour24Tod\", name=\"Today 23:00\", type=\"com.fibaro.multilevelSensor\"}, \n {className=\"minPriceTom\", name=\"Tomorrow Min Price\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"maxPriceTom\", name=\"Tomorrow Max Price\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"avgPriceTom\", name=\"Tomorrow Avg Price\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour01Tom\", name=\"Tomorrow 00:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour02Tom\", name=\"Tomorrow 01:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour03Tom\", name=\"Tomorrow 02:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour04Tom\", name=\"Tomorrow 03:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour05Tom\", name=\"Tomorrow 04:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour06Tom\", name=\"Tomorrow 05:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour07Tom\", name=\"Tomorrow 06:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour08Tom\", name=\"Tomorrow 07:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour09Tom\", name=\"Tomorrow 08:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour10Tom\", name=\"Tomorrow 09:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour11Tom\", name=\"Tomorrow 10:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour12Tom\", name=\"Tomorrow 11:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour13Tom\", name=\"Tomorrow 12:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour14Tom\", name=\"Tomorrow 13:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour15Tom\", name=\"Tomorrow 14:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour16Tom\", name=\"Tomorrow 15:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour17Tom\", name=\"Tomorrow 16:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour18Tom\", name=\"Tomorrow 17:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour19Tom\", name=\"Tomorrow 18:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour20Tom\", name=\"Tomorrow 19:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour21Tom\", name=\"Tomorrow 20:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour22Tom\", name=\"Tomorrow 21:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour23Tom\", name=\"Tomorrow 22:00\", type=\"com.fibaro.multilevelSensor\"},\n {className=\"hour24Tom\", name=\"Tomorrow 23:00\", type=\"com.fibaro.multilevelSensor\"}, \n }\n for _,c in ipairs(initChildData) do\n local ips = UI and self:makeInitialUIProperties(UI or {}) or {}\n local child = self:createChildDevice(\n {name = c.name,\n type=c.type,\n properties = {viewLayout = ips.viewLayout, uiCallbacks = ips.uiCallbacks},\n interfaces = {\"quickApp\"}, \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's 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() -- Setup the Child Devices\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:createVariables()\n \n http = net.HTTPClient({timeout = tonumber(self:getVariable(\"httpTimeout\")) *1000})\n \n if tonumber(debugLevel) >= 4 then \n self:simData() -- Go in simulation\n else\n self:getData() -- Get data from the Tibber platform\n end\nend\n\n-- EOF "},{"name":"childs","isMain":false,"isOpen":false,"content":"-- Tibber Monitor Childs\n\nclass 'hEnergy'(QuickAppChild)\nfunction hEnergy:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hEnergy:updateValue(data) \n self:updateProperty(\"value\", data.hEnergy)\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \" \")\nend\n\nclass 'hCost'(QuickAppChild)\nfunction hCost:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hCost:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.hCost+(extraCost*data.hEnergy))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", string.format(\"%.2f\",data.hCost) ..\" + \" ..string.format(\"%.2f\",extraCost*data.hEnergy))\nend\n\nclass 'dEnergy'(QuickAppChild) \nfunction dEnergy:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction dEnergy:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.dEnergy)))\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \" \")\nend\n\nclass 'dCost'(QuickAppChild)\nfunction dCost:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction dCost:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.dCost+(extraCost*data.dEnergy))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", string.format(\"%.2f\",data.dCost) ..\" + \" ..string.format(\"%.2f\",extraCost*data.dEnergy))\nend\n\nclass 'mEnergy'(QuickAppChild)\nfunction mEnergy:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction mEnergy:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.mEnergy)))\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \" \")\nend\n\nclass 'mCost'(QuickAppChild)\nfunction mCost:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction mCost:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.mCost+(extraCost*data.mEnergy))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", string.format(\"%.2f\",data.mCost) ..\" + \" ..string.format(\"%.2f\",extraCost*data.mEnergy))\nend\n\nclass 'yEnergy'(QuickAppChild)\nfunction yEnergy:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction yEnergy:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.yEnergy)))\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \" \")\nend\n\nclass 'yCost'(QuickAppChild)\nfunction yCost:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction yCost:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.yCost+(extraCost*data.yEnergy))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", string.format(\"%.2f\",data.yCost) ..\" + \" ..string.format(\"%.2f\",extraCost*data.yEnergy))\nend\n\nclass 'tEnergy'(QuickAppChild) -- Device for Energy Panel\nfunction tEnergy:__init(dev)\n QuickAppChild.__init(self,dev)\n if fibaro.getValue(self.id, \"rateType\") ~= \"consumption\" then \n self:updateProperty(\"rateType\", \"consumption\")\n self:warning(\"Changed rateType interface of Total Energy child device (\" ..self.id ..\") to consumption\")\n end\nend\nfunction tEnergy:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.tEnergy)))\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \" \")\nend\n\nclass 'tCost'(QuickAppChild)\nfunction tCost:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction tCost:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.tCost+(extraCost*data.tEnergy))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", string.format(\"%.2f\",data.tCost) ..\" + \" ..string.format(\"%.2f\",extraCost*data.tEnergy))\nend\n\nclass 'hPrice'(QuickAppChild)\nfunction hPrice:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hPrice:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",data.totalPrice)))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", \"(\" ..translation[data.level] ..\")\")\nend\n\nclass 'minPriceTod'(QuickAppChild)\nfunction minPriceTod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction minPriceTod:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",(data.minPriceTod or 0))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", (data.minStartsAtTod or \"\") ..\" \" ..(translation[data.minLevelTod] or \"\"))\nend\n\nclass 'maxPriceTod'(QuickAppChild)\nfunction maxPriceTod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction maxPriceTod:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",(data.maxPriceTod or 0))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", (data.maxStartsAtTod or \"\") ..\" \"..(translation[data.maxLevelTod] or \"\"))\nend\n\nclass 'avgPriceTod'(QuickAppChild)\nfunction avgPriceTod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction avgPriceTod:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",(data.avgPriceTod or 0))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", \" \")\nend\n\nclass 'hour01Tod'(QuickAppChild) -- 00:00-01:00\nfunction hour01Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour01Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[1].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[1].level])\nend\n\nclass 'hour02Tod'(QuickAppChild) -- 01:00-02:00\nfunction hour02Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour02Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[2].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[2].level])\nend\n\nclass 'hour03Tod'(QuickAppChild) -- 02:00-03:00\nfunction hour03Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour03Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[3].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[3].level])\nend\n\nclass 'hour04Tod'(QuickAppChild) -- 03:00-04:00\nfunction hour04Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour04Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[4].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[4].level])\nend\n\nclass 'hour05Tod'(QuickAppChild) -- 04:00-05:00\nfunction hour05Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour05Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[5].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[5].level])\nend\n\nclass 'hour06Tod'(QuickAppChild) -- 05:00-06:00\nfunction hour06Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour06Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[6].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[6].level])\nend\n\nclass 'hour07Tod'(QuickAppChild) -- 06:00-07:00\nfunction hour07Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour07Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[7].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[7].level])\nend\n\nclass 'hour08Tod'(QuickAppChild) -- 07:00-08:00\nfunction hour08Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour08Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[8].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[8].level])\nend\n\nclass 'hour09Tod'(QuickAppChild) -- 08:00-09:00\nfunction hour09Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour09Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[9].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[9].level])\nend\n\nclass 'hour10Tod'(QuickAppChild) -- 09:00-10:00\nfunction hour10Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour10Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[10].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[10].level])\nend\n\nclass 'hour11Tod'(QuickAppChild) -- 10:00-11:00\nfunction hour11Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour11Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[11].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[11].level])\nend\n\nclass 'hour12Tod'(QuickAppChild) -- 11:00-12:00\nfunction hour12Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour12Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[12].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[12].level])\nend\n\nclass 'hour13Tod'(QuickAppChild) -- 12:00-13:00\nfunction hour13Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour13Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[13].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[13].level])\nend\n\nclass 'hour14Tod'(QuickAppChild) -- 13:00-14:00\nfunction hour14Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour14Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[14].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[14].level])\nend\n\nclass 'hour15Tod'(QuickAppChild) -- 14:00-15:00\nfunction hour15Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour15Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[15].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[15].level])\nend\n\nclass 'hour16Tod'(QuickAppChild) -- 15:00-16:00\nfunction hour16Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour16Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[16].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[16].level])\nend\n\nclass 'hour17Tod'(QuickAppChild) -- 16:00-17:00\nfunction hour17Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour17Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[17].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[17].level])\nend\n\nclass 'hour18Tod'(QuickAppChild) -- 17:00-18:00\nfunction hour18Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour18Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[18].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[18].level])\nend\n\nclass 'hour19Tod'(QuickAppChild) -- 18:00-19:00\nfunction hour19Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour19Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[19].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[19].level])\nend\n\nclass 'hour20Tod'(QuickAppChild) -- 19:00-20:00\nfunction hour20Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour20Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[20].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[20].level])\nend\n\nclass 'hour21Tod'(QuickAppChild) -- 20:00-21:00\nfunction hour21Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour21Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[21].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[21].level])\nend\n\nclass 'hour22Tod'(QuickAppChild) -- 21:00-22:00\nfunction hour22Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour22Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[22].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[22].level])\nend\n\nclass 'hour23Tod'(QuickAppChild) -- 22:00-23:00\nfunction hour23Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour23Tod:updateValue() \n self:updateProperty(\"value\", tonumber(jsonPricesTod[23].total))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", translation[jsonPricesTod[23].level])\nend\n\nclass 'hour24Tod'(QuickAppChild) -- 23:00-24:00\nfunction hour24Tod:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour24Tod:updateValue() \n if jsonPricesTod[24] then\n self:updateProperty(\"value\", tonumber(jsonPricesTod[24].total))\n self:updateProperty(\"log\", translation[jsonPricesTod[24].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \" \")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'minPriceTom'(QuickAppChild)\nfunction minPriceTom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction minPriceTom:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",(data.minPriceTom or 0))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", (data.minStartsAtTom or \"\") ..\" \" ..(translation[data.minLevelTom] or \"\"))\nend\n\nclass 'maxPriceTom'(QuickAppChild)\nfunction maxPriceTom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction maxPriceTom:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",(data.maxPriceTom or 0))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", (data.maxStartsAtTom or \"\") ..\" \"..(translation[data.maxLevelTom] or \"\"))\nend\n\nclass 'avgPriceTom'(QuickAppChild)\nfunction avgPriceTom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction avgPriceTom:updateValue(data) \n self:updateProperty(\"value\", tonumber(string.format(\"%.2f\",(data.avgPriceTom or 0))))\n self:updateProperty(\"unit\", data.currency)\n self:updateProperty(\"log\", \" \")\nend\n\nclass 'hour01Tom'(QuickAppChild) -- 00:00-01:00\nfunction hour01Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour01Tom:updateValue(data) \n if jsonPricesTom[1] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[1].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[1].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour02Tom'(QuickAppChild) -- 01:00-02:00\nfunction hour02Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour02Tom:updateValue(data) \n if jsonPricesTom[2] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[2].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[2].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour03Tom'(QuickAppChild) -- 02:00-03:00\nfunction hour03Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour03Tom:updateValue(data) \n if jsonPricesTom[3] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[3].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[3].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour04Tom'(QuickAppChild) -- 03:00-04:00\nfunction hour04Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour04Tom:updateValue(data) \n if jsonPricesTom[4] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[4].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[4].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour05Tom'(QuickAppChild) -- 04:00-05:00\nfunction hour05Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour05Tom:updateValue(data) \n if jsonPricesTom[5] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[5].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[5].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour06Tom'(QuickAppChild) -- 05:00-06:00\nfunction hour06Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour06Tom:updateValue(data) \n if jsonPricesTom[1] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[6].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[6].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour07Tom'(QuickAppChild) -- 06:00-07:00\nfunction hour07Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour07Tom:updateValue(data) \n if jsonPricesTom[7] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[7].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[7].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour08Tom'(QuickAppChild) -- 07:00-08:00\nfunction hour08Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour08Tom:updateValue(data) \n if jsonPricesTom[8] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[8].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[8].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour09Tom'(QuickAppChild) -- 08:00-09:00\nfunction hour09Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour09Tom:updateValue(data) \n if jsonPricesTom[9] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[9].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[9].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour10Tom'(QuickAppChild) -- 09:00-10:00\nfunction hour10Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour10Tom:updateValue(data) \n if jsonPricesTom[10] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[10].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[10].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour11Tom'(QuickAppChild) -- 10:00-11:00\nfunction hour11Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour11Tom:updateValue(data) \n if jsonPricesTom[11] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[11].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[11].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour12Tom'(QuickAppChild) -- 11:00-12:00\nfunction hour12Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour12Tom:updateValue(data) \n if jsonPricesTom[12] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[12].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[12].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour13Tom'(QuickAppChild) -- 12:00-13:00\nfunction hour13Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour13Tom:updateValue(data) \n if jsonPricesTom[13] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[13].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[13].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour14Tom'(QuickAppChild) -- 13:00-14:00\nfunction hour14Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour14Tom:updateValue(data) \n if jsonPricesTom[14] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[14].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[14].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour15Tom'(QuickAppChild) -- 14:00-15:00\nfunction hour15Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour15Tom:updateValue(data) \n if jsonPricesTom[15] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[15].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[15].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour16Tom'(QuickAppChild) -- 15:00-16:00\nfunction hour16Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour16Tom:updateValue(data) \n if jsonPricesTom[16] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[16].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[16].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour17Tom'(QuickAppChild) -- 16:00-17:00\nfunction hour17Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour17Tom:updateValue(data) \n if jsonPricesTom[17] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[17].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[17].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour18Tom'(QuickAppChild) -- 17:00-18:00\nfunction hour18Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour18Tom:updateValue(data) \n if jsonPricesTom[18] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[18].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[18].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour19Tom'(QuickAppChild) -- 18:00-19:00\nfunction hour19Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour19Tom:updateValue(data) \n if jsonPricesTom[19] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[19].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[19].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour20Tom'(QuickAppChild) -- 19:00-20:00\nfunction hour20Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour20Tom:updateValue(data) \n if jsonPricesTom[20] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[20].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[20].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour21Tom'(QuickAppChild) -- 20:00-21:00\nfunction hour21Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour21Tom:updateValue(data) \n if jsonPricesTom[21] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[21].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[21].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour22Tom'(QuickAppChild) -- 21:00-22:00\nfunction hour22Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour22Tom:updateValue(data) \n if jsonPricesTom[22] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[22].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[22].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour23Tom'(QuickAppChild) -- 22:00-23:00\nfunction hour23Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour23Tom:updateValue(data) \n if jsonPricesTom[23] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[23].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[23].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\nclass 'hour24Tom'(QuickAppChild) -- 23:00-24:00\nfunction hour24Tom:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction hour24Tom:updateValue(data) \n if jsonPricesTom[24] then \n self:updateProperty(\"value\", tonumber(jsonPricesTom[24].total))\n self:updateProperty(\"log\", translation[jsonPricesTom[24].level])\n else\n self:updateProperty(\"value\", 0)\n self:updateProperty(\"log\", \"N/A\")\n end\n self:updateProperty(\"unit\", data.currency)\nend\n\n-- EOF"},{"name":"readme","isMain":false,"isOpen":false,"content":"--[[ Quickapp Tibber Monitor readme\n\nThis QuickApp gets todays and tomorrows energy prices and current energy consumption from the Tibber platform. \nNext to the current prices the mimimum, maximum and average prices and percentage +/- related to the average price for today and tomorrow are calculated. \nTax and extra cost (cable owner) are included in the hourly, daily, monthly, yearly and total cost. \nAll values are displayed in the labels. Colors show the price levels in the labels:\n🟢 VERY CHEAP\n🟡 CHEAP\n🟠 NORMAL\n🔴 EXPENSIVE\n🟣 VERY EXPENSIVE\n\nThe Energy Panel is updated with the hourly prices and energy consumption. \nSeveral languages are supported. \n\nChild devices are available for:\n- Hour-1 Energy (Energy usage of the previous hour)\n- Hour-1 Cost (Energy cost of the previous hour)\n- Daily Energy (usage in kWh)\n- Daily Cost (energy and extra cost separately in the log text)\n- Monthly Energy (usage in kWh)\n- Monthly Cost (energy and extra cost separately in the log text)\n- Yearly Energy (usage in kWh)\n- Yearly Cost (energy and extra cost separately in the log text)\n- Total Energy (usage in kWh, devicetype com.fibaro.energyMeter and automatic rateType=consumption for Fibaro Energy Panel)\n- Total Cost (energy and extra cost separately in the log text)\n- Current Price (hour and price level in the log text)\n- Minimum Today Price (hour and price level in the log text)\n- Maximum Today Price (hour and price level in the log text)\n- Average Today Price (hour and price level in the log text)\n- 24x Child devices for the Today prices from 1 to 24 hour (price level in the log text)\n- Minimum Tomorrow Price (hour and price level in the log text)\n- Maximum Tomorrow Price (hour and price level in the log text)\n- Average Tomorrow Price (hour and price level in the log text)\n- 24x Child devices for the Tomorrow prices from 1 to 24 hour (price level in the log text)\n\nFor easy use in for example blockscenes, Global Variables are available for:\n- 24x Today Price Level 1-24 hour (VERY CHEAP, CHEAP, NORMAL, EXPENSIVE, VERY EXPENSIVE)\n- 24x Tomorrow Price Level 1-24 hour (VERY CHEAP, CHEAP, NORMAL, EXPENSIVE, VERY EXPENSIVE)\n- 24x Today Price Percentage 1-24 hour (Price related to today average price)\n- 24x Tomorrow Price Percentage 1-24 hour (Price related to tomorrow average price)\n\nThese devices and global variables can be used to control appliances according to the lowest and forecast prices.\n\n\nUse this QuickApp at your own risk. You are responsible for ensuring that the information provided via this QuickApp do not contain errors. \nTibber is a registered trademark being the property of TIBBER. TIBBER reserves all rights to the registered trademarks.\nInformation which is published on TIBBER’s websites belongs to TIBBER or is used with the permission of the rights holder. \nMaking of copies, presentations, distribution, display or any other transfer of the information on the website to the public is, except for strictly private use, prohibited unless done with the consent of TIBBER. \nPublished material on dedicated TIBBER press websites, intended for public use, is exempt from the consent requirement.\nAlso see: https://tibber.com/en/legal-notice\n\nTo communicate with the API you need to acquire a OAuth access token and pass this along with every request passed to the server.\nA Personal Access Token give you access to your data and your data only. \nThis is ideal for DIY people that want to leverage the Tibber platform to extend the smartness of their home. \nSuch a token can be acquired here: https://developer.tibber.com\n\nWhen creating your access token or OAuth client you’ll be asked which scopes you want the access token to be associated with. \nThese scopes tells the API which data and operations the client is allowed to perform on the user’s behalf. \nThe scopes your app requires depend on the type of data it is trying to request. \nIf you for example need access to user information you add the USER scope. \nIf information about the user's homes is needed you add the appropriate HOME scopes.\n\nTomorrow values are available from 13:00 hour\nIf you have more than one home in your subscription, you need to fill in your home number the change between your homes. \nKnown limitation: In case of the change due to daylight saving time, the 02:00 hour is skipped going to summer, only 23 price values are available\n\nTibber Price levels are based on trailing price average (3 days for hourly values and 30 days for daily values)\n- VERY CHEAP - The price is smaller or equal to 60 % compared to average price\n- CHEAP - The price is greater than 60 % and smaller or equal to 90 % compared to average price\n- NORMAL - The price is greater than 90 % and smaller than 115 % compared to average price\n- EXPENSIVE - The price is greater or equal to 115 % and smaller than 140 % compared to average price\n- VERY EXPENSIVE - The price is greater or equal to 140 % compared to average price\n\nTibber Tax: The tax part of the price (guarantee of origin certificate, energy tax (Sweden only) and VAT)\n\nTibber API documentation: https://developer.tibber.com/docs/guides/calling-api\nTibber API explorer: https://developer.tibber.com/explorer\nTibber status: https://status.tibber.com\n\n\nToDo, maybe (?)\n- Setup current hour price with current date/time and not from Tibber response\n- Energy prices and cost insertion in Energy Panel not hourly but once a day\n- In case of error: retry or wait for next interval (that is the current method)\n- Show prices in cents\n- Activate simulation if use of demo token\n\n\nChanges versio 3.0 (21th April 2023)\n- Added 24 child devices for the today prices 1 to 24 hour\n- Added 24 child devices for the tomorrow prices 1 to 24 hour\n- Added child devices for tomorrow minimum, tomorrow maximum and tomorrow average prices\n- Added tommorow prices to the labels\n- Added tomorrow minimum, tomorrow maximum and tomorrow average prices to the labels\n- Added color 🟢🟡🟠🔴🟣 to the prices in the labels based on the Tibber price level\n- Added todays energy usage per hour to the labels\n- Deleted today PRICES from the global variables, because they are available in the child devices\n- Added global variables for tomorrow price LEVELS (the today global variables were already there)\n- Added global variables for today price PERCENTAGES \n- Added global variables for tomorrow price PERCENTAGES \n- Changed the name of the global variables to get a better sorting in the dashboard\n- Added separate QuickApp variables to activate today and or tomorrow global variables\n- Changed to QuickApp variable secondsH (interval) to how many seconds after the whole hour the QuickApp should run, so the QuickApp now runs once an hour a few minutes after the whole hour\n- Added extra check for existance of the 24 hour values (for example in case of daylight saving time change)\n- Changed the main device to Generic Device\n- Changed to multifile QuickApp\n- Added translation for English (en), Dutch (nl), Swedish (se), Norwegian (no), German (de)\n- Added new Tibber user-agent to http request headers\n- Made some changes to work with missing tomorrow prices from Tibber\n- Improved some debug logging messages on debug level 3\n\n\nChanges version 2.1 (25th June 2022)\n- Changed the child device names Hourly Energy and Hourly Cost to Hour-1 Energy and Hour-1 Cost, because they actually are from the previous hour\n- Added Global Variables for Prices 0-10 hour\n- Removed Global Variable for Current Price Level, the Current Price Level is also available in the Global Variable for all 0-10 hour levels\n- Added QuickApp variable currentPrice to insert the current price in the Energy Panel if you also use the Tibber Live QuickApp. Otherwise the hour+1 price is interted. \n\nChanges version 2.0 (25th May 2022)\n- Changed the device for the energy panel from the Daily Energy to the Total Energy child device. Because Tibber reports always the past hour at the start of the new hour (so always too late) and the Energy panel and the Daily Energy child devices both resets at midnight and the Total Energy child device doesn't resets, that prevents the last hour from not getting into the energy panel. Thanks to @JcBorgs for analysing and testing. \n- Added workaround with the help of @JcBorgs for a Tibber API bug in 00-01 hour consumption (energy and cost can change to \"null\" during the day) \n- Added workaround for empty Tibber responses between 00:00 and 00:05 hour with help of @JcBorgs\n- Added insert of hour-1 price in Energy Panel (can be turned on or off) with help of @JcBorgs\n- Changed the name of all child devices Percentage to dynamic names like \"At hour 16:00\", \"At hour 17:00\", etc. with help of @jgab and @JcBorgs\n- Changed handling of no response from Tibber\n- Removed user defined icon (not necessary anymore)\n\nChanges version 1.3 (6th February 2022)\n- For easy use in blockscenes added Global Variables for the levels (CHEAP, etc) for the current price and percentages +0, +1, +2, +3, +4, +5, +6, +7, +8, +9 and +10 hour. (Activate the global variables with the QuickApp Variable setGlobalVar = true)\n- Added an extra Child Device for Percentage +0 hour (current hour)\n- Added QuickApp Variable setPercentage to setup the calculation of the percentages from \"average\" price or from \"current\" price\n- Changed the calculation of the percentages according to the setting in setPercentage, \"average\" or \"current\" price\n- Limited the calculation of the average price to the current price and the next 10 prices (in line with the child devices +0, +1 ... +10)\n- Added a minimum and maximum to forNextHour of 12 and 35 hours prices \n\nChanges version 1.2 (2nd February 2022) \n- Solved a nasty bug with the percentage in the labels for tomorrow prices\n- Added extra child devices for percentage +6 +7 +8 +9 +10 hour\n\nChanges version 1.1 (29th January 2022)\n- Added average price calculation and child device (made by Fibaro forum member @drzordz)\n- Added QuickApp variable to setup amount of hours to show the next prices (made by Fibaro forum member @drzordz)\n\nChanges version 1.0 (8th Januari 2022)\n- Reduced max and min price and percentage to two decimals digits \n- Solved issue with empty hourly energy\n- Added the prices to the log text of the child devices +1 +2 +3 +4 +5\n- Added percentages to the hourly prices in the labels\n- Added percentages to the minimum and maximum prices in the labels\n- Changed the abbreviation to the latest moment (display in properties and labels) to get the (theoretical) most accurate calculation\n- Changed the default interval to 930 seconds to update more often and have less issues in case Tibber doesn't respond\n\nChanges version 0.6 (1st January 2022)\n- Solved bug that didn't cleaned up the labels \n\nChanges version 0.5 (1st January 2021)\n- Changed main device to generic.device\n- Changed Tax calculations\n- Added child devices monthly and total energy and cost\n- Calculated the daily, monthly, yearly and total energy, cost and tax to get this day, this month, this year and total values\n- Solved a bug showing more than 12 prices just after midnight\n- Solved handling nil values at beginning of year, etc\n\nChanges version 0.3 (30th December 2021)\n- Added quickapp variable homeNr to select which home if you have more than one in your subscription\n\nChanges version 0.2 (29th December 2021)\n- Added all child devices\n- Added QuickApp variable for extra cost and added the cost to the calculations\n- Replaced \"null\" values in response to prevent errors\n- Limited values to next 12 hours\n\nChanges version 0.1 (23rd December 2021)\n- Initial version\n\n\nVariables (mandatory and created automatically): \n- token = Authorization token (see the Tibber website: https://developer.tibber.com)\n- homeNr = Tibber home (nodes) number if you have more than one home (default = 1)\n- extraCost = Extra cost per kWh for Tibber and Cable owner, decimals with dot, not comma (default = 0)\n- secondsH = How many seconds after the whole hour should the QuickApp run (default = 300 seconds (3 minutes), always greater than 0)\n- httpTimeout = How long to wait for a response from Tibber (default = 10 seconds) \n- debugLevel = Number (1=some, 2=few, 3=all, 4=simulation mode) (default = 1)\n- GlobVarLevel = true or false, whether you want to use the Global Variables for the today and tomorrow price LEVELS (default = false)\n- GlobVarPerc = true or false, whether you want to use the Global Variables for the today and tomorrow price PERCENTAGES (default = false)\n- setEnergyPanel = inserting prices in Energy Panel (default = false)\n- currentPrice = inserting current prices (if you also use Tibber Live) in Energy Panel (default = false)\n- workaroundE01 = Stores the value of the 00-01 hour energy for a Tibber API bug workaround (default = 0)\n- workaroundC01 = Stores the value of the 00-01 hour cost for a Tibber API bug workaround (default = 0)\n- workaroundPnn = Stores the hour-1 price for the Energy Panel (default = 0)\n- workaroundP23 = Stores the 23h price for the Energy Panel (default = 0)\n\n]]\n\n-- EOF "},{"name":"i18n1","isMain":false,"isOpen":false,"content":"-- Tibber Monitor i18n Translations\n\n\nclass \"i18n\"\nfunction i18n:translation(language)\n translation = {\n en = {\n [\"SIMULATION MODE\"] = \"SIMULATION MODE\", \n [\"Energy usage\"] = \"Energy usage\", \n [\"TODAY Prices\"] = \"TODAY Prices\",\n [\"TOMORROW Prices\"] = \"TOMORROW Prices\",\n [\"Not yet available\"] = \"Not yet available\",\n [\"Hourly Energy\"] = \"Hourly Energy\", \n [\"Daily Energy\"] = \"Daily Energy\", \n [\"Monthly Energy\"] = \"Monthly Energy\", \n [\"Yearly Energy\"] = \"Yearly Energy\", \n [\"Total Energy\"] = \"Total Energy\", \n [\"Actual Price\"] = \"Actual Price\", \n [\"Nord Pool Spot price\"] = \"Nord Pool Spot price\", \n [\"Last update\"] = \"Last update\", \n [\"Min\"] = \"Min\", \n [\"Max\"] = \"Max\", \n [\"Average\"] = \"Average\", \n [\"NORMAL\"] = \"NORMAL\", \n [\"CHEAP\"] = \"CHEAP\", \n [\"VERY CHEAP\"] = \"VERY CHEAP\", \n [\"EXPENSIVE\"] = \"EXPENSIVE\", \n [\"VERY EXPENSIVE\"] = \"VERY EXPENSIVE\", \n [\"Extra cost\"] = \"Extra cost\", \n [\"Cost\"] = \"Cost\", \n [\"per\"] = \"per\", \n [\"Tax\"] = \"Tax\", \n [\"At hour\"] = \"At hour\", \n [\"at\"] = \"at\"}, \n nl = {\n [\"SIMULATION MODE\"] = \"SIMULATIE MODE\", \n [\"Energy usage\"] = \"Energie verbruik\", \n [\"TODAY Prices\"] = \"VANDAAG prijzen\",\n [\"TOMORROW Prices\"] = \"MORGEN prijzen\",\n [\"Not yet available\"] = \"Nog niet beschikbaar\",\n [\"Hourly Energy\"] = \"Uurlijkse energie\", \n [\"Daily Energy\"] = \"Dagelijkse energie\", \n [\"Monthly Energy\"] = \"Maandelijkse energie\", \n [\"Yearly Energy\"] = \"Jaarlijkse energie\", \n [\"Total Energy\"] = \"Totale energie\", \n [\"Actual Price\"] = \"Aktuele prijs\", \n [\"Nord Pool Spot price\"] = \"Nord Pool Spotprijs\", \n [\"Last update\"] = \"Laatste update\", \n [\"Min\"] = \"Min\", \n [\"Max\"] = \"Max\", \n [\"Average\"] = \"Gemiddelde\", \n [\"NORMAL\"] = \"NORMAAL\", \n [\"CHEAP\"] = \"GOEDKOOP\", \n [\"VERY CHEAP\"] = \"ZEER GOEDKOOP\", \n [\"EXPENSIVE\"] = \"DUUR\", \n [\"VERY EXPENSIVE\"] = \"ZEER DUUR\", \n [\"Extra cost\"] = \"Extra kosten\", \n [\"Cost\"] = \"Kosten\", \n [\"per\"] = \"per\", \n [\"Tax\"] = \"Belasting\", \n [\"At hour\"] = \"Op uur\", \n [\"at\"] = \"op\"}, \n de = {\n [\"SIMULATION MODE\"] = \"SIMULATIONSMODUS\",\n [\"Energy usage\"] = \"Energieverbrauch\", \n [\"TODAY Prices\"] = \"HEUTE Preise\",\n [\"TOMORROW Prices\"] = \"MORGEN Preise\", \n [\"Not yet available\"] = \"Noch nicht verfügbar\",\n [\"Hourly Energy\"] = \"Stündliche Energie\", \n [\"Daily Energy\"] = \"Tägliche Energie\", \n [\"Monthly Energy\"] = \"Monatliche Energie\", \n [\"Yearly Energy\"] = \"Jahresenergie\", \n [\"Total Energy\"] = \"Gesamtenergie\", \n [\"Actual Price\"] = \"Aktueller Preis\", \n [\"Nord Pool Spot price\"] = \"Nord Pool Spot-Preis\", \n [\"Last update\"] = \"Letzte Aktualisierung\", \n [\"Min\"] = \"Min\", \n [\"Max\"] = \"Max\", \n [\"Average\"] = \"Durchschnitt\", \n [\"NORMAL\"] = \"NORMAL\", \n [\"CHEAP\"] = \"BILLIG\", \n [\"VERY CHEAP\"] = \"SEHR GÜNSTIG\", \n [\"EXPENSIVE\"] = \"TEUER\", \n [\"VERY EXPENSIVE\"] = \"SEHR TEUER\", \n [\"Extra cost\"] = \"Zusätzliche Kosten\", \n [\"Cost\"] = \"Kosten\", \n [\"per\"] = \"pro\", \n [\"Tax\"] = \"Steuer\", \n [\"At hour\"] = \"Zur Stunde\", \n [\"at\"] = \"bei\"}, \n se = {\n [\"SIMULATION MODE\"] = \"SIMULERINGSLÄGE\",\n [\"Energy usage\"] = \"Energianvändning\", \n [\"TODAY Prices\"] = \"IDAG Priser\",\n [\"TOMORROW Prices\"] = \"I MORGON Priser\",\n [\"Not yet available\"] = \"Inte tillgänglig än\",\n [\"Hourly Energy\"] = \"Timenergi\", \n [\"Daily Energy\"] = \"Daglig energi\", \n [\"Monthly Energy\"] = \"Månadsenergi\", \n [\"Yearly Energy\"] = \"Årlig energi\", \n [\"Total Energy\"] = \"Total energi\", \n [\"Actual Price\"] = \"Faktiskt pris\", \n [\"Nord Pool Spot price\"] = \"Nord Pool spot pris\", \n [\"Last update\"] = \"Senaste uppdateringen\", \n [\"Min\"] = \"Min\", \n [\"Max\"] = \"Max\", \n [\"Average\"] = \"Genomsnitt\", \n [\"NORMAL\"] = \"VANLIGT\", \n [\"CHEAP\"] = \"BILLIG\", \n [\"VERY CHEAP\"] = \"MYCKET BILLIGT\", \n [\"EXPENSIVE\"] = \"DYR\", \n [\"VERY EXPENSIVE\"] = \"VÄLDIGT DYR\", \n [\"Extra cost\"] = \"Extra kostnad\", \n [\"Cost\"] = \"Kosta\", \n [\"per\"] = \"per\", \n [\"Tax\"] = \"Beskatta\", \n [\"At hour\"] = \"På timme\", \n [\"at\"] = \"på\"}, \n no = {\n [\"SIMULATION MODE\"] = \"SIMULASJONSMODUS\", \n [\"Energy usage\"] = \"Energibruk\", \n [\"TODAY Prices\"] = \"I DAG Priser\",\n [\"TOMORROW Prices\"] = \"I MORGEN Priser\",\n [\"Not yet available\"] = \"Ikke tilgjengelig enda\",\n [\"Hourly Energy\"] = \"Timebasert energi\", \n [\"Daily Energy\"] = \"Daglig energi\", \n [\"Monthly Energy\"] = \"Månedlig energi\", \n [\"Yearly Energy\"] = \"Årlig energi\", \n [\"Total Energy\"] = \"Total energi\", \n [\"Actual Price\"] = \"Faktisk pris\", \n [\"Nord Pool Spot price\"] = \"Nord Pool spot pris\", \n [\"Last update\"] = \"Siste oppdatering\", \n [\"Min\"] = \"Min\", \n [\"Max\"] = \"Max\", \n [\"Average\"] = \"Gjennomsnitt\", \n [\"NORMAL\"] = \"NORMAL\", \n [\"CHEAP\"] = \"BILLIG\", \n [\"VERY CHEAP\"] = \"VELDIG BILLIG\", \n [\"EXPENSIVE\"] = \"DYRT\", \n [\"VERY EXPENSIVE\"] = \"VELDIG DYRT\", \n [\"Extra cost\"] = \"Kkstra kostnader\", \n [\"Cost\"] = \"Koste\", \n [\"per\"] = \"per\", \n [\"Tax\"] = \"Avgift\", \n [\"At hour\"] = \"På timen\", \n [\"at\"] = \"på\"},} \n translation = translation[language] -- Shorten the table to only the current translation\n return translation\nend\n\n-- EOF "}]}