I saw some requests on how to connect the Goodwe Solar Panel Inverter to openhab using the Goodwe’s API. Therefore, I would like to share my solution with you.
Some prerequisites:
- You should have the SEMSPORTAL up and running with your Inverter
- I propose you set up a second user in the portal for openhab. (if you log in with the same user twice at the same time, the portal will terminate the session.)
- Find your PowerStationId in the SEMSPORTAL. You can see it in the URL when you log in and it looks something like this: abcdef10-8ccf-23df-8d12-b123456b123b
- Install the exec binding and JSON transformation binding in openhab.
First of all, you need to write a small shell script. Make sure you put in you semsportal accountname, password and your PowerStationID:
/etc/openhab2/scripts/semsapi.sh
#!/bin/bash
RESULT=$(curl https://www.semsportal.com/api/v2/Common/CrossLogin --silent --header "Content-Type: application/json" --header "Connect: keep-alive" --header "User-Agent: PVMaster/2.1.0 (iPhone; iOS 13.0; Scale/2.00)" --header "Accept-Language: en;q=1" --header "Token: {\"version\":\"v2.1.0\",\"client\":\"ios\",\"language\":\"en\"}" --data-binary "{\"account\":\"secondopenhabuser@gmail.com\",\"pwd\":\"yourpassword\"}")
HEADER=$(echo "$RESULT"|jq ".data"|tr '\n' ' ')
RETURN=$(curl https://www.semsportal.com/api/v2/PowerStation/GetMonitorDetailByPowerstationId --silent --header "Content-Type: application/json" --header "Accept: */*" --header "User-Agent: PVMaster/2.1.0 (iPhone; iOS 13.0; Scale/2.00)" --header "Accept-Language: DE;q=1" --header 'Token: '"$HEADER" --data-binary "{\"powerStationId\":\"abcdef10-8ccf-23df-8d12-b123456b123b\"}")
echo "$RETURN" | jq ".data"
You can minimize the output by tweaking with the jq command at the end. For now, it returns all available data. Make sure the script is executable and test it. You should see a long JSON-Output with all the values from your inverter.
Next, let’s get this output into openhab. So, let’s configure the exec binding to start the script every minute:
/etc/openhab2/things/exec.things
exec:command:semsportal_json [command="bash /etc/openhab2/scripts/semsapi.sh",interval=60, timeout=10, autorun=false]
/etc/openhab2/items/goodwe.items
String PV_JSON_Out "[%s]" {channel="exec:command:semsportal_json:output"}
Here are some example values I read from my Inverter. Adjust to you needs:
/etc/openhab2/items/goodwe.items
Number:Energy UG_PV_Total_Output "Total Output [%.1f kWh]" <energy>
Number:Energy UG_PV_Grid "Grid [%.1f W]" <energy>
Number:Energy UG_PV_Output_Power "Output Power [%.1f W]" <energy>
Number:Energy UG_PV_Home_Load "Home Load [%.1f W]" <energy>
Number:Energy UG_PV_Todays_Output "Today's Output [%.1f kWh]" <energy>
Number:Energy UG_PV_Battery "Battery Output [%.1f W]" <energy>
Number UG_PV_SoC "Battery SoC [%d %%]" <battery>
And this is the rule that does all the magic in openhab, put this in a rule file, e.g.
/etc/openhab2/rules/goodwe.rules
rule "PV JSON transform"
when
Item PV_JSON_Out changed
then
val totalOutput = transform("JSONPATH","$.inverter[0].etotal",PV_JSON_Out.state.toString)
val todaysOutput = transform("JSONPATH","$.inverter[0].eday",PV_JSON_Out.state.toString)
val grid = transform("JSONPATH","$.powerflow.grid",PV_JSON_Out.state.toString)
val outputPower = transform("JSONPATH","$.powerflow.pv",PV_JSON_Out.state.toString)
val homeLoad = transform("JSONPATH","$.powerflow.load",PV_JSON_Out.state.toString)
val battery = transform("JSONPATH","$.powerflow.bettery",PV_JSON_Out.state.toString)
val soc = transform("JSONPATH","$.powerflow.soc",PV_JSON_Out.state.toString)
UG_PV_Total_Output.postUpdate(totalOutput)
UG_PV_Todays_Output.postUpdate(todaysOutput)
UG_PV_Grid.postUpdate(grid.toString.replace('(',' ').replace(')',''))
UG_PV_Output_Power.postUpdate(outputPower.toString.replace('(',' ').replace(')',''))
UG_PV_Home_Load.postUpdate(homeLoad.replace('(',' ').replace(')',''))
UG_PV_Battery.postUpdate(battery.replace('(',' ').replace(')',''))
UG_PV_SoC.postUpdate(soc)
end
That’s all. Let me know, if you got it working or need some help. Happy to see your ideas on what to do with all the information.
- RogerG