Goodwe SEMS portal Solar panel data to Node-RED

UPDATE 1 nov 2021: Mind the power station ID!

The Goodwe PV solar panel inverters come with a webportal which show all it's performance. This Node-RED flow outputs a (small) part of the data available from this Goodwe SEMS portal at https://www.semsportal.com/. It's using the version 2 API.

Outputs from this flow include:

  • fysical address of the converter,
  • name of the station,
  • total power generated and
  • power generated today.

Much more data is readily available.

In the fuction nodes the flow needs these inputs:

  • The loginname to the portal,
  • The corresponding password (both set in the "Get ID token"-function node).
  • The power station ID, as found in the URL when logged into the portal.

The power station ID is set in the "Get station output"-function node. To find the ID for your installation, login to the normal SEMS webportal. Once logged in, the last part of the URL in your webbrowser is the ID. Copy this part into the script for the variable "psid".

Among other sources, this helped most: https://github.com/DiedB/Homey-SolarPanels/issues/28#issuecomment-521042829

The first HTTP API call returns a session login token ID. This token is used in the second call, which returns all data. It seems the word "token" is used differently throughout the API, which can be confusing. The token is session-bound and expires in ? time. Replies from the "Request station" call can be delayed upto 10-ish seconds.

[{"id":"8d9517ae094a5e8f","type":"tab","label":"Query SEMS portal for Goodwe Inverter","disabled":false,"info":""},{"id":"7666019830c94009","type":"debug","z":"8d9517ae094a5e8f","name":"Token Details","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":200,"wires":[]},{"id":"35b7837b9e219f92","type":"http request","z":"8d9517ae094a5e8f","name":"Request token","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":480,"y":240,"wires":[["7666019830c94009","2f2802572b0a16fa"]]},{"id":"20f12cc0ec2b10df","type":"function","z":"8d9517ae094a5e8f","name":"Get ID token from login","func":"// Credentials as used for login to the Semsportal at https://www.semsportal.com/\n\naccount = \"YOUR_SEMS_USERNAME\";\npwd = \"YOUR_SEMS_PASSWORD\";\n\n// ---------- no changes needed below ----------------------------\nloginPayload = { 'account': account, 'pwd': pwd };\n\n// It's a given, likely from the API documentation?\ntoken = '{\"client\": \"ios\", \"version\": \"v2.1.0\", \"language\": \"en\"}';\n\nglobal_url = 'https://www.semsportal.com/api/';\nheaders = { 'token': token };\n\nmsg.url = global_url + \"v2/Common/CrossLogin\";\nmsg.headers = headers;\nmsg.payload = loginPayload;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":180,"wires":[["35b7837b9e219f92"]]},{"id":"6b960b40ef6d9b5c","type":"inject","z":"8d9517ae094a5e8f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":220,"y":180,"wires":[["20f12cc0ec2b10df"]]},{"id":"2f2802572b0a16fa","type":"function","z":"8d9517ae094a5e8f","name":"Get station output","func":"if(msg==\"no response from server\") { return; }\n\n// Power station ID can be found in the last part of the URL of the SEMSportlal, once logged in\n\n// Power station ID can be found in the last part of the URL of the SEMSportlal, once logged in\npsid = 'd0eac052-96....GET YOUR OWN CODE HERE....d0';\n\n\n// -------------- Generic below ---------------------------------\n\n// https://github.com/DiedB/Homey-SolarPanels/issues/28\n\n// Get the relevant response from the login call: \nvar uid = msg.payload.data.uid; // User ID\nvar id_token = msg.payload.data.token; // Time-bound token from login\nvar timestamp = msg.payload.data.timestamp;\n\n// Warning: The API uses 'token' with different meanings throughout the communication\ntoken = '{\"uid\": \"'+ uid + '\", \"timestamp\": '+ timestamp+ ', \"token\": \"'+ id_token + '\", \"client\": \"ios\", \"version\": \"v2.0.4\", \"language\": \"en\"}';\nheaders = { 'User-Agent': 'JH', 'Token': token }\n\nglobal_url = 'https://www.semsportal.com/api/'\nmsg.url = global_url + \"v2/PowerStation/GetMonitorDetailByPowerstationId\";\n\nmsg.headers = headers;\n\npayload = {'powerStationId': psid};\nmsg.payload = payload;\n\nreturn msg;\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":300,"wires":[["c63f21c5f355ef7a","abc27ec229e67dd6"]]},{"id":"ed7ace700ba8677a","type":"debug","z":"8d9517ae094a5e8f","name":"Data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":890,"y":420,"wires":[]},{"id":"c63f21c5f355ef7a","type":"http request","z":"8d9517ae094a5e8f","name":"Request station","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":620,"y":360,"wires":[["ebf19d5d3f71fc32","f6c3c5bea5812317","98187240f169989f"]]},{"id":"ebf19d5d3f71fc32","type":"function","z":"8d9517ae094a5e8f","name":"Get values","func":"// Get values as shown in the webportal:\n\n// Stationname, top left as displayed in the dropdown (not sure how more stations handle....?)\nvar station_name = msg.payload.data.info.stationname;\n\n// Fysical address\nvar address = msg.payload.data.info.address;\n\n// Total power als shown on the webportal left below today's production\nvar total_power = msg.payload.data.kpi.total_power;\n\n// Today's power als in the circle middle down the webportal main page\nvar day_power = msg.payload.data.kpi.power;\n\nmsg = {};\n\nmsg.payload = {'station_name': station_name, 'address': address, 'total_power': total_power, 'day_power': day_power};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":420,"wires":[["ed7ace700ba8677a"]]},{"id":"f6c3c5bea5812317","type":"debug","z":"8d9517ae094a5e8f","name":"Station Info","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":830,"y":360,"wires":[]},{"id":"98187240f169989f","type":"change","z":"8d9517ae094a5e8f","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.data.inverter[0].d","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":840,"y":300,"wires":[["a962b60aa198dfb0"]]},{"id":"a962b60aa198dfb0","type":"debug","z":"8d9517ae094a5e8f","name":"Data","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":300,"wires":[]},{"id":"abc27ec229e67dd6","type":"debug","z":"8d9517ae094a5e8f","name":"Token Details","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":760,"y":240,"wires":[]}]

Flow Info

Created 3 years, 5 months ago
Updated 2 years, 8 months ago
Rating: 5 3

Owner

Actions

Rate:

Node Types

Core
  • change (x1)
  • debug (x5)
  • function (x3)
  • http request (x2)
  • inject (x1)
Other
  • tab (x1)

Tags

  • Goodwe
  • Sems
  • Solar
  • panel
  • converter
  • output
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option