Solax X1 Hybrid G4 (local & cloud API)

So either you have not used the correct sensors in the chart, the sensor are not configured correctly, or you solax is returning data in different fields.
You’ll need to trace this back, looking at the sensors values in developer / states.

I had issues connecting to local also These are all the steps I took:

Had to find the dongle local IP address. Mine is 192.168.0.1xx Found it in the router attached devices on and showed as “espressif”
I did a IP reservation in my router settings for the inverter to ensure it always has the same IP address.

The password for the local query in the secrets.yaml will be the dongle serial the one below the QR code on the dongle.

Finally I substituted the serial number from the dongle above in all these areas in the config file

Hope this helps. Took me a while to get right

1 Like

Hi, I’ve finally figure it out, now the local values are working fine.

In the local API output of my Solax invertor the serial number entity “sn” is capitalized as “SN”. I didn’t realized that this make a difference in the parsing of the JSON. After changing the script it worked!

Now I can begin mapping the correct values. A mayor step forward!

2 Likes

Hi,

I have been following a few guides with this API for solax etc. Can anyone tell me where I could be going wrong. It is reading data through the entities, but im not getting anything on the Energy dashboard.

Thankyou so much in advance.



sensor:
- platform: rest
  scan_interval: 60
  resource: https://www.solaxcloud.com/proxyApp/proxy/api/getRealtimeInfo.do?tokenId=XXXXX&sn=XXXXX
  name: "Solax 1"
  json_attributes_path: "$.result"
  json_attributes:
    - yieldtoday
    - yieldtotal
    - powerdc1
    - powerdc2
    - uploadTime
    - inverterStatus
    - acpower
    - feedinpower
    - feedinenergy
    - soc
    - consumeenergy
  value_template: "1" # dummy value; not used; avoids error
- platform: template
  sensors:
    solax_1_today:
      friendly_name: "Solax 1 today"
      value_template: "{{ state_attr('sensor.solax_1', 'yieldtoday') }}"
      unit_of_measurement: "kWh"
    solax_1_total:
      friendly_name: "Solax 1 total"
      value_template: "{{ state_attr('sensor.solax_1', 'yieldtotal') }}"
      unit_of_measurement: "kWh"
    solax_1_now:
      friendly_name: "Solax 1 now"
      value_template: "{{ state_attr('sensor.solax_1', 'acpower') }}"
      unit_of_measurement: "W"
    solax_1_pv1:
      friendly_name: "Solax 1 PV Power1"
      value_template: "{{ state_attr('sensor.solax_1', 'powerdc1') }}"
    solax_1_pv2:
      friendly_name: "Solax 1 PV Power2"
      value_template: "{{ state_attr('sensor.solax_1', 'powerdc2') }}"
      unit_of_measurement: "W"
      icon_template: mdi:solar-panel
    solax_1_pin:
      friendly_name: "Solax 1 FeedIn Power"
      value_template: "{{ state_attr('sensor.solax_1', 'feedinpower') }}"
      unit_of_measurement: "W"
    solax_1_ein:
      friendly_name: "Solax 1 FeedIn Energy"
      value_template: "{{ state_attr('sensor.solax_1', 'feedinenergy') }}"
      unit_of_measurement: "kWh"
    solax_1_econ:
      friendly_name: "Solax 1 Consume Energy"
      value_template: "{{ state_attr('sensor.solax_1', 'consumeenergy') }}"
      unit_of_measurement: "kWh"
    solax_1_upload_time:
      friendly_name: "Solax 1 upload time"
      value_template: "{{ state_attr('sensor.solax_1', 'uploadTime') }}"
      icon_template: mdi:alarm-check
    solax_1_status:
      friendly_name: "Solax 1 status"
      value_template: >
        {% if state_attr('sensor.solax_1', 'inverterStatus') == '100' %}Wait
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '101' %}Check
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '102' %}Normal
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '103' %}Fault
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '104' %}Permanent Fault
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '105' %}Update
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '106' %}EPS Check
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '107' %}EPS
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '108' %}Self-test
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '109' %}Idle
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '110' %}Standby
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '111' %}Pv Wake Up Bat
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '112' %}Gen Check
        {% elif state_attr('sensor.solax_1', 'inverterStatus') == '113' %}Gen Run
        {% else %}I dont know{% endif %}
    solax_now:
      friendly_name: "Inverter Power"
      unit_of_measurement: "W"
      value_template: "{{ (states('sensor.solax_1_now') | float) }}"
      icon_template: mdi:lightning-bolt-circle
    solax_today:
      friendly_name: "PV today"
      unit_of_measurement: "kWh"
      value_template: "{{ (states('sensor.solax_1_today') | float) }}"
    solax_total:
      friendly_name: "PV total"
      unit_of_measurement: "kWh"
      value_template: "{{ (states('sensor.solax_1_total') | float) }}"
    solax_pv_power1:
      friendly_name: "PV Power1"
      unit_of_measurement: "W"
      value_template: "{{ (states('sensor.solax_1_pv1') | float) }}"
      icon_template: mdi:solar-power-variant-outline
    solax_pv_power2:
      friendly_name: "PV Power2"
      unit_of_measurement: "W"
      value_template: "{{ (states('sensor.solax_1_pv2') | float) }}"
      icon_template: mdi:solar-power-variant-outline
    solax_pv_power_total:
      friendly_name: "PV Power Total"
      unit_of_measurement: "W"
      value_template: "{{ (states('sensor.solax_1_pv2') | float) + (states('sensor.solax_1_pv1') | float) }}"
      icon_template: mdi:solar-power-variant
    solax_house_cons:
      friendly_name: "House Power"
      unit_of_measurement: "W"
      value_template: "{{ (states('sensor.solax_1_now') | float) - (states('sensor.solax_1_pin') | float) }}"
      icon_template: mdi:home-lightning-bolt-outline
    solax_feedin_power:
      friendly_name: "Grid Power"
      unit_of_measurement: "W"
      icon_template: mdi:transmission-tower
      value_template: "{{ (states('sensor.solax_1_pin') | float) }}"
    solax_feedin_energy:
      friendly_name: "FeedIn Energy"
      unit_of_measurement: "kWh"
      value_template: "{{ (states('sensor.solax_1_ein') | float) }}"
    solax_consume_energy:
      friendly_name: "Consume Energy"
      unit_of_measurement: "kWh"
      value_template: "{{ (states('sensor.solax_1_econ') | float) }}"
    solax_consume_power:
      friendly_name: "Consume Power"
      unit_of_measurement: "W"
      value_template: "{{ (states('sensor.solax_1_now') | float) - (states('sensor.solax_1_pin') | float) }}"
      
- platform: integration
  source: sensor.solax_house_cons
  name: selfiehome_energy_spent
  unit_prefix: k
  round: 2
template:
  - sensor:
    - name: test_energy
      state: "{{ states('sensor.solax_total') }}" 
      unit_of_measurement: 'kWh'
      state_class: measurement
      device_class: energy
      attributes:         
          last_reset: '1970-01-01T00:00:00+00:00'

Hi @ColinRobbins many thanks again for your reply. To help a newbie simplify this a little could you please list the correct configuration required in the powerflow chart settings then once I have this correct I can investigate further if required. I assume my mistake is within the powerflow chart config as all sensors seem to be showing correct data individually. What is the battery adjusted sensor for though?

There is a full worked example in the post: Solax X1 Hybrid G4 Worked Example.
You just need to substitute the cloud sensors for the local sensors set up in this thread.

Any updates on talking to the LAN dongle?
I am also currently installing the Solax Inverter and I have a LAN dongle attached.
My first intention was to use ModBus over the COM-Port but a local REST call to the IP of the inverter would be much easier.
THX, Georg!

@74Quickie74 thank you for pointing it out - I’ve updated the above config and the git repo with a more generic approach (checking for length) rather than a specific value. Hope this helps.

@Walkramis you are a star! I’ve adapted your approach slightly - that is without the inversion on setting the value as that didn’t seem to work for me as you described. It works when multiplying the minutes (same as on read). Before you worked it out, I had it rely on the time setting in the second period and was enabling/disabling the second charge period. Setting the actual time as much better so thanks a lot for this. Here are my automations (feedback welcome!):

# Always reset to the same state - i.e. no off-peak forced charging overnight
- id: "1143938438939"
  alias: Battery - Disable forced charge
  description: "Allows for discharge if too much energy stored from previous day (default state)"
  trigger:
  - platform: time
    at: "23:40:00"  
  - platform: time
    at: "23:50:00"
  action:
  - repeat:
      sequence:
      - service: rest_command.solax_local_set_forced_charge_start
        data:
          value: >
            {{ 4 + 25 * 256 }}
      - delay:
          hours: 0
          minutes: 0
          seconds: 15
          milliseconds: 0
      - service: homeassistant.update_entity
        entity_id: sensor.solax_rest_local_settings

      until:
      - condition: template
        # Try up to 3 times if the updated setting doen't reflect the target
        value_template: >-
            {{ states('sensor.solax_local_battery_setting_start_charge') == '04:25' or repeat.index == 3 }}
  mode: single

# Detect if battery needs topping up within the off-peak tariff or if discharge should stop and the remainder power be left for peak usage 
# (+4 is how much the inverter overshoots the target charge, +4 is buffer in case of fast discharge)
- id: "1029376657476"
  alias: Battery - Enable forced charge
  description: "Stops allowed discharge and allows for charging to target"
  trigger:
  - platform: time_pattern
    minutes: "/1"
  condition: 
  - condition: time
    after: "00:25:00"
    before: "04:20:00"
  - condition: template
    value_template: >-
      {{ states('sensor.solax_local_battery_soc')|int <= states('sensor.solax_local_battery_charge_from_grid_to')|int + 8 }}
  action:
  - repeat:
      sequence:
      - service: rest_command.solax_local_set_forced_charge_start
        data:
          value: >
            {{ 0 + 35 * 256 }}            
      - delay:
          hours: 0
          minutes: 0
          seconds: 15
          milliseconds: 0
      - service: homeassistant.update_entity
        entity_id: sensor.solax_rest_local_settings

      until:
      - condition: template
        # Try up to 3 times if the updated setting doen't reflect the target
        value_template: >-
            {{ states('sensor.solax_local_battery_setting_start_charge') == '00:35' or repeat.index == 3 }}
  mode: single

@ColinRobbins @kamilb many thanks for your reply however as a newbie I think that’s where my problem is. The local sensors have different names in the local sensor config and I have used what I thought to be correct but some of these use pos and negative for production and consumption where as the cloud sensors were more obvious for me. Would it be possible to just have a snapshot of your powerflow chart local config so I can match mine to yours and then all should be OK. Apologies for something that probably sounds so simple to others but I’m only just learning HA. Many thanks in advance.

Just got this working, easily moving over from the cloud. Will need to mess with some settings to get them to show in the HA default energy page , but thanks so much for your great work on this! Any future plans to package it in HACS?

I would like to share my experience with this local Solax solution. I think it is great, and offers much more than the cloud readout. First of all, the cloud API is not very reliable in my experience. I had holes in my data and dashboards due to unavailability of the Cloud API. Local API is running smooth. I did however turned down the sync a notch to 10 seconds interval, since I received some Home Assistant logs about synch issues.

I would like to say that it first was a struggle for me to get it running. The scripts are a great resource, but if you don’t understand the working of it, it is difficult to troubleshoot anything. My scripting skills are not great, nor my Home Assistant YAML language in general. Thats why I would like to add some hard lessons learned here in this post.

  1. For sake of organising scripts I have the ‘-template’ part in the configurations-script in a different file (templates.yaml). This makes troubleshooting a bit easier since It helps keep the configuration clean. Use ‘template: !include templates.yaml’ in your configuration.yaml file to get it running.
  2. Every Solax system seems to get other output via the local API. It helps to check if all variables that the ‘sensor.yaml’ script expect is available. Make shure the capitalisation is in order, it took me weeks to figure out what was wrong and it turned out that ‘sn’ was ‘SN’ in my Solax API output.
  3. Use the CMD command AND the Cloud API URL to get data from (nearly) the same moment to get an idea of the mapping of your local dataset. It helped me alot. The phone App of Solax didn’t work localy so I had nothing else to compare. As a bonus tip: the first actual data line is numbered 0 (zero), the second line is 1 (one) and so on. So if you identify your (for example) Daily Yield at row 6, you have to point to value 5 in the script.
  4. Use a tool for formatting and be able to read easier the API output. I have used Best JSON Formatter and JSON Validator: Online JSON Formatter a lot.
  5. Take a good look at the Home Assistant Error Logs. However they can be very cryptic, it can identify a direction for solving problems you endure. I had some issues with rounding numbers of Daily and Total Yields (single digit, no floating) for example. Changing the script was a menace but the logs helped a bit.
  6. Once every runs smootly, you can add more sensors yourself if you have more data in your local API output. Add one sensor in a time to make troubleshooting a bit easier.
  7. Remember: it is a journey, not a destination. You WILL have to do some customisation on the sourcescript. However, the source script is a very good base to start from.

As last I want to share a dashboard I’ve created in adition to the Energy Dashboard. It uses the same colours to make a easy distinction of the Energy values (changes once an hour) with near-realtime API data. I’ve used the ‘Energy Overview Card’ available via HACS.

1 Like

Hey, thanks for the great integration. I was wondering whether people are seeing the wrong data in ‘Solax Local Battery Remain Energy’? I have two 5.8kWh batteries but when at 100% it only shows 6.02kWh remaining from the battery. I’ve verified that both batteries are indeed working, and SoC seems to be accurate too comparing to the SolaX app.

@nikotime, you need to change 6.2 in the above template to your total capacity in order to get the estimate reflecting your setup.

2 Likes

Doh that makes perfect sense. Thanks!

After tearing my hair out trying to get other X1 integrations working I am somewhat socked that this just worked!!
Now I need to figure out how to get those fancy diagrams
thank you

@ColinRobbins @kamilb
Thank you after further playing around and other research I finally have the power flow chart displaying correctly. 1 item I had missed was to invert 2 of the sensors.
My last question (for now) is there a way to get the inverter status from the local feed?

Dear All,

Just realized the Solax Integration offered by HA works very well with my X1-Hybrid-G4 unit. Almost every single entity can be read and controlled via this integration.Easy to configure as well.

Hi,

What did you enter to configure it please?

2 Likes

Wow … answering my own question. That was easy! Thanks so much :slight_smile:

1 Like