Skip to content

Instantly share code, notes, and snippets.

@juhaautioniemi
Created March 7, 2017 08:58
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juhaautioniemi/0850bcda0d246dd7d3141308522d00a7 to your computer and use it in GitHub Desktop.
Save juhaautioniemi/0850bcda0d246dd7d3141308522d00a7 to your computer and use it in GitHub Desktop.
Get solar power plant data from SMA Sunny Webbox using RPC API

Description

This flow requests data directly from Sunny Webbox data acquisition unit every 30 seconds (00:00:30, 00:01:00... etc) and then parses the result only if response payload.result has changed or timeout value has reached 1800 seconds.

Returned values are current power [W], daily energy [kWh], total energy [kWh], current mode and error message.

Created and tested with Node-RED 0.16.2 and Node.js 6.10.0 in Windows 10 machine. Connection to Sunny Webbox is established over local area network.

User actions

Change Sunny Webbox IP address (msg.url for HTTP request) to match your Sunny Webbox.

RPC API

SMA Sunny Webbox RPC API: http://files.sma.de/dl/4253/SWebBoxRPC-eng-BUS112713.pdf

[{"id":"c82c82cf.19283","type":"http request","z":"b41f15af.eabd08","name":"make HTTP POST request","method":"POST","ret":"obj","url":"","tls":"","x":796.6000518798828,"y":117.59999084472656,"wires":[["141953eb.2f3e3c","73b171a1.86fc7"]]},{"id":"d33e0fa.2fc7df","type":"function","z":"b41f15af.eabd08","name":"Create GetPlantOverview request","func":"msg.url = \"http://172.16.26.144/rpc\"\nmsg.payload='RPC={\"proc\":\"GetPlantOverview\",\"format\":\"JSON\",\"version\":\"1.0\",\"id\":\"1\"}'\nreturn msg;","outputs":1,"noerr":0,"x":494.6000518798828,"y":117.60003662109375,"wires":[["c82c82cf.19283"]]},{"id":"b40f01a4.070f9","type":"function","z":"b41f15af.eabd08","name":"Parse GetPlantOverview","func":"data = msg.payload\n\nvar tsUTC = flow.get(\"tsUTC\");\nvar tsLocal = flow.get(\"tsLOCAL\");\n\nvar power = 0;\nvar daily = 0;\nvar total = 0;\nvar opstt = \"\";\nvar msgtt = \"\";\n\ntsUTC = flow.get(\"tsUTC\")\nmsg = { \n \"payload\": {\n \"d\": { }, \n \"ts\": tsUTC\n }\n};\n\nmsg.payload.d.power = {};\nmsg.payload.d.power.value = {};\n\nmsg.payload.d.daily_energy = {};\nmsg.payload.d.daily_energy.value = {};\n\nmsg.payload.d.total_energy = {};\nmsg.payload.d.total_energy.value = {};\n\n\npower = parseFloat(data.result.overview[0].value);\ndaily = parseFloat(data.result.overview[1].value);\ntotal = parseFloat(data.result.overview[2].value);\nopstt = data.result.overview[3].value;\nmsgtt = data.result.overview[4].value;\n\nif(msgtt === \"\")\n{\n msgtt = \"-\"; \n}\n\nmsg.payload.d.power.value = power;\nmsg.payload.d.daily_energy.value = daily;\nmsg.payload.d.total_energy.value = total;\n\nnode.status({fill:\"blue\",shape:\"dot\",text:\"Latest update: \"+tsUTC});\n \nreturn msg;","outputs":"1","noerr":0,"x":668.6001129150391,"y":322.59999084472656,"wires":[["445a951a.ad1d3c","333ec82a.d14278"]]},{"id":"445a951a.ad1d3c","type":"debug","z":"b41f15af.eabd08","name":"MQTT payload to Watson IoT","active":true,"console":"false","complete":"payload","x":1005.6001739501953,"y":321.2000274658203,"wires":[]},{"id":"7404fc7.2481204","type":"file","z":"b41f15af.eabd08","name":"Save to log file","filename":"","appendNewline":true,"createDir":true,"overwriteFile":"false","x":1319.5000762939453,"y":355.7999725341797,"wires":[]},{"id":"333ec82a.d14278","type":"function","z":"b41f15af.eabd08","name":"Create filename by year, month and date","func":"function addZero(i) {\n if (i < 10) {\n i = \"0\" + i;\n }\n return i;\n}\n\nmsg.filename = \"\";\n\nvar nowDate = new Date(); \n\nvar year = nowDate.getFullYear();\nvar month = addZero(nowDate.getMonth()+1);\nvar day = addZero(nowDate.getDate());\nvar hh = addZero(nowDate.getHours());\nvar mm = addZero(nowDate.getMinutes());\nvar ss = addZero(nowDate.getSeconds());\n\nvar date = year+'-'+month+'-'+day; \n\nmsg.filename = \"c:\\\\data\\\\\"+year+\"\\\\\"+month+\"\\\\\"+date+\"-\"+\"webbox.json\";\n\nreturn msg;","outputs":1,"noerr":0,"x":1045.500015258789,"y":355.7999725341797,"wires":[["7404fc7.2481204"]]},{"id":"c364c5c5.809158","type":"inject","z":"b41f15af.eabd08","name":"interval 30 s | timeout 1800 s","topic":"","payload":"{\"interval\": 30, \"timeout\":1800}","payloadType":"json","repeat":"1","crontab":"","once":false,"x":165,"y":28.799942016601562,"wires":[["e1cdb574.3aaca8"]]},{"id":"e1cdb574.3aaca8","type":"function","z":"b41f15af.eabd08","name":"release every 30 secs","func":"function addZero(i) {\n if (i < 10) {\n i = \"0\" + i;\n }\n return i;\n}\n\nvar date = new Date();\n\nvar year = date.getFullYear();\nvar month = addZero(date.getMonth()+1);\nvar day = addZero(date.getDate());\nvar hh = addZero(date.getHours());\nvar mm = addZero(date.getMinutes());\nvar ss = addZero(date.getSeconds());\nvar minutes = date.getMinutes();\nvar seconds = date.getSeconds();\n\nvar tsLocal = year + \"-\" +month+ \"-\" + day+\" \" + hh + \":\" + mm+ \":\" + ss;\n\nflow.set(\"timeout\",msg.payload.timeout);\n \ntimeoutCount = flow.get(\"timeoutCount\")||0;\n \nvar interval = msg.payload.interval;\nvar returnValue = false;\n \nmsg.payload.ts = date.toISOString();\nflow.set(\"tsUTC\",msg.payload.ts)\nflow.set(\"tsLOCAL\",tsLocal)\ntimeoutCount++;\nflow.set(\"timeoutCount\",timeoutCount); \n \nvar total = (minutes * 60) + seconds;\n \nvar remainder = total % interval;\n \nif(remainder === 0)\n{\n returnValue = true;\n node.status({fill:\"green\",shape:\"dot\",text:\"total: \"+total +\" | \"+ \"remainder: \"+remainder +\" | \" + \"Interval hit...\"});\n}\nelse\n{\n returnValue = false; \n node.status({fill:\"red\",shape:\"dot\",text:\"total: \"+total +\" | \"+ \"remainder: \"+remainder +\" | \" + \"Waiting...\"});\n}\n\nif(returnValue){ return msg; }","outputs":1,"noerr":0,"x":194,"y":117.79994201660156,"wires":[["d33e0fa.2fc7df"]]},{"id":"141953eb.2f3e3c","type":"function","z":"b41f15af.eabd08","name":"Continue if payload data has changed or timeout hits","func":" var d = context.get(\"d\")||\"\";\n var timeoutCount = flow.get(\"timeoutCount\")||\"\";\n var timeout = flow.get(\"timeout\");\n var returnValue = false;\n var data = JSON.stringify(msg.payload.result); \n \n if(data != d)\n {\n returnValue = true;\n node.status({fill:\"green\",shape:\"dot\",text: \"timeoutCount: \"+timeoutCount +\" / \"+timeout+ \" | \" + \"Payload changed...\"});\n timeoutCount = 0; \n }\n else if(timeoutCount >= timeout)\n {\n returnValue = true;\n node.status({fill:\"green\",shape:\"dot\",text: \"timeoutCount: \"+timeoutCount+\" / \"+timeout+\" | \" + \"Timeout...\"});\n timeoutCount = 0; \n }\n else\n {\n node.status({fill:\"red\",shape:\"dot\",text:\"timeoutCount: \"+timeoutCount +\" / \"+timeout+ \" | \" + \"Payload not changed...\"});\n returnValue = false; \n }\n\n flow.set(\"timeoutCount\",timeoutCount); \n context.set(\"d\",data);\n if(returnValue){ return msg; }","outputs":1,"noerr":0,"x":622.0001068115234,"y":225.7999267578125,"wires":[["b40f01a4.070f9"]]},{"id":"85c91f4f.70f0d","type":"comment","z":"b41f15af.eabd08","name":"Set your Webbox IP address here","info":"","x":496.50001525878906,"y":85.19999694824219,"wires":[]},{"id":"73b171a1.86fc7","type":"debug","z":"b41f15af.eabd08","name":"Original GetPlantOverview response","active":true,"console":"false","complete":"payload","x":1148.1998443603516,"y":117.19999694824219,"wires":[]}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment