Universal Solar Inverter over Modbus RS485 / TCP custom_component (Growatt, Sofar, SolaX, Solis)

@Tim1739: I have managed to get the SiteID, TokenID etc by using the android app: Package Capture. Are you only using the REST platform and adding them as sensors? And can you show us what your config looks like in the REST platform? Would help me a lot as I also cannot access the LAN module directly by IP.

@J0101
I’m currently only using the REST platform. This is an example of one of my configs, hope it helps!

This helps a lot, thank you! The code works, and i will check if all works tomorrow when the site is on-line (and the sun is shingin). I have one question, the “today=” in the resource API is the date of today. Does this mean that the code would not work tomorrow? Maybe a silly question, but hopefully you can answer it.

I have finally got full battery control working!

I can now prevent and alter the current that the battery charges and discharges at.
I can also alter the min discharge percentage. (Please do not alter the min value on the slider to below 10!)

I wanted to be able to charge my car from Solar without draining my house battery as the inverter would push that electricity out as a priority. Now prior to charging I can alter the discharge Amps slider to zero and charge my car preserving the electric in the house battery for later use.

Another option is to put the SolaX inverter into Backup Mode. This mode still diverts Solar into your House battery as a Priority and any excess will go into your car as well as pull from the grid.

There is a slight limitation with Grid charging and that is I haven’t been able to toggle Grid Charge on and off within Force Time Mode.
But all you need to do is change your mode in the Web Portal to “Force Time Use” and save.

Then change “Charge from Grid” to “All are allowed” and save.

Then you can change your run mode beck to SelfUse and save.
Now every time you toggle “SolaX Force Time” in Home Assistant it will grid charge your battery, as the setting to allow Grid Charge is stored in your Inverter.

If anyone has a 3 Phase Inverter ie X3 could you please let me know if the Phase R S T values look correct or if I need to change the scales.

Usual disclaimer use at your own risk.
I do not know if this will work on other SolaX inverters as the older Models such as SK-SU5000 use a different method to control the battery.

2 Likes

Hi guys,

So I have core running on a raspbian buster pi 4. I’m quite certain I have all the software in the right places but my solax x1 boost 3.3td doesn’t seem to respond to the messages it is sent. It’s connected on the rs485 port through a usb rs485 converter. I can see the tx led flashing every 10 seconds(like i configured) but nothing coming back. Is there some configuration I’m overlooking? I received the communication protocol “Solax Power Single Phase External
Communication Protocol V1.2” from solax and edited the registers accordingly.

Any help would be greatly apreciated. And if anyone is interested in the communication document I can share it.

Are you able to share your yaml config?
Have you copied my config I have on the Github link and change the mode to RS485?

Could you please PM me that document. Then I can see what I can add.

Yes, I definitely can share my configuration. solax.yaml:

# https://github.com/wills106/homeassistant-config/blob/8afee639874723d035008f2ffc12d0574f8cd322/packages/solax.yaml
# Using https://github.com/InfernoEmbedded/PowerScraper as a basis for the Modbus registers used on Solax Inverters.
# I created this as I am using the Ethernet port on the Inverter for Modnbus over TCP as the web API is unavailable.
# But the Inverter can communicate to the cloud ok somehow? I do not have a Pocket WiFi module.
# Only tested with ModBus over TCP, no reason why USB - RS485 shouldn't work

modbus:
  name: SolaX
#  type: tcp # Comment out for RS485
#  host: 5.8.8.8 # Comment out for RS485
#  port: 502 # Comment out for RS485

# Uncomment for USB - RS485 dongle
  type: serial
  method: rtu
  port: /dev/ttyUSB1
  baudrate: 9600
  stopbits: 1
  bytesize: 8
  parity: N

sensor:
- platform: modbus
  scan_interval: 10
  registers:
    - name: SolaX Inverter Temperature
      hub: SolaX
      unit_of_measurement: °C
      register: 0
      register_type: input
      scale: 0.1
      precision: 1
    - name: SolaX Inverter Yield Today
      hub: SolaX
      unit_of_measurement: kWh
      register: 1
      register_type: input
      scale: 0.1
      precision: 1
    - name: Solax PV1 voltage
      hub: SolaX
      unit_of_measurement: V
      register: 2
      register_type: input
      scale: 0.1
      precision: 1
    - name: SolaX PV2 Voltage
      hub: SolaX
      unit_of_measurement: V
      register: 3
      register_type: input
      scale: 0.1
      precision: 1
    - name: SolaX PV1 Current
      hub: SolaX
      unit_of_measurement: A
      register: 4
      register_type: input
      scale: 0.1
      precision: 1
    - name: SolaX PV2 Current
      hub: SolaX
      unit_of_measurement: A
      register: 5
      register_type: input
      scale: 0.1
      precision: 1
    - name: SolaX Current output
      hub: SolaX
      unit_of_measurement: A
      register: 6
      register_type: input
      scale: 0.1
      precision: 1
    - name: SolaX Grid voltage
      hub: SolaX
      unit_of_measurement: V
      register: 7
      register_type: input
      scale: 0.1
      precision: 1
    - name: SolaX Grid Frequency
      hub: SolaX
      unit_of_measurement: Hz
      register: 8
      register_type: input
      scale: 0.01
      precision: 0.1
    - name: SolaX Power Output
      hub: SolaX
      unit_of_measurement: W
      register: 9
      register_type: input
      scale: 0.1
      precision: 1
# Register nummer 10 overgeslagen. Not in use
    - name: Solax Yield Total
      hub: SolaX
      unit_of_measurement: kWh
      register: 11
      register_type: input
      scale: 0.1
      precision: 1
    - name: Solax Runtime Total
      hub: SolaX
      unit_of_measurement: h
      register: 12
      register_type: input
      scale: 1
      precision: 1
    - name: Solax Inverter Mode
      hub: SolaX
      register: 13
      register_type: input
    - name: Solax Grid voltage fault value
      hub: SolaX
      unit_of_measurement: V
      register: 14
      register_type: input
      scale: 0.1
      precision: 1
    - name: Solax Grid Frequency Fault Value
      hub: SolaX
      unit_of_measurement: Hz
      register: 15
      register_type: input
      scale: 0.01
      precision: 0.1
    - name: Solax DC injection fault value
      hub: SolaX
      unit_of_measurement: mA 
      register: 16
      register_type: input
      scale: 1
      precision: 1
    - name: Solax Temperature fault value
      hub: SolaX
      register: 17
      register_type: input
    - name: Solax Pv1 Voltage fault value
      hub: SolaX
      unit_of_measurement: V
      register: 18
      register_type: input
      scale: 0.1
      precision: 1
    - name: Solax Pv2 Voltage fault value
      hub: SolaX
      unit_of_measurement: V
      register: 19
      register_type: input
      scale: 0.1
      precision: 1
    - name: Solax GFC fault value
      hub: SolaX
      unit_of_measurement: mA
      register: 20
      register_type: input
      scale: 0.1
      precision: 1
    - name: Solax Error Message
      hub: SolaX
      register: 21
      register_type: input

# Compine PV1 and PV2 power
- platform: template
  sensors:
    solax_pv_total_power:
      friendly_name: "Solax PV Total Power"
      value_template: "{{ states('sensor.solax_pv1_power') | int + states('sensor.solax_pv2_power') | int }}"
      unit_of_measurement: 'W'

- platform: template
  sensors:
    solax_run_mode_template:
      friendly_name: "SolaX Run Mode"
      value_template: >-
        {% if is_state('sensor.solax_run_mode', '0') %}
          Waiting
        {% elif is_state('sensor.solax_run_mode', '1') %}
          Checking
        {% elif is_state('sensor.solax_run_mode', '2') %}
          Normal Mode
        {% elif is_state('sensor.solax_run_mode', '3') %}
          Off Mode
        {% elif is_state('sensor.solax_run_mode', '7') %}
          EPS Mode
        {% elif is_state('sensor.solax_run_mode', '9') %}
          Idle Mode
        {% else %}
          Unknown
        {% endif %}

that is what I have in the solax.yaml in my packages folder.

and my configuration:


# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Uncomment this if you are using SSL/TLS, running in Docker container, etc.
# http:
#   base_url: example.duckdns.org:8123

homeassistant:
  packages: !include_dir_named packages
# Text to speech
tts:
  - platform: google_translate
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml 
#slimme meter
#sensor:
#  - platform: dsmr
#    port: /dev/ttyUSB0
#    dsmr_version: 4

#slimme meter via DSMR reader
sensor:
  - platform: dsmr_reader
  

mqtt:
  broker: 192.168.1.124

I will PM the pdf

You might need to add the slave unit number. On ModBus over TCP you can read values without the unit number, but to be able to write to an address you must have a unit number.
You might need to try different unit numbers starting at 0

sensor:
- platform: modbus
  scan_interval: 10
  registers:
    - name: SolaX Inverter Temperature
      hub: SolaX
      unit: '1'
      unit_of_measurement: °C
      register: '0'
      register_type: input
      scale: 0.1
      precision: 1

ok I’ll try. any trick to quickly check 254 unit numbers without having to manually write them in a config file? :unamused:

and shouldn’t the slave adress be specified on the sensor level? or won’t that work?

According to https://www.home-assistant.io/integrations/sensor.modbus/

Each individual sensor needs a unit number.

That was quick. :upside_down_face: thanks.

Any joy?

Just so you know on the newer inverters register 0 is the voltage, incase you get some strange value back.

right now i’m still not getting anything back. but i’ve only tried until slave nr 21. So it will take a while.

I’m going to email solax support again. See if they might at least give me some pointers.

I would have thought it would be a low unit number like 0 - 5 etc

I take it you have tried the basics such as confirming your dongle is actually ttyUSB1 and that you have A going to A and B going to B on the wiring? It’s not like an RS232 null modem where TX goes to RX etc.

Let us know how you get on.

Hi
Interested in your integration with the Solax Inverter, especially the battery control side of things. I am using Node-Red and have managed to easily extract Modbus ‘input register’ data to create a real time dashboard, based on your code to identify which register contains what.
However performing a Modbus writte to the registers listed in your ‘yaml’ file does not work and if I read those registers they do not reflect the configured settings.
When you setup your system did the battery registers match e.g. if the Battery Min Discharge % was configured for 20% did it the contents of match register address 32?

Thanks

Have you tried using my exact setup and not Node-Red to make sure it works ok?

What model Inverter do you have?

Also you are correct when you read register 32 it doesn’t match up to the set value!

Thanks
That makes me more confident writing to reg 32. If I still have no luck I will install HA as the next step.

I have just got this to read data from my Solax X1-AC inverter. I had to increase the baud rate to 115200 though:

  type: serial
  method: rtu
  port: /dev/ttyUSB0
  baudrate: 115200
  stopbits: 1
  bytesize: 8
  parity: N
1 Like

I just copied the generic configuration from the Home-Assistant ModBus docs.
Glad it has proved useful in your setup.