-
Notifications
You must be signed in to change notification settings - Fork 0
/
Solax_Monitor-30.fqa
1 lines (1 loc) · 32.1 KB
/
Solax_Monitor-30.fqa
1
{"name":"Solax Monitor","type":"com.fibaro.powerMeter","apiVersion":"1.2","initialProperties":{"viewLayout":{"$jason":{"body":{"header":{"style":{"height":"0"},"title":"quickApp_device_337"},"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_337"}}},"uiCallbacks":[],"quickAppVariables":[{"name":"tokenId","value":"0"},{"name":"inverterSN","value":"0"},{"name":"language","value":"en"},{"name":"solarM2","value":"0"},{"name":"interval","value":"300"},{"name":"debugLevel","value":"1"}],"typeTemplateInitialized":true},"files":[{"name":"main","isMain":true,"isOpen":true,"content":"-- QUICKAPP Solax Monitor main\n\n\nlocal function getChildVariable(child,varName) -- Fetch child class names\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\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:solarPower(power, m2) -- Calculate Solar Power per m²\n self:logging(3,\"Start solarPower() - Calculate Solar Power per m²\")\n if m2 > 0 and power > 0 then\n solarPower = power / m2\n else\n solarPower = 0\n end\n return solarPower\nend\n\n\nfunction QuickApp:unitCheckWh(measurement) -- Set the measurement and unit to kWh, MWh or GWh\n self:logging(3,\"Start unitCheckWh() - Set the measurement and unit to kWh, MWh or GWh\")\n if measurement > 1000000000 then\n return string.format(\"%.3f\",measurement/1000000000),\"GWh\"\n elseif measurement > 1000000 then\n return string.format(\"%.3f\",measurement/1000000),\"MWh\"\n elseif measurement > 1000 then\n return string.format(\"%.1f\",measurement/1000),\"kWh\"\n else\n return string.format(\"%.0f\",measurement),\"Wh\"\n end\nend\n\n\nfunction QuickApp:inverterStatus(status) -- Set the inverter status (API manual Appendix Table 5) \n if status == \"100\" then\n return \"Wait Mode\"\n elseif status == \"101\" then\n return \"Check Mode\"\n elseif status == \"102\" then\n return \"Normal Mode\"\n elseif status == \"103\" then\n return \"Fault Mode\"\n elseif status == \"104\" then\n return \"Permanent Fault Mode\"\n elseif status == \"105\" then\n return \"Update Mode\"\n elseif status == \"106\" then\n return \"EPS Check Mode\"\n elseif status == \"107\" then\n return \"EPS Mode\"\n elseif status == \"108\" then\n return \"Self-Test Mode\" \n elseif status == \"109\" then\n return \"Idle Mode\"\n elseif status == \"110\" then\n return \"Standby Mode\"\n elseif status == \"111\" then\n return \"Pv Wake Up Bat Mode\"\n elseif status == \"112\" then\n return \"Gen Check Mode\"\n elseif status == \"113\" then\n return \"Gen Run Mode\"\n else \n return \"Unknown Mode\"\n end\nend\n\n\nfunction QuickApp:inverterType(type) -- Set the inverter type (API manual Appendix Table 4)\n if type == \"1\" then\n return \"X1-LX\"\n elseif type == \"2\" then\n return \"X-Hybrid\"\n elseif type == \"3\" then\n return \"X1-Hybiyd/Fit\"\n elseif type == \"4\" then\n return \"X1-Boost/Air/Mini\"\n elseif type == \"5\" then\n return \"X3-Hybiyd/Fit\"\n elseif type == \"6\" then\n return \"X3-20K/30K\"\n elseif type == \"7\" then\n return \"X3-MIC/PRO\"\n elseif type == \"8\" then\n return \"X1-Smart\"\n elseif type == \"9\" then\n return \"X1-AC\"\n elseif type == \"10\" then\n return \"A1-Hybrid\"\n elseif type == \"11\" then\n return \"A1-Fit\"\n elseif type == \"12\" then\n return \"A1-Grid\" \n elseif type == \"13\" then\n return \"J1-ESS\"\n else\n return \"unknown\"\n end\nend\n\n\nfunction QuickApp:updateProperties() -- Update the properties\n self:logging(3,\"updateProperties() - Update the properties\")\n self:updateProperty(\"value\", tonumber(data.acpower))\n self:updateProperty(\"power\", tonumber(data.acpower))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", data.uploadTime)\nend\n\n\nfunction QuickApp:updateLabels() -- Update the labels\n self:logging(3,\"updateLabels() - Update the labels\")\n local labelText = \"\"\n \n if debugLevel == 4 then\n labelText = labelText ..translation[\"SIMULATION MODE\"] ..\"\\n\\n\"\n end\n \n labelText = labelText ..translation[\"Current Power\"] ..\": \" ..data.acpower ..\" Watt\" ..\"\\n\\n\"\n \n labelText = labelText ..translation[\"Solar Power/m²\"] ..\": \" ..data.solarPower ..\" Watt/m² (\" ..solarM2 ..\" m²)\" ..\"\\n\"\n labelText = labelText ..translation[\"Today Energy\"] ..\": \" ..data.yieldtoday ..\" kWh\" ..\"\\n\"\n labelText = labelText ..translation[\"Total Energy\"] ..\": \" ..data.yieldtotal ..\" \" ..data.yieldtotalUnit ..\"\\n\"\n labelText = labelText ..translation[\"Total Power/m²\"] ..\": \" ..data.feedinpowerM2 ..\" Watt/m²\" ..\"\\n\\n\"\n \n labelText = labelText ..translation[\"Total Power to Grid\"] ..\": \" ..data.feedinpower ..\" Watt\" ..\"\\n\"\n labelText = labelText ..translation[\"Total Energy to Grid\"] ..\": \" ..data.feedinenergy ..\" kWh\" ..\"\\n\"\n labelText = labelText ..translation[\"Energy from Grid\"] ..\": \" ..data.consumeenergy ..\" kWh\" ..\"\\n\\n\"\n \n labelText = labelText ..translation[\"Battery Energy\"] ..\": \" ..data.soc ..\" %\" ..\"\\n\"\n labelText = labelText ..translation[\"Battery Power\"] ..\": \" ..data.batPower ..\" Watt\" ..\"\\n\\n\"\n \n labelText = labelText ..translation[\"AC Power R\"] ..\": \" ..data.peps1 ..\" Watt\" ..\"\\n\"\n labelText = labelText ..translation[\"AC Power S\"] ..\": \" ..data.peps2 ..\" Watt\" ..\"\\n\"\n labelText = labelText ..translation[\"AC Power T\"] ..\": \" ..data.peps3 ..\" Watt\" ..\"\\n\\n\"\n \n labelText = labelText ..translation[\"Power DC1\"] ..\": \" ..data.powerdc1 ..\" Watt\" ..\"\\n\"\n labelText = labelText ..translation[\"Power DC2\"] ..\": \" ..data.powerdc2 ..\" Watt\" ..\"\\n\"\n labelText = labelText ..translation[\"Power DC3\"] ..\": \" ..data.powerdc3 ..\" Watt\" ..\"\\n\"\n labelText = labelText ..translation[\"Power DC4\"] ..\": \" ..data.powerdc4 ..\" Watt\" ..\"\\n\\n\"\n \n labelText = labelText ..translation[\"Inverter Type\"] ..\": \" ..data.inverterType ..\"\\n\"\n labelText = labelText ..translation[\"Inverter Status\"] ..\": \" ..data.inverterStatus ..\"\\n\"\n labelText = labelText ..translation[\"Last update\"] ..\": \" ..data.uploadTime ..\"\\n\" \n self:updateView(\"label\", \"text\", labelText)\n self:logging(2,labelText)\nend\n\n\nfunction QuickApp:getValues(table) -- Get the values from json file \n self:logging(3,\"getValues() - Get the values from json file \")\n local jsonTable = table\n data.acpower = string.format(\"%.0f\", jsonTable.result.acpower or \"0\")\n data.solarPower = string.format(\"%.2f\",self:solarPower(tonumber(data.acpower), tonumber(solarM2)))\n data.yieldtoday = string.format(\"%.1f\",jsonTable.result.yieldtoday or \"0\")\n data.yieldtotal = jsonTable.result.yieldtotal*1000 or \"0\"\n data.yieldtotal, data.yieldtotalUnit = self:unitCheckWh(tonumber(data.yieldtotal))-- Set measurement and unit to kWh, MWh or GWh \n data.feedinpower = string.format(\"%.0f\",jsonTable.result.feedinpower or \"0\")\n data.feedinpower = string.format(\"%.2f\",-tonumber(data.feedinpower)) -- Convert positive to negative, negative to positive\n data.feedinenergy = string.format(\"%.2f\",jsonTable.result.feedinenergy or \"0\")\n data.consumeenergy = string.format(\"%.2f\",jsonTable.result.consumeenergy or \"0\")\n data.feedinpowerM2 = string.format(\"%.0f\",jsonTable.result.feedinpowerM2 or \"0\")\n data.soc = string.format(\"%.0f\",jsonTable.result.soc or \"0\")\n data.peps1 = string.format(\"%.0f\",jsonTable.result.peps1 or \"0\")\n data.peps2 = string.format(\"%.0f\",jsonTable.result.peps2 or \"0\")\n data.peps3 = string.format(\"%.0f\",jsonTable.result.peps3 or \"0\")\n data.inverterType = jsonTable.result.inverterType\n data.inverterType = self:inverterType(data.inverterType)\n data.inverterStatus = jsonTable.result.inverterStatus\n data.inverterStatus = self:inverterStatus(data.inverterStatus)\n data.batPower = string.format(\"%.0f\",jsonTable.result.batPower or \"0\")\n data.powerdc1 = string.format(\"%.0f\",jsonTable.result.powerdc1 or \"0\")\n data.powerdc2 = string.format(\"%.0f\",jsonTable.result.powerdc2 or \"0\")\n data.powerdc3 = string.format(\"%.0f\",jsonTable.result.powerdc3 or \"0\")\n data.powerdc4 = string.format(\"%.0f\",jsonTable.result.powerdc4 or \"0\")\n data.uploadTime = jsonTable.result.uploadTime\n local pattern = \"(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)\"\n local runyear, runmonth, runday, runhour, runminute, runseconds = data.uploadTime:match(pattern)\n local convertedTimestamp = os.time({year = runyear, month = runmonth, day = runday, hour = runhour, min = runminute, sec = runseconds})\n data.uploadTime = os.date(\"%d-%m-%Y %H:%M\", convertedTimestamp)\nend\n\n\nfunction QuickApp:simData() -- Simulate Solax Monitor\n self:logging(3,\"simData() - Simulate Solax Monitor\")\n local apiResult = '{\"success\":true,\"exception\":\"Query success!\",\"result\":{\"inverterSN\":\"H3UE*********\",\"sn\":\"SW********\",\"acpower\":575.0,\"yieldtoday\":2.5,\"yieldtotal\":445.3,\"feedinpower\":-44.0,\"feedinenergy\":6.23,\"consumeenergy\":1292.27,\"feedinpowerM2\":0.0,\"soc\":15.0,\"peps1\":0.0,\"peps2\":0.0,\"peps3\":0.0,\"inverterType\":\"5\",\"inverterStatus\":\"102\",\"uploadTime\":\"2022-04-16 07:55:03\",\"batPower\":355.0,\"powerdc1\":0.0,\"powerdc2\":213.0,\"powerdc3\":0.0,\"powerdc4\":0.0}}'\n --local apiResult = '{\"success\":false,\"exception\":\"Query success!\",\"result\":\"this sn did not access!\"}'\n \n local jsonTable = json.decode(apiResult) \n if jsonTable == nil or jsonTable == \"\" or jsonTable == \"[]\" or not jsonTable.success then -- Check for empty or faulty result\n self:warning(\"Temporarily no production data from Solax Cloud\")\n self:updateProperty(\"log\", \"No data from Cloud\")\n return\n end\n \n self:getValues(jsonTable)\n self:updateLabels()\n self:updateProperties()\n\n for id,child in pairs(self.childDevices) do \n child:updateValue(data,userID) \n end\n \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 the API\n self:logging(3,\"getData() - Get the data from the API\")\n local url = \"https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=\"..self:getVariable('tokenId')..\"&sn=\" ..self:getVariable('inverterSN')\n self:logging(2,\"URL: \" ..url)\n http:request(url, {\n options={headers = {Accept = \"application/json\"},method = 'GET'}, \n success = function(response)\n self:logging(3,\"response status: \" ..response.status)\n self:logging(3,\"headers: \" ..response.headers[\"Content-Type\"])\n self:logging(2,\"Response data: \" ..response.data)\n\n response.data = response.data:gsub(\"null\", \"0.0\") -- clean up the response.data by replacing null with 0.0\n local jsonTable = json.decode(response.data) \n \n if jsonTable == nil or jsonTable == \"\" or jsonTable == \"[]\" or response.status > 200 or jsonTable.success == \"false\" or not jsonTable.success then -- Check for empty or faulty result\n self:warning(\"Temporarily no production data from Solax Cloud\")\n self:updateProperty(\"log\", \"No data from Cloud\")\n return\n end\n\n self:getValues(jsonTable)\n self:updateLabels()\n self:updateProperties()\n\n for id,child in pairs(self.childDevices) do \n child:updateValue(data,userID) \n end\n\n end,\n error = function(error)\n self:error(\"error: \" ..json.encode(error))\n self:updateProperty(\"log\", \"error: \" ..json.encode(error))\n end\n }) \n \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 self:logging(3,\"createVariables() - Create all Variables \")\n translation = i18n:translation(string.lower(self:getVariable(\"language\"))) -- Initialise the translation\n data = {}\n data.acpower = \"0\"\n data.solarPower = \"0\" \n data.yieldtoday = \"0\"\n data.yieldtotal = \"0\"\n data.yieldtotalUnit= \"Wh\"\n data.feedinpower = \"0\"\n data.feedinenergy = \"0\"\n data.consumeenergy = \"0\"\n data.feedinpowerM2 = \"0\"\n data.soc = \"0\"\n data.peps1 = \"0\"\n data.peps2 = \"0\"\n data.peps3 = \"0\"\n data.inverterType = \"\"\n data.inverterStatus = \"\"\n data.uploadTime = \"\"\n data.batPower = \"0\"\n data.powerdc1 = \"0\"\n data.powerdc2 = \"0\"\n data.powerdc3 = \"0\"\n data.powerdc4 = \"0\"\nend\n\n\nfunction QuickApp:getQuickAppVariables() -- Get all Quickapp Variables or create them\n local tokenId = self:getVariable(\"tokenId\")\n local inverterSN = self:getVariable(\"inverterSN\")\n local language = string.lower(self:getVariable(\"language\"))\n solarM2 = tonumber(self:getVariable(\"solarM2\"))\n interval = tonumber(self:getVariable(\"interval\")) \n debugLevel = tonumber(self:getVariable(\"debugLevel\"))\n\n -- Check existence of the mandatory variables, if not, create them with default values\n if tokenId == \"\" or tokenId == nil then\n tokenId = \"0\" -- This siteID is just an example, it is not working \n self:setVariable(\"tokenId\",tokenId)\n self:trace(\"Added QuickApp variable tokenId\")\n end\n if inverterSN == \"\" or inverterSN == nil then\n inverterSN = \"0\" -- This inverter ID is just an example, it is not working\n self:setVariable(\"inverterSN\",inverterSN)\n self:trace(\"Added QuickApp variable inverterSN\")\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 solarM2 == \"\" or solarM2 == nil then \n solarM2 = \"0\" -- Default Solar/m²\n self:setVariable(\"solarM2\",solarM2)\n self:trace(\"Added QuickApp variable solarM2\")\n end \n if interval == \"\" or interval == nil then\n interval = \"300\" -- Default interval\n self:setVariable(\"interval\",interval)\n self:trace(\"Added QuickApp variable interval\")\n interval = tonumber(interval)\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 tokenId == nil or tokenId == \"\" or tokenId == \"0\" then -- Check mandatory tokenId \n self:error(\"tokenId is empty! Please obtain your tokenID on the API page of Solaxcloud for free and copy the tokenId to the quickapp variable\")\n self:warning(\"No tokenId: Switched to Simulation Mode\")\n debugLevel = 4 -- Simulation mode due to empty tokenId \n end\n if inverterSN == nil or inverterSN == \"\" or inverterSN == \"0\" then -- Check mandatory inverterSN \n self:error(\"inverterSN is empty! Get your inverterSN from your inverter and copy the inverterSN to the quickapp variable\")\n self:warning(\"No inverterSN: Switched to Simulation Mode\")\n debugLevel = 4 -- Simulation mode due to empty inverterSN\n end\nend\n\n\nfunction QuickApp:setupChildDevices() -- Pick up all Child Devices\n local cdevs = api.get(\"/devices?parentId=\"..self.id) or {}\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=\"solarpower\", name=\"Solar Power\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"yieldtoday\", name=\"Today Energy\", type=\"com.fibaro.energyMeter\", value=0},\n {className=\"yieldtotal\", name=\"Total Energy\", type=\"com.fibaro.energyMeter\", value=0},\n {className=\"feedinpower\", name=\"Grid Power\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"feedinenergy\", name=\"Energy to Grid\", type=\"com.fibaro.energyMeter\", value=0},\n {className=\"consumeenergy\", name=\"Energy from Grid\", type=\"com.fibaro.energyMeter\", value=0},\n {className=\"feedinpowerM2\", name=\"Power M2\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"soc\", name=\"Battery Energy\", type=\"com.fibaro.multilevelSensor\", value=0},\n {className=\"peps1\", name=\"peps1\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"peps2\", name=\"peps2\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"peps3\", name=\"peps3\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"batPower\", name=\"Battery Power\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"powerdc1\", name=\"powerdc1\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"powerdc2\", name=\"powerdc2\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"powerdc3\", name=\"powerdc3\", type=\"com.fibaro.powerMeter\", value=0},\n {className=\"powerdc4\", name=\"powerdc4\", type=\"com.fibaro.powerMeter\", value=0},\n }\n for _,c in ipairs(initChildData) do\n local child = self:createChildDevice(\n {name = c.name,\n type=c.type,\n value=c.value,\n unit=c.unit,\n initialInterfaces = {},\n },\n _G[c.className] -- Fetch class constructor from class name\n )\n child:setVariable(\"className\",c.className) -- Save class name so we know when we load it next time\n end \n else \n for _,child in ipairs(cdevs) do\n local className = getChildVariable(child,\"className\") -- Fetch child class name\n local childObject = _G[className](child) -- Create child object from the constructor name\n self.childDevices[child.id]=childObject\n childObject.parent = self -- Setup parent link to device controller \n end\n end\nend\n\n\nfunction QuickApp:onInit()\n __TAG = fibaro.getName(plugin.mainDeviceId) ..\" ID:\" ..plugin.mainDeviceId\n self:debug(\"onInit\") \n \n self:setupChildDevices()\n \n if not api.get(\"/devices/\"..self.id).enabled then\n self:warning(\"Device\", fibaro.getName(plugin.mainDeviceId), \"is disabled\")\n return\n end\n \n self:getQuickAppVariables() \n self:createVariables()\n \n http = net.HTTPClient({timeout=5*1000})\n \n if tonumber(debugLevel) >= 4 then \n self:simData() -- Go in simulation\n else\n self:getData() -- Get data from Solax Monitor\n end\nend\n\n-- EOF "},{"name":"childs","isMain":false,"isOpen":false,"content":"-- Quickapp Solax Monitor childs\n\n\nclass 'solarpower'(QuickAppChild)\nfunction solarpower:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction solarpower:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.solarPower))\n self:updateProperty(\"unit\", \"Watt/m²\")\n self:updateProperty(\"log\", solarM2 ..\" m²\")\nend\n\nclass 'yieldtoday'(QuickAppChild)\nfunction yieldtoday:__init(dev)\n QuickAppChild.__init(self,dev)\n if fibaro.getValue(self.id, \"rateType\") ~= \"production\" then \n self:updateProperty(\"rateType\", \"production\")\n self:warning(\"Changed rateType interface of Solax lastDayData child device (\" ..self.id ..\") to production\")\n end\nend\nfunction yieldtoday:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.yieldtoday))\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'yieldtotal'(QuickAppChild)\nfunction yieldtotal:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction yieldtotal:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.yieldtotal))\n self:updateProperty(\"unit\", data.yieldtotalUnit)\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'feedinpower'(QuickAppChild)\nfunction feedinpower:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction feedinpower:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.feedinpower))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'feedinenergy'(QuickAppChild)\nfunction feedinenergy:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction feedinenergy:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.feedinenergy))\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'consumeenergy'(QuickAppChild)\nfunction consumeenergy:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction consumeenergy:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.consumeenergy))\n self:updateProperty(\"unit\", \"kWh\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'feedinpowerM2'(QuickAppChild)\nfunction feedinpowerM2:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction feedinpowerM2:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.feedinpowerM2))\n self:updateProperty(\"unit\", \"Watt/m²\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'soc'(QuickAppChild)\nfunction soc:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction soc:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.soc))\n self:updateProperty(\"unit\", \"%\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'peps1'(QuickAppChild)\nfunction peps1:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction peps1:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.peps1))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'peps2'(QuickAppChild)\nfunction peps2:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction peps2:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.peps2))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'peps3'(QuickAppChild)\nfunction peps3:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction peps3:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.peps3))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'batPower'(QuickAppChild)\nfunction batPower:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction batPower:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.batPower))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'powerdc1'(QuickAppChild)\nfunction powerdc1:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction powerdc1:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.powerdc1))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'powerdc2'(QuickAppChild)\nfunction powerdc2:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction powerdc2:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.powerdc2))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'powerdc3'(QuickAppChild)\nfunction powerdc3:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction powerdc3:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.powerdc3))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\nclass 'powerdc4'(QuickAppChild)\nfunction powerdc4:__init(dev)\n QuickAppChild.__init(self,dev)\nend\nfunction powerdc4:updateValue(data) \n self:updateProperty(\"value\", tonumber(data.powerdc4))\n self:updateProperty(\"unit\", \"Watt\")\n self:updateProperty(\"log\", \"\")\nend\n\n-- EOF"},{"name":"readme","isMain":false,"isOpen":false,"content":"--[[ Solax Monitor readme\n\n\nThis QuickApp monitors your Solax managed Solar Panels\nThe QuickApp has (child) devices for Solarpower/m², Today production, Total production, Total Power to Grid, Total Energy to Grid, Consumed Energy, Energy from Grid, Total Power/m², Battery Energy, AC Power R, AC Power S, AC Power T, Battery Power, Power DC1, Power DC2, Power DC3 and Power DC4\nThe rateType interface of child device Today Energy is automatically set to \"production\"\nThe readings from the child device Today Energy will be shown in the new energy panel \nThe readings from the child device Total Energy is automatically set to the right Wh unit (Wh, kWh, MWh or GWh) \n\nSee API documentation on https://www.eu.solaxcloud.com/phoebus/resource/files/userGuide/Solax_API.pdf\nUser can get a specific range of information through the granted tokenID. Please obtain your tokenID on the API page of Solaxcloud for free.\nThe tokenID can be used to obtain real-time data of your inverter system. The obtain frequency need to be lower than 10 times/min and 10,000 times/day.\n\nTODO: \n- change to standard ratetypes\n\nVersion 3.0 (11th January 2023)\n- Changed the descriptions of the Solax Cloud values\n- Converted the feedinpower value from positive to negative or from negative to positive\n- Added translation for English, Dutch and Portugese\n- Added child device for consumeenergy\n\nVersion 2.1 (4th December 2022)\n- Prevented almost empty responses like these: {\"success\":false,\"exception\":\"Query success!\",\"result\":\"this sn did not access!\"}\n- Added log text to main device if no data from Solax Cloud \n\nVersion 2.0 (16th April 2022)\n- Added Child Devices for feedinpower, feedinenergy, consumeenergy, feedinpowerM2, soc, peps1, peps2, peps3, batPower, powerdc1, powerdc2, powerdc3, powerdc4\n- Added all values returned from the Solax Cloud to the labels\n- Changed all the device types to the most current ones\n- Changed the handling of bad responses from the Solax Cloud\n- Replaced null values in responses with 0.0\n- Optimized some code\n\nVersion 1.0 (17th November 2021)\n- Tested, ready for release\n\nVersion 0.2 (15th November 2021)\n- Changed json response\n\nVersion 0.1 (13th November 2021)\n- First (test) version\n\n\nVariables (mandatory and created automatically): \n- tokenId = token ID of your Solax Inverter, obtain your tokenID on the API page of Solaxcloud for free\n- inverterSN = Unique identifier (Serial No.) of your Solax inverter\n- solarM2 = The amount of m2 Solar Panels (use . for decimals) for calculating Solar Power m² (default = 0)\n- interval = The default is 300 seconds (5 minutes), the daily API limitation is maximum 10 times/min and 10,000 times/day\n- debugLevel = Number (1=some, 2=few, 3=all, 4=simulation mode) (default = 1)\n\n\nExample json string (https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId={tokenId}&sn={sn}):\n{\"exception\":\"Query success!\",\"result\":{\"inverterSN\":\"XBT422Fnnnnnnn\",\"sn\":\"SNWERTYUIO\",\"acpower\":480.0,\"yieldtoday\":876.0,\"yieldtotal\":99860.6,\"feedinpower\":0.0,\"feedinenergy\":0.0,\"consumeenergy\":0.0,\"feedinpowerM2\":0.0,\"soc\":0.0,\"peps1\":0.0,\"peps2\":0.0,\"peps3\":0.0,\"inverterType\":\"4\",\"inverterStatus\":\"102\",\"uploadTime\":\"2021-11-15 10:54:36\",\"batPower\":0.0,\"powerdc1\":26.0,\"powerdc2\":29.0,\"powerdc3\":null,\"powerdc4\":null},\"success\":true}\n\n{\"success\":true,\"exception\":\"Query success!\",\"result\":{\"inverterSN\":\"H3UE*********\",\"sn\":\"SW********\",\"acpower\":575.0,\"yieldtoday\":2.5,\"yieldtotal\":445.3,\"feedinpower\":-44.0,\"feedinenergy\":6.23,\"consumeenergy\":1292.27,\"feedinpowerM2\":0.0,\"soc\":15.0,\"peps1\":0.0,\"peps2\":0.0,\"peps3\":0.0,\"inverterType\":\"5\",\"inverterStatus\":\"102\",\"uploadTime\":\"2022-04-16 07:55:03\",\"batPower\":-355.0,\"powerdc1\":0.0,\"powerdc2\":213.0,\"powerdc3\":null,\"powerdc4\":null}}\n\n\nAPI items: Description (Accuracy) (Unit) \n- inverterSN: Unique identifier of inverter (Serial No.)\n- sn: Unique identifier of communication module (Registration No.)\n- acpower: Inverter.AC.power.total (1) (W)\n- yieldtoday: Inverter.AC.energy.out.daily (0.1) (KWh)\n- yieldtotal: Inverter.AC.energy.out.total (0.1) (KWh) \n- feedinpower: Grid.power.total (1) (W)\n- feedinenergy: Grid.energy.toGrid.total (0.01) (KWh) \n- consumeenergy: Grid.energy.fromGrid.total (0.01) (KWh) \n- feedinpowerM2: Inverter.Meter2.AC.power.total (1) (W) \n- soc: inverter.DC.battery.energy.SOC (1) (%)\n- peps1: Inverter.AC.EPS.power.R (1) (W)\n- peps2: Inverter.AC.EPS.power.S (1) (W)\n- peps3: Inverter.AC.EPS.power.T (1) (W)\n- inverterType: Inverter type, details refer to Table 4 in appendix\n- inverterStatus: Inverter status, details refer to Table 5 in appendix\n- uploadTime: Update time (format 2016-10-26 17:33:01)\n- batPower: Inverter.DC.Battery.power.total (1) (W)\n- powerdc1: Inverter.DC.PV.power.MPPT1 (1) (W)\n- powerdc2: Inverter.DC.PV.power.MPPT2 (1) (W)\n- powerdc3: Inverter.DC.PV.power.MPPT3 (1) (W)\n- powerdc4: Inverter.DC.PV.power.MPPT4 (1) (W)\n]]\n\n-- EOF"},{"name":"i18n","isMain":false,"isOpen":false,"content":"-- Quickapp Solax Monitor i18n translation\n\n\nclass \"i18n\"\nfunction i18n:translation(language)\n translation = {\n en = {\n [\"SIMULATION MODE\"] = \"SIMULATION MODE\", \n [\"Current Power\"] = \"Current Power\",\n [\"Solar Power/m²\"] = \"Solar Power/m²\",\n [\"Today Energy\"] = \"Today Energy\",\n [\"Total Energy\"] = \"Total Energy\",\n [\"Total Power to Grid\"] = \"Total Power to Grid\",\n [\"Total Energy to Grid\"] = \"Total Energy to Grid\",\n [\"Energy from Grid\"] = \"Energy from Grid\",\n [\"Total Power/m²\"] = \"Total Power/m²\",\n [\"Battery Energy\"] = \"Battery Energy\",\n [\"AC Power R\"] = \"AC Power R\",\n [\"AC Power S\"] = \"AC Power S\",\n [\"AC Power T\"] = \"AC Power T\",\n [\"Battery Power\"] = \"Battery Power\",\n [\"Power DC1\"] = \"Power DC1\",\n [\"Power DC2\"] = \"Power DC2\",\n [\"Power DC3\"] = \"Power DC3\",\n [\"Power DC4\"] = \"Power DC4\",\n [\"Inverter Type\"] = \"Inverter Type\",\n [\"Inverter Status\"] = \"Inverter Status\",\n [\"Last update\"] = \"Last update\"},\n pt = {\n [\"SIMULATION MODE\"] = \"MODO SIMULAÇÃO\", \n [\"Current Power\"] = \"Potência atual\",\n [\"Solar Power/m²\"] = \"Potência solar/m²\",\n [\"Today Energy\"] = \"Energia diária\",\n [\"Total Energy\"] = \"Total de energia\",\n [\"Total Power to Grid\"] = \"Potência total para a rede\",\n [\"Total Energy to Grid\"] = \"Energia injectada para a rede\",\n [\"Energy from Grid\"] = \"Energia da rede\",\n [\"Total Power/m²\"] = \"Potência total/m²\",\n [\"Battery Energy\"] = \"Energia da bateria\",\n [\"AC Power R\"] = \"Potência AC R\",\n [\"AC Power S\"] = \"Potência AC S\",\n [\"AC Power T\"] = \"Potência AC T\",\n [\"Battery Power\"] = \"Potência bateria\",\n [\"Power DC1\"] = \"Potência DC1\",\n [\"Power DC2\"] = \"Potência DC2\",\n [\"Power DC3\"] = \"Potência DC3\",\n [\"Power DC4\"] = \"Potência DC4\",\n [\"Inverter Type\"] = \"Tipo dde inversor\",\n [\"Inverter Status\"] = \"Estado do inversor\",\n [\"Last update\"] = \"Ultimo update\"},\n nl = {\n [\"SIMULATION MODE\"] = \"SIMULATIE MODE\", \n [\"Current Power\"] = \"Huidig vermogen\",\n [\"Solar Power/m²\"] = \"Zon energie/m²\",\n [\"Today Energy\"] = \"Energie vandaag\",\n [\"Total Energy\"] = \"Energie totaal\",\n [\"Total Power to Grid\"] = \"Totaal vermogen naar Grid\",\n [\"Total Energy to Grid\"] = \"Totaal energie naar Grid\",\n [\"Energy from Grid\"] = \"Energie van Grid\",\n [\"Total Power/m²\"] = \"Totaal vermogen/m²\",\n [\"Battery Energy\"] = \"Batterij Energie\",\n [\"AC Power R\"] = \"AC vermogen R\",\n [\"AC Power S\"] = \"AC vermogen S\",\n [\"AC Power T\"] = \"AC vermogen T\",\n [\"Battery Power\"] = \"Battery vermogen\",\n [\"Power DC1\"] = \"Vermogen DC1\",\n [\"Power DC2\"] = \"Vermogen DC2\",\n [\"Power DC3\"] = \"Vermogen DC3\",\n [\"Power DC4\"] = \"Vermogen DC4\",\n [\"Inverter Type\"] = \"Inverter Type\",\n [\"Inverter Status\"] = \"Inverter Status\",\n [\"Last update\"] = \"Laatst bijgewerkt\"},\n } \n translation = translation[language] -- Shorten the table to only the current translation\n return translation\nend\n\n-- EOF"}]}