Verified against simultaneous SolarEdge app readings (PV 40 W, battery discharge 520 W, house 560 W): battery1_power negative means discharge, and power_ac on this DC-coupled Energy Hub is the inverter's TOTAL AC output - it already contains the battery contribution. The old formula double-counted the battery, so house_load collapsed (44 W shown vs 560 W real) and the PV tile showed battery-inflated totals, which looked like PV and house consumption were swapped. New derived fields: house_load = power_ac + grid, and pv_power = power_ac - battery (true PV production). Dashboard PV tiles and both yield panels now use pv_power / integral(pv_power) - the energy_total lifetime counter also counts battery throughput and is not a PV yield.
3.7 KiB
Usage
Installation
The easiest way this is to run the docker container and set it to restart always. This basically makes it a system service that will always run.
To make it safe and avoid passing credentials we're using a configuration file.
mkdir /etc/solaredge_modbus_mqtt
chmod 700 /etc/solaredge_modbus_mqtt
cp config.yaml-dist /etc/solaredge_modbus_mqtt/config.yaml
docker run --detach --name=solaredge_modbus_mqtt --restart=always --volume=/etc/solaredge_modbus_mqtt/config.yaml:/app/config.yaml marijnkoesen/solaredge_modbus_mqtt:latest
Configuration
modbus:
host: 192.168.178.28 # inverter (SunSpec over Modbus TCP)
port: 1502
timeout: 1
unit: 1
influx:
url: http://influx.example.com:8086
db: solaredge
user: ~ # optional basic-auth user with WRITE on the db
pass: ~
measurement: solaredge
poll_interval: 3
The daemon polls the inverter and writes one line-protocol point per cycle directly
to InfluxDB. If InfluxDB is unreachable, points are spooled to spool.txt and
replayed on the next successful write (capped at 20000 lines). Mount a volume for
/app/spool.txt if backlog across container restarts matters.
model and serialnumber are written as tags; everything else as fields.
Off-grid / fail-over
offgrid— boolean, true while the inverter runs islanded (off-grid) — vendor event biterror_code— inverter vendor error bitmask (0 = none), LCD-style codesstorage_control_mode_text— e.g.Backup Only,Maximize Self Consumptionbattery1_*— SOE/SOH, power, voltage, temperatures, status of battery 1
Register addresses were validated by probing a SE10K-RWB48BFN4 (fw 0004.0025.0011) with one battery and one meter. Blocks that fail to read (flaky gateway) are skipped for that cycle; the fields are simply absent from the point.
Grafana dashboard
Import grafana_dashboard.json (Dashboards -> New -> Import). Select your
InfluxDB datasource when prompted (e.g. InfluxDB-HJK); the $serial variable
is filled from the serialnumber tag. InfluxQL only, InfluxDB 1.x.
The daemon also writes derived flow fields (house_load, pv_power,
grid_import, grid_export, battery_charge, battery_discharge,
solar_to_house) so the dashboard's consumption-source panels are plain
mean()/integral() queries.
Sign conventions (verified against the SolarEdge app): meter1_power
positive = export, battery1_power negative = discharge, and power_ac is
the inverter's total AC output (PV + battery, DC-coupled Energy Hub) - which
is why pv_power = power_ac - battery and house_load = power_ac + grid.
If a different system disagrees, flip METER_IMPORT_POSITIVE /
BATTERY_DISCHARGE_POSITIVE in solaredge_modbus_mqtt/__init__.py and
restart - the derived fields follow.
Uninstall
docker update --restart=no solaredge_modbus_mqtt
docker stop solaredge_modbus_mqtt
Update
docker update --restart=no solaredge_modbus_mqtt
docker stop solaredge_modbus_mqtt
docker rm solaredge_modbus_mqtt
docker run --detach --name=solaredge_modbus_mqtt --restart=always --volume=/etc/solaredge_modbus_mqtt/config.yaml:/app/config.yaml marijnkoesen/solaredge_modbus_mqtt:latest
For developers
Building and running the docker image
docker build -t solaredge_modbus_mqtt:latest .
or
docker buildx build --platform linux/amd64 solaredge_modbus_mqtt:latest .
cp config.yaml-dist config.yaml
docker run --volume=$PWD/config.yaml:/app/config.yaml solaredge_modbus_mqtt:latest
Running without docker
pip3 install -r requirements.txt
cp config.yaml-dist config.yaml
python3 solaredge_modbus_mqtt.py
Running tests
pip3 install -r requirements.txt
python3 -m unittest