Solax X1 Hybrid G4 (local & cloud API)

Thanks a lot @andrewcoo. This works. :slight_smile:

@kamilb Thanks for the great tutorial. :heart:

I have spotted one minor error and also have a few suggested updates.

The following line in your configuration.yaml

payload: !secret solax_local_set_battery_level_payload

Should be:

payload: !secret solax_local_set_battery_grid_charge_level_payload

Think you changed the secrets.yaml but forgot to update the configurations.yaml file.

Another change is due to an update to the powercalc. Since version 1.8.0 the YAML syntax changed slightly, see: Powercalc new YAML Structure

As a result the following line in your configuration.yaml

sensor powercalc_label: !include powercalc.yaml

Should now be:

powercalc: !include powercalc.yaml

And the powercalc.yaml should be:

sensors:
  - entity_id: sensor.solax_local_pv_output
    name: Solar Panels V2
    fixed:
      power: "{{ states('sensor.solax_local_pv_output')| int(default=0) }}"

  - entity_id: sensor.solax_cloud_solar_panel
    name: Solax Cloud Solar Panels V1
    fixed:
      power: "{{ states('sensor.solax_cloud_solar_panel')| int(default=0) }}"

  - entity_id: sensor.solax_cloud_battery_use_in
    name: Solar Cloud Battery In V1
    fixed:
      power: "{{states('sensor.solax_cloud_battery_use_in')}}"

  - entity_id: sensor.solax_cloud_battery_use_out
    name: Solar Cloud Battery Out V1
    fixed:
      power: "{{states('sensor.solax_cloud_battery_use_out')}}"

Hope this info helps others :slight_smile:

3 Likes

has this stopped working for anyone else in the last 24 hours?

Would you consider making a portal for others to use this? So we could just get a token from solax and then utilise the work you have done to run my solax system more efficiently taking into consideration the weather forecasted ?

I have exactly the same needs as you, inc the water heating and plus wanting to automate car charging also.

Hi Tom. Could you elaborate on your thinking around the portal? I don’t see yet how this could work…

can you post your configuration?

Had the same issue Manu-J had today and this fixed my issue. Thanks Dave.

Thanks for this solution! I’ve got some questions:

I dont have a Solax Triple Power device, can I skip some parts of the code?
I think that this applies only for the automation right? @kamilb

Because we share the same inverter and I’m struggling with the mapping for the local entities, would you mind sharing the local yaml’s you’re using? @Freakandel

Question for all: what did you set on scan_interval?
I’ve configured 3600 (5minutes) but if it doesn’t bother, I would change it a bit faster.

Thanks!

Just as an aside I assume many people on this thread are unaware of this project :

https://github.com/wills106/homeassistant-solax-modbus

It works perfectly and has absolutely no reliance on the cloud at all. I use it with my X1 Hybrid G4 and PocketWifi

Mine is set to pick up data every 5s but I could probably turn that down to 1s if I needed to …

Thanks for the suggestion but your solution requires a modbus adapter which I don’t have and additional configuration. This way looks easier.

I am using what came with my default installation. Nothing else. Simply the X1 Hybrid G4 and the PocketWifi v3 adapter which it also uses to communicate with the cloud.

Not sure what you mean by it needing a modbus adapter and additional configuration. It works out of the box.

Simply put the IP address of the X1 in and off it goes (obviously your X1 must be on your network)

It uses TCP or MODBUS - this is the setting screen for TCP.

image

O the page is mentioning it at the Installation section:
GitHub - wills106/homeassistant-solax-modbus: SolaX Power Modbus custom_component for Home Assistant (Supports some Ginlong Solis, Growatt, Sofar Solar, TIGO TSI & Qcells Q.Volt Hyb)

But thats good news. Will try it somewhere these days :slight_smile:

If you expand the readme it shows more info. Anyway, I know it works and gets rid of the horrible cloud reliance.

You also get a heck of a lot more control and entities by default (this is on my installation)

image

I have just setup an X1-Hybrid-G4 and it hooked up brilliantly but for some odd reason my import energy is 1000 kWh over what it should be?
image

I’ve updated the configuration files and added a few automations for Octopus Saving Sessions - described here in more details: Automated Octopus Saving Sessions with Solax X1 Hybrid G4

Anyone else lost all connectivity after the last solax update?

Hi. What update are you referring to? Inverter firmware, wifi dongle or HA integration?

Hi John, Yes ofcause I can share my config file.

Local part of my sensor.yaml

### Solax Local REST sensor ###
- platform: rest
  scan_interval: 10
  resource: !secret solax_local_ip
  payload: !secret solax_local_realtime_payload
  method: POST
  name: "solax_rest_local"
  json_attributes:
        - SN
        - ver
        - type
        - Data
        - Information
  value_template: 'OK'  # dummy value, not used; avoids the "State max length is 255 characters" error

### Solax Local REST settings ###
- platform: rest
  scan_interval: 3600
  resource: !secret solax_local_ip
  payload: !secret solax_local_settings_payload
  method: POST
  name: "solax_rest_local_settings"
  # Unfortunately settings are not returned as a JSON document but an array of numbers, so having to pick just the relevant to avoid the max 255 chars limit
  # 0 - Self Use Min SOC %
  # 1 - Self Use Charge from grid (0 for disabled, 1 for enabled)
  # 2 - Self Use Charge from grid to % 
  value_template: "{{ '[' ~ value.split(',')[28] ~ ',' ~ value.split(',')[29] ~ ',' ~ value.split(',')[30] ~ ']' }}"

This works fime for me now. It is a but customised from the original script, where I use sensor.yaml.

Please let me know if this works for you!

Thanks for the reply! I was looking for the mapping part so the seperate sensors for all attributes, can you share that part also?

# --- LOCAL --------------------------

### Local sensor readings ###
  - name: solax_local
    state: > 
          {% if state_attr('sensor.solax_rest_local', 'SN') == "SW......."  %}{{ now().strftime("%H:%M:%S") }}
          {% else %}{{ (states('sensor.solax_local')) }}{% endif %}
    attributes: 
      sn: >-
          {% if state_attr('sensor.solax_rest_local', 'SN') == "SW......." %}{{ (state_attr('sensor.solax_rest_local', 'SN')) }}
          {% else %}{{ (state_attr('sensor.solax_local', 'SN')) }}{% endif %}
      ver: >-
        {% if state_attr('sensor.solax_rest_local', 'SN') == "SW......." %}{{ (state_attr('sensor.solax_rest_local', 'ver')) }}
        {% else %}{{ (state_attr('sensor.solax_local', 'ver')) }}{% endif %}
      type: >-
        {% if state_attr('sensor.solax_rest_local', 'SN') == "SW......." %}{{ (state_attr('sensor.solax_rest_local', 'type')) }}
        {% else %}{{ (state_attr('sensor.solax_local', 'type')) }}{% endif %}
      Data: >-
        {% if state_attr('sensor.solax_rest_local', 'SN') == "SW......." %}{{ (state_attr('sensor.solax_rest_local', 'Data')) }}
        {% else %}{{ (state_attr('sensor.solax_local', 'Data')) }}{% endif %}
      Information: >-
        {% if state_attr('sensor.solax_rest_local', 'SN') == "SW......." %}{{ (state_attr('sensor.solax_rest_local', 'Information')) }}
        {% else %}{{ (state_attr('sensor.solax_local', 'Information')) }}{% endif %}

### Make the settings look like sensor data by embedding the info in the Data attribute 
  - name: solax_local_settings
    state: > 
          {{ now().strftime("%H:%M:%S") }}
    attributes: 
      Data: >-
        {{ (states('sensor.solax_rest_local_settings')) }}

#### Combined Solar PV output ####
  - name: "Solax Local PV Output"
    unique_id: solax_local_pv_output
    state: "{{ (state_attr('sensor.solax_local', 'Data')[11]) | int(default=0) }}"
    unit_of_measurement: "W"
    state_class: measurement
    device_class: "power"

#### Actual Voltage AC ####
  - name: "Solax Local Voltage AC Output"
    unique_id: solax_local_voltage_ac
    state: "{{ (state_attr('sensor.solax_local', 'Data')[5]) | int(default=0) }}"
    unit_of_measurement: "V"
    state_class: measurement
    device_class: "power"

#### Actual Voltage DC ####
  - name: "Solax Local Voltage DC Output"
    unique_id: solax_local_voltage_dc
    state: "{{ (state_attr('sensor.solax_local', 'Data')[2]) | int(default=0) }}"
    unit_of_measurement: "V"
    state_class: measurement
    device_class: "power"

#### Actual Current AC ####
  - name: "Solax Local Current AC Output"
    unique_id: solax_local_current_ac
    state: "{{ ((state_attr('sensor.solax_local', 'Data')[4]) | float - 0) }}"
    unit_of_measurement: "A"
    state_class: measurement
    device_class: "power"

#### Actual Current DC ####
  - name: "Solax Local Current DC Output"
    unique_id: solax_local_current_dc
    state: "{{ ((state_attr('sensor.solax_local', 'Data')[0]) | float - 0) }}"
    unit_of_measurement: "A"
    state_class: measurement
    device_class: "power"

#### Total Yield ####
  - name: "Solax Local PV Total Yield"
    unique_id: solax_local_pv_total_yield
    state: "{{ ((state_attr('sensor.solax_local', 'Data')[9]) | float - 0) }}"
    unit_of_measurement: "kWh"
    device_class: energy
#    state_class: total_increasing

#### Daily Yield ####
  - name: "Solax Local PV Yield Today"
    unique_id: solax_local_pv_yield_today
    state: "{{ ((state_attr('sensor.solax_local', 'Data')[8]) | float -0) }}"
    unit_of_measurement: "kWh"
    device_class: energy
#    state_class: measurement

### Inverter output (negative for charging battery) ####
  - name: "Solax Local AC Power"
    unique_id: solax_local_ac_power
    state: >
      {% if state_attr('sensor.solax_local', 'Data')[6] > 32767 %}{{ (state_attr('sensor.solax_local', 'Data')[6] - 65536) | int(default=0) }}
      {% else %}{{ state_attr('sensor.solax_local', 'Data')[6] | int(default=0) }}{% endif %}
    unit_of_measurement: "W"
    state_class: measurement
    device_class: "power"

### Grid power (positive for feed-in, negative for consumption) ###
  - name: "Solax Local Grid Power"
    unique_id: solax_local_grid_power
    state:  >
      {% if state_attr('sensor.solax_local', 'Data')[32] > 32767 %}{{ (state_attr('sensor.solax_local', 'Data')[32] - 65536) }}
      {% else %}{{ state_attr('sensor.solax_local', 'Data')[32] }}{% endif %}
    unit_of_measurement: "W"
    state_class: measurement
    device_class: "power"
1 Like