Files
solaredge_modbus_mqtt/README.md
T
2026-10-10 16:13:58 +02:00

118 lines
3.6 KiB
Markdown

## 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.
```shell
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
```yaml
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 bit
- `error_code` — inverter vendor error bitmask (0 = none), LCD-style codes
- `storage_control_mode_text` — e.g. `Backup Only`, `Maximize Self Consumption`
- `battery1_*` — 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`, `grid_import`,
`grid_export`, `battery_charge`, `battery_discharge`, `solar_to_house`) so the
dashboard's consumption-source panels are plain `mean()`/`integral()` queries.
**Sign calibration:** `meter1_power` positive = import and `battery1_power`
positive = discharge are assumptions observed once; verify on the first sunny
day (export while surplus / charge while battery fills). If inverted, flip
`METER_IMPORT_POSITIVE` / `BATTERY_DISCHARGE_POSITIVE` in
`solaredge_modbus_mqtt/__init__.py` and restart - all derived fields follow.
### Uninstall
```shell
docker update --restart=no solaredge_modbus_mqtt
docker stop solaredge_modbus_mqtt
```
### Update
```shell
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
```shell
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
```shell
pip3 install -r requirements.txt
cp config.yaml-dist config.yaml
python3 solaredge_modbus_mqtt.py
```
### Running tests
```shell
pip3 install -r requirements.txt
python3 -m unittest
```