Universal Solar Inverter over Modbus RS485 to MQTT (Formally SolaX No Pocket WiFi)

Hi,
i want to share my project to connect a Solax X1/X3 Solar Inverter without Solax Cloud and without Pocket Wifi. Data will be read complete locally by Modbus RS-485 RTU and share it via MQTT.
So any Homeautomatisation solution has access to that Solar LiveData.

Please visit my github project: GitHub - tobiasfaust/SolaxModbusGateway: Solax Modbus to MQTT Gateway

Screenshot of Webfrontend:

1 Like

You can use Tasmota if you want.

as far as i know the tasmota extension does not support Solax G4 series, only G3 Series.
I tested it some weeks before.

@tobiasfaust Thanks for sharing your project! I’ve been trying to connect my Solax X1 Boost (serial number starts with XB) inverter through RS485, but I’ve been unsuccessful so far.

Shouldn’t it be possible to utilize ESPHome’s (or ESPEasy, etc.) native modbus functionality, at least for reading basic data (powerdc1, etc.)? I must note that I don’t know much about the protocol, but the documentation provided in your repository appears pretty standard, e.g. function code 0X04 for reading input registers.

When I connect to the inverter using ESPHome and baud rate 9600 I receive the following error:

[D][modbus:115]: Modbus error function code: 0x84 exception: 2
[E][modbus_controller:068]: Modbus error function code: 0x4 exception: 2 
[E][modbus_controller:072]: Modbus error - last command: function code=0x4  register address = 0xA  registers count=2 payload size=0

It feels like I’m close to fetching data from the inverter, but there’s an addressing error (exception 2).

I finally got this to work without another custom firmware. It’s just ESPHome and getting the addressing right for my Solax X1 Boost (XB33…) was the biggest challenge. I’m using a Wemos D1 Mini with this Modbus Shield V2 to send the measurements to HA wirelessly. You don’t need the shield, since the wiring is pretty easy, but it cleans up the project nicely.

ESPHome Confguration
# Enable/Disable logging
logger:
  # level: VERY_VERBOSE
  baud_rate: 0 ## Must be 0 to prevent reading issues and buffer overflows

uart:
  id: mod_bus
  tx_pin: D7
  rx_pin: D6
  baud_rate: 9600
  stop_bits: 1
  
modbus:
  flow_control_pin: D5
  id: modbus1
  send_wait_time: 1000ms

modbus_controller:
  - id: solax
    address: 0x1
    modbus_id: modbus1
    setup_priority: -10
    #command_throttle: 250ms
    update_interval: 15s

sensor:
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} PV1 Input Voltage"
    address: 0x400
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 1
    unit_of_measurement: V
    device_class: voltage
    state_class: measurement
    filters:
      - multiply: 0.1
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} PV2 Input Voltage"
    address: 0x401
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 1
    unit_of_measurement: V
    device_class: voltage
    state_class: measurement
    filters:
      - multiply: 0.1
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} PV1 Input Current"
    address: 0x402
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 1
    unit_of_measurement: A
    device_class: current
    state_class: measurement
    filters:
      - multiply: 0.1
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} PV2 Input Current"
    address: 0x403
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 1
    unit_of_measurement: A
    device_class: current
    state_class: measurement
    filters:
      - multiply: 0.1
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} Grid Voltage"
    address: 0x404
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 1
    unit_of_measurement: V
    device_class: voltage
    state_class: measurement
    filters:
      - multiply: 0.1
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} Grid Frequency"
    address: 0x407
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 2
    unit_of_measurement: Hz
    device_class: frequency
    state_class: measurement
    filters:
      - multiply: 0.01
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} Output Current"
    address: 0x40A
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 1
    unit_of_measurement: A
    device_class: current
    state_class: measurement
    filters:
      - multiply: 0.1
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} Temperature"
    address: 0x40D
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0
    unit_of_measurement: C
    device_class: temperature
    state_class: measurement
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} Inverter Power"
    address: 0x40e
    register_type: read
    value_type: U_WORD
    unit_of_measurement: W
    device_class: power
    state_class: measurement
    accuracy_decimals: 0
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} Run Mode"
    address: 0x40f
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0
  # - platform: modbus_controller
  #   modbus_controller_id: solax
  #   name: "${prefix} Output Power"
  #   address: 0x410
  #   register_type: read
  #   value_type: U_WORD
  #   accuracy_decimals: 0
  - platform: modbus_controller
    modbus_controller_id: solax
    id: ${prefix}_power_dc1
    name: "${prefix} Power DC1"
    address: 0x414
    register_type: read
    value_type: U_WORD
    unit_of_measurement: W
    device_class: power
    state_class: measurement
    accuracy_decimals: 0
  - platform: modbus_controller
    modbus_controller_id: solax
    id: ${prefix}_power_dc2
    name: "${prefix} Power DC2"
    address: 0x415
    register_type: read
    value_type: U_WORD
    unit_of_measurement: W
    device_class: power
    state_class: measurement
    accuracy_decimals: 0
    on_value:
      then:
        component.update: ${prefix}_total_dc_power
  - platform: template
    id: ${prefix}_total_dc_power
    name: "${prefix} Total DC Power"
    lambda: |-
      return (id(${prefix}_power_dc1).state + id(${prefix}_power_dc2).state);
    update_interval: never
    unit_of_measurement: W
    device_class: power
    state_class: measurement
    accuracy_decimals: 0
  - platform: modbus_controller
    modbus_controller_id: solax
    name: "${prefix} Production Total"
    address: 0x423
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 1
    unit_of_measurement: kWh
    device_class: energy
    state_class: total_increasing
    filters:
      - multiply: 0.1

Thanks for your work.
You Could also add your Registers into my Registers.h JSON and it should work Fine :slight_smile: asap

just a short update.
from now GROWATT inverters are supported.
Basically, all inverters with mobus-RTU, RS-485 are supported.
Documentation is here:

OpenWB Wallboxes are directly supported

Its also possible to write registers, for example battery SOC

first of all thanx to @tobiasfaust - great work. now mx solax x3 G4 inverters sends all his “secret infomation” to my mqtt server.

homeassistant/SolaxX3/state Online
...

but how can i integrate the inverter into HASS? When i open my MQTT device in home assistant the inverter is not displayed.

i hope someone can help me here, give me a tip.

sorry, i cannot support you regarding integration in HA. My ModbusMqttGateway pushes all values to a standard MQTT Server. Mqtt is a standard protocoll, and if HA supports mqtt, its possible to integrate it.

My ModbusMqttGateway supports many solarInverter types.