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

Have you double checked your IP address for the inverter? It’s quite hard to spot in your list of devices on your router/firewall as it’s not an obvious name.

Might be easier to manually set the IP address?

@wills106 Yes. I managed to find the router’s IP address. The default is 192.169.1.8. I also identified that port 502 is open. However, I was unable to extract the information and communicate with the inverter through the home assistant. I don’t know if it will have to do with the fact that I already had pocket wifi …

Hi,

I have both lan and pocket wifi installed in my inverter but it works anyway. Are you sure you are using the IP-address for the Lan connection to the inverter? Not the wifi-dongle or the routers IP-address

Hi @fandersson

I also have both lan and pocket wifi installed in my inverter. I am using the IP- adress of LAN connection to the inverter.

You can see in the image attached the IP and the port.

Can you show me your setings in 5.8.8.8 and Inverter?

Ok, strange.

I havent changed anything in the inverter. Just logged in to connect to wifi with the dongle. I also changed scan_interval to 7 sec since it was a bit heavy to read all values every second. Other than that no changes. Havent opened any ports in the Asus router either.

I have batrium connected to my Victron

has anyone got the batrium working in HASS yet

I have a few more interesting registers now

sensor:
- platform: modbus
  scan_interval: 2 # might need to set it higher
  registers:
  # Holding Registers
    - name: SolaX Serial Number
      hub: SolaX
      register: 0
      count: 7
      data_type: string
    - name: SolaX Factory Name
      hub: SolaX
      register: 7
      count: 7
      data_type: string
# When you put your Inverter into say ForceTime, you get no feedback. This is the feedback!
    - name: SolaX Charger Use Mode
      hub: SolaX
      register: 139
# Want to know what you have actualy set you minimum battery level to?
    - name: SolaX Battery Min
      hub: SolaX
      unit_of_measurement: "%"
      register: 140
# 0 = Lead Acid, 1 = Lithium
    - name: SolaX Battery Type
      hub: SolaX
      register: 141

More run modes documented as well as the corresponding Charger Use Mode

- 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', '4') %}
          Pemanent Fault Mode
        {% elif is_state('sensor.solax_run_mode', '5') %}
          Update Mode
        {% elif is_state('sensor.solax_run_mode', '6') %}
          EPS Check Mode
        {% elif is_state('sensor.solax_run_mode', '7') %}
          EPS Mode
        {% elif is_state('sensor.solax_run_mode', '8') %}
          Self Test
        {% elif is_state('sensor.solax_run_mode', '9') %}
          Idle Mode
        {% else %}
          Unknown
        {% endif %}
    solax_charger_use_mode_template:
      friendly_name: "SolaX Charger Use Mode"
      value_template: >-
        {% if is_state('sensor.solax_charger_use_mode', '0') %}
          Self Use Mode
        {% elif is_state('sensor.solax_charger_use_mode', '1') %}
          Force Time Use
        {% elif is_state('sensor.solax_charger_use_mode', '2') %}
          Back Up Mode
        {% elif is_state('sensor.solax_charger_use_mode', '3') %}
          Feedin Priority
        {% else %}
          Unknown
        {% endif %}

I am trying to improve the method used to communicate to the Inverter, so I wont add these onto GitHub just yet.

1 Like

Nice! I will try these later today

I tried it and it works good!

Just a thought, is it possible to divide the “platform -sensors” into different “groups” so that you can have different scan intervals? Things like battery typ, serial nr, states etc would be enough to read much less than current production. Or wont the inverter like to answer two calls?

I’m trying to read multiple registers at once and then split them into separate sensors.
That way there is less load on the ModBus bus as you can read them in a single transaction
read register 0 - 10, spit out the individual numbers
instead of read register 0, then read register 1, then read register 2 etc

But I am failing at getting my head around it at the min:

2 Likes

Thanks @wills106 for your hard work on this, it’s really useful. For the past year or so I’ve been scraping data from the web server available over the pocket wifi, but really wanted something a little more robust that didn’t tie up a Pi sitting attached to the Solax access point. So your work here really helped move me forward. I’m especially excited to get stuck in to some automation around charging.

I’ve got a X1-RetroFit-3.7 battery inverter in addition to a X1-Boost-3.6 for the solar. Right now I’m focused on the battery system. The X1ac file you produced works well for it, modified to use the LAN rather than RS485 connection.

I have discovered a couple of additional registers I’ve confirmed on my system:

    - name: SolaX Import Today
      hub: SolaX
      unit_of_measurement: kWh
      register: 154
      register_type: input
      scale: 0.01
      precision: 2
    - name: SolaX Charged Today
      hub: SolaX
      unit_of_measurement: kWh
      register: 145
      register_type: input
      scale: 0.1
      precision: 1

These reflect how much energy has gone into the battery today, and how much energy has been imported from the grid (measured by the external meter attached to the inverted in my case). I suspect daily grid export should be available too, but there’s not been enough sun today to have a measurable value to check against!

I know from the web server data (and the on-device screen) there are a bunch of cumulative counters too, like lifetime import/export for the inverter and meter. I’ve not pinned these down yet. I suspect they overflow 16 bits, so may well be spread across registers. I intend to spend some more time on that soon.

One other thing I found with my inverter was I need to authenticate before I can write to the registers to change anything. The authentication seems to last some unspecified amount of time. I discovered this because I authenticated first in the SolaX app and magically the controls started working for a short while.

You can see the extra step here, though I should replace the PIN with a secret of course…

  - alias: Solax ForceTime
    trigger:
      platform: state
      entity_id: input_boolean.solax_forcetime
      to: 'on'
    action:
    - service: modbus.write_register # authenticate
      data_template:
        hub: SolaX
        unit: '1'
        address: '0'
        value: '2014'
    - delay: '00:00:01'
    - service: modbus.write_register # Force Time Mode
      data_template:
        hub: SolaX
        unit: '1'
        address: '31'
        value: '1'
    - delay: '00:00:01'
    - service: modbus.write_register # 2nd Force Time Mode incase Inverter missed first
      data_template:
        hub: SolaX
        unit: '1'
        address: '31'
        value: '1'

It’s worked every time since.

Glad you have found it useful.
I have access to the full register list, I haven’t added anymore yet as I am trying to get my head around reading multiple registers in one go.

You shouldn’t need to “authenticate” the inverter. (Password input was only needed on really old inverters)
There can be a delay in force-time working during the night when there is no solar activity, so it may look like it’s not doing anything at first.

If you read Holding register 139, it should confirm it’s in force-time mode before the battery starts to take charge.

I wouldn’t worry about making 2014 a secret, it’s the default along with the higher level 6868

Now that reading multiple registers has been fixed in an upcoming PR

I will restart on moving this over to reading multiple registers in a single transaction.

Instead of reading
register: 0
and then
register: 1
and then
register: 2
etc you can replace it with:

    - name: SolaX Group Test
      hub: SolaX
      register: 0
      register_type: input
      count: 10
      data_type: custom
      structure: ">10h"

Which would return:
2423,15,294,1246,1207,0,1,5007,34,2
This can then be split into separate sensors through templating.

The benefit of this is that it will reduce the load on the Inverter ModBus bus, which will allow for a quicker response on register updates and will hopefully prevent / reduce missed writes to the inverter.

Ie:

  - alias: Solax ForceTime
    trigger:
      platform: state
      entity_id: input_boolean.solax_forcetime
      to: 'on'
    action:
    - service: modbus.write_register # Force Time Mode
      data_template:
        hub: SolaX
        unit: '255'
        address: '31'
        value: '1'
    - delay: '00:00:01'
    - service: modbus.write_register # 2nd Force Time Mode incase Inverter missed first
      data_template:
        hub: SolaX
        unit: '255'
        address: '31'
        value: '1'

Which can be replaced with a single write_register:

  - alias: Solax ForceTime
    trigger:
      platform: state
      entity_id: input_boolean.solax_forcetime
      to: 'on'
    action:
    - service: modbus.write_register # Force Time Mode
      data_template:
        hub: SolaX
        unit: '255'
        address: '31'
        value: '1'
2 Likes

Hi guys,

I have problems to wake my inverter from idle mode, what is the register to write? and what value?
My inverter is x1_hybrid with a triple power battery

thanks

If you read Holding register 139, it should confirm if it’s in force-time mode before the battery starts to take charge.

A few posts above give the meaning’s to the different values.

If you want to charge the battery during the night after the sun has gone to bed, the inverter needs to go through a check stage. So the inverter can appear like it’s doing nothing! It can take a min or two to respond and appear like it’s doing anything.

Also try changing your scan_interval: to a higher number, as the current method can flood the ModBus bus. Hence me wanting to read multiple registers at once!

I have observed that the only way to wake up is swtching on the “cluster control” in the app. what is the registry to activate the remote control?

I have increase the scan interval to 20, is it enough?

Should be more than enough, mine runs fine at 2 I know some have had to increase theirs to 7 / 8 to work reliably.

Do you have more than one inverter?

I would try reading Holding register 139 when you do a force charge, see if the value changes correctly and then give it enough time to react / complete checks.

Edit:

I can display some of the check sequence / times as a sensor by the looks of it. Will have a proper look at some point.

Thanks wills106 for your fast response.

I only have one inverter, in the “super” menu in the app, appears “cluster control”. I have only one inverter. I supose that means “remote control”. When I active that option, the system wait that I set the power output.

I have a sensor with the 139 register and I can check when I change the use_mode. The problem come because in idle mode the inverter doesn’t react after a mode changed throuth the 31 register.

I assume that I have to activate the “cluster control” to wake up the system, but I don’t know what register is.

I have never had to “activate” any modes.
I would just give the Inverter time to see what happens.
Like I say I think I can provide a “check” or “countdown” sensor to see if the Inverter is waking up so to speak.