Skip to main content
loading
By Michal Novotný
December 19, 2025
Smart Home vs GoodWe

In the post, we will demonstrate step by step how to communicate directly with the Goodwe inverter in a smart home setup and obtain real-time information (unlike the SEMS portal). This information is essential if we want to react to current parameters in a smart home, such as activating additional cooling or controlling a socket with a load.

Hardware

Pi-Home - if you don't have it, see the section How To

Software

OpenHAB 3

Procedure:

1) We will connect via SSH to the Raspberry and verify if we have the pip3 manager for Python libraries installed:

sudo apt install python3-pip

then we will install the goodwe library:

 sudo pip3 install goodwe

 

2) We will navigate to the scripts directory for OpenHAB, create a file named "goodwejson.py," and test the communication:

cd /etc/openhab/scripts

sudo nano goodwejson.py

 

Insert the following content here, replacing the IP address marked in red with your actual GoodWe inverter's IP address:

import asyncio 
import goodwe 

asyncdef get_runtime_data(): 
   ip_address = '192.168.1.100
   sensors = [ 
       "ppv",               # PV total power (W)
       "ppv1",              # PV1 power (W)
       "ppv2",              # PV2 power (W)
       "temperature",       # Inverter Temp Radiator
       "temperature_air",   # Inverter Temp Air
       "battery_temperature", # battery temperature
       "pbattery1",         # battery power (W) + = charging, - = discharging
       "battery_mode",      # 1=standby, 2=discharge, 3=charge
       "battery_soc",       # battery state of charge (%)
       "active_power",      # grid power (W): - = buy, + = sell
       "grid_in_out",       # 1=sell or export, 2=buy or import
       "house_consumption", # own consumption (W)
       "e_day",             # today's PV energy production (kWh)
       "e_total",           # total PV energy production (kWh)
       "meter_e_total_exp", # total sold (exported) energy (kWh)
       "meter_e_total_imp" # total bought or imported energy (kWh)
   ] 

   inverter = await goodwe.connect(ip_address) 
   runtime_data = await inverter.read_runtime_data() 
   print(f'{{') 
   for sensor in inverter.sensors(): 
       if sensor.id_ in runtime_data: 
           if sensor.id_ in sensors: 
               print(f'"{sensor.id_}": {runtime_data[sensor.id_]},') 
   print(f'"end": 0') 
   print(f"}}") 

asyncio.run(get_runtime_data())


 

save by pressing the CTRL+O keyboard shortcut, confirm with Enter, and exit the nano editor by pressing CTRL+X.

Test if the script fetches current data, for example:

python3 goodwejson.py

 

3) Create another script in the same folder, named goodwe.sh:

sudo nano goodwe.sh

and paste following content:


#!/bin/bash
 
RESULT=$(python3 /etc/openhab/scripts/goodwejson.py)

echo"$RESULT"| tr '\n'' '


 

Save using the keyboard shortcut CTRL+O, confirm with Enter, and exit the nano editor (CTRL+X)

Let's also run a command regarding the permission settings for the file:

sudo chmod 744 goodwe.sh

and add it to the exec.whitelist file to allow execution:

sudo nano /etc/openhab/misc/exec.misc

It should contain the following:

# For security reasons, all commands used by the exec binding or transformation need to be whitelisted.
# Each command needs to be listed on a separate line below.
bash /etc/openhab/scripts/goodwe.sh
 

Save using the keyboard shortcut CTRL+O, confirm with Enter, and exit the nano editor (CTRL+X).

4) Let's create a .things file for OpenHAB, where we define the script and execution frequency (according to forum information, do not go below 30 seconds, as it might block your SEMS portal)

sudo nano /etc/openhab/things/exec.things

Insert the following content:

exec:command:goodwe_json [command="bash /etc/openhab/scripts/goodwe.sh", interval=30, timeout=10, autorun=false]

 

Save using the keyboard shortcut CTRL+O, confirm with Enter, and exit the nano editor (CTRL+X).

5) Define the .items file for OpenHAB - definition of custom objects

sudo nano /etc/openhab/items/goode.items

Insert the following content:

String ZP_JSON_Out "[%s]" {channel="exec:command:goodwe_json:output"}
Number:Energy   zpPv              "zpPv [%.0f W]"        <energy>
Number:Energy   zpPv1             "zpPv [%.0f W]"        <energy>
Number:Energy   zpPv2             "zpPv [%.0f W]"        <energy>
Number:Energy   zpIRad            "zpPv [%.1f °C]"        <energy>
Number:Energy   zpIAir            "zpPv [%.1f ˚C]"        <energy>
Number:Energy   zpBatteryTemp     "zpPv [%.1f °C]"        <energy>
Number:Energy   zpBattery         "zpBattery [%.0f W]"   <battery>
Number          zpBatteryStatus   "zpBatteryStatus [%d]" <battery>
Number          zpSoc             "zpSoc [%d %%]"        <battery>
Number:Energy   zpActivePower     "zpActivePower [%.0f W]" <energy>
Number          zpGridStatus      "zpGridStatus [%d]"
Number:Energy   zpConsumption     "zpConsumption [%.0f W]" <energy>
Number:Energy   zpEday            "zpEday [%.1f kWh]"    <energy>
Number:Energy   zpEtotal          "zpEtotal [%.0f kWh]"    <energy>
Number:Energy   zpEtotalExp       "zpEtotalExp [%.0f kWh]"    <energy>
Number:Energy   zpEtotalImp       "zpEtotalImp [%.0f kWh]"    <energy>

Save using the keyboard shortcut CTRL+O, confirm with Enter, and exit the nano editor (CTRL+X).

 6) Finally, we define the .rules file for OpenHAB - value transformations

sudo nano /etc/openhab/rules/goode.rules

Insert the following content:

rule "ZP JSON transform"
when
    Item ZP_JSON_Out changed
then
    val Pv = transform("JSONPATH","$.ppv",ZP_JSON_Out.state.toString)
    val Pv1 = transform("JSONPATH","$.ppv1",ZP_JSON_Out.state.toString)
    val Pv2 = transform("JSONPATH","$.ppv2",ZP_JSON_Out.state.toString)
    val InvRadTemp = transform("JSONPATH","$.temperature",ZP_JSON_Out.state.toString)
    val InvAirTemp = transform("JSONPATH","$.temperature_air",ZP_JSON_Out.state.toString)
    val BatteryTemp = transform("JSONPATH","$.battery_temperature",ZP_JSON_Out.state.toString)
    val Battery  = transform("JSONPATH","$.pbattery1",ZP_JSON_Out.state.toString)
    val BatteryStatus =  transform("JSONPATH","$.battery_mode",ZP_JSON_Out.state.toString)
    val Soc = transform("JSONPATH","$.battery_soc",ZP_JSON_Out.state.toString)
    val ActivePower = transform("JSONPATH","$.active_power",ZP_JSON_Out.state.toString)
    val GridStatus = transform("JSONPATH","$.grid_in_out",ZP_JSON_Out.state.toString)
    val Consumption = transform("JSONPATH","$.house_consumption",ZP_JSON_Out.state.toString)
    val Eday = transform("JSONPATH","$.e_day",ZP_JSON_Out.state.toString)
    val Etotal = transform("JSONPATH","$.e_total",ZP_JSON_Out.state.toString)
    val EtotalExp = transform("JSONPATH","$.meter_e_total_exp",ZP_JSON_Out.state.toString)
    val EtotalImp = transform("JSONPATH","$.meter_e_total_imp",ZP_JSON_Out.state.toString)


    zpPv.postUpdate(Pv)
    zpPv1.postUpdate(Pv1)
    zpPv2.postUpdate(Pv2)
    zpIRad.postUpdate(InvRadTemp)
    zpIAir.postUpdate(InvAirTemp)
    zpBatteryTemp.postUpdate(BatteryTemp)
    zpBattery.postUpdate(Battery)
    zpBatteryStatus.postUpdate(BatteryStatus)
    zpSoc.postUpdate(Soc)
    zpActivePower.postUpdate(ActivePower)
    zpGridStatus.postUpdate(GridStatus)
    zpConsumption.postUpdate(Consumption)
    zpEday.postUpdate(Eday)
    zpEtotal.postUpdate(Etotal)
    zpEtotalExp.postUpdate(EtotalExp)
    zpEtotalImp.postUpdate(EtotalImp)
end

 

Save using the keyboard shortcut CTRL+O, confirm with Enter, and exit the nano editor (CTRL+X).

Done. Now, take a look at OpenHAB under Items, and the information should be displayed and updated for you. You can download the Widget from this thread: https://community.openhab.org/t/animated-energy-widget/133510 and insert your GoodWe values there.

 

Examples of dashboards with installed PV systems:

 

 

 

 

Tags

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.