Skip to content

About

This ESP tool reads the metrics data from the Solax X3 Hybrid Gen4 inverter via modbus and writes it to a InfluxDB

Resources

Stars

3 stars

Watchers

1 watching

Forks

Latest commit

 

History

9 Commits

Folders and files

Repository files navigation

Solax X3 Hybrid esp8266 modbus-to-influxdb converter

This ESP tool reads the metrics data from the Solax X3 Hybrid Gen4 inverter via modbus and writes it to an InfluxDB.

  • Reads the important metrics data from the Solax inverter modbus input register
  • Stores the metrics in an InfluxDB (in my case hosted on a Raspberry Pi, visualized in a Grafana dashboard)
  • Exposes the same data read-only in the local network as JSON (GET /status) plus a health endpoint (GET /health)
  • Pushes the current grid feed-in surplus to a Nibe heat pump bridge

Polling interval

DATA_POLL_INTERVAL is 1000 ms, but each of the 42 input registers is read in its own Modbus transaction with a busy-wait of at least 25 ms. The effective cycle time is therefore roughly 2-3 seconds, not one second.

Hardware

  • The Solax X3 Hybrid Gen4 inverter provides a modbus RTU (RS485) interface (it is called COM on the inverter)
    • Remark: some older versions of this inverter also supported modbus TCP but since the 4th generation this option was removed (I don't understand why??)
    • The modbus default baudrate for this device is 19200 (8N1, slave ID 1)
  • I used the NodeMCU version of esp8266 (NodeMCU 1.0 / ESP-12E)
  • A RJ45 socket is used for this interface
  • For the RS485 connection on the ESP you need a level converter (in my case I used the MAX485)

Pinning

On the inverter side — RJ45 pinout of the COM port:

RJ45 pin Signal
4 RS485 A
5 RS485 B
6 GND (optional, was not required in my case)

On the ESP side — the MAX485 sits between them:

MAX485 NodeMCU Direction
RO (receiver out) D2 MAX485 -> ESP (RX)
DI (driver in) D1 ESP -> MAX485 (TX)
DE + RE (tied together) D3 ESP -> MAX485 (transmit enable)
A / B — to RJ45 pin 4 / 5 on the inverter

Note that D1/D2 carry the TTL side (RO/DI), not A/B. A/B is the RS485 differential pair going to the inverter.

Configuration

Credentials are not in the repository. Copy the template and fill in your values:

cp project/secrets.h.example project/secrets.h
$EDITOR project/secrets.h

project/secrets.h is gitignored. It holds the WiFi credentials, the static IP, the InfluxDB URL/token/org/bucket and the Nibe bridge URL. Set NIBE_API_URL to "" if you don't have a heat pump to talk to.

Building and flashing

Either open project/project.ino in the Arduino IDE as before, or use the provided Makefile (requires arduino-cli):

make build                                  # compile
make ports                                  # find the board
make flash PORT=/dev/cu.usbserial-0001      # compile + upload
make monitor PORT=/dev/cu.usbserial-0001    # serial log at 115200 baud

Verified toolchain (pinned in project/sketch.yaml):

Component Version
esp8266 core 3.1.2
modbus-esp8266 4.1.0
ESP8266 Influxdb 3.13.2

Data semantics

InfluxDB receives the raw register values, not scaled units. Most registers carry a factor of 0.1 (voltage in 0.1 V, current in 0.1 A, energy in 0.1 kWh; the feedin_energy_* / consum_energy_* counters use 0.01 kWh). The conversion happens in the Grafana dashboard so that the historical series stay consistent. The factor for every register is documented inline in project/project.ino.

REST API

Endpoint Response
GET /status JSON object with the numeric registers from the most recent poll cycle, CORS enabled
GET /health 200 when modbus and InfluxDB are both fine, 503 with a JSON error body otherwise
GET /nibe Current state of the heat pump push
POST /nibe?enabled=true|false Switch the heat pump push on/off, persisted in EEPROM

Heat pump push switch

The push to the Nibe bridge can be toggled at runtime without reflashing. The setting is stored in the emulated EEPROM and survives a reboot and a firmware update. Accepted values are true|false, 1|0 and on|off.

curl http://192.168.1.41/nibe
# {"enabled":true,"configured":true,"active":true}

curl -X POST "http://192.168.1.41/nibe?enabled=false"
# {"enabled":false,"configured":true,"active":false}
Field Meaning
enabled the persisted switch
configured whether NIBE_API_URL is set at all
active enabled && configured — whether a push actually happens

The default on a fresh chip is enabled: true, matching the behaviour before the switch existed. The EEPROM is only written when the value actually changes, so repeated calls cost no flash write cycles.

About

This ESP tool reads the metrics data from the Solax X3 Hybrid Gen4 inverter via modbus and writes it to a InfluxDB

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages