PV SolaX inverter cloud sensors via API

Good to hear that you got the sensors in HA. My yieldtoday sensor does not show that kind of behaviour. Perhaps a temp. hickup at Solax?

Can confirm that this option works!
Thanks for doing the hard work on this one.

1 Like

Hello,

IĀ“m totaly new here and IĀ“m thankful for all the clear information and coding written here.
I would like to use Home Assistant to make the best use of my SolaX solar panel system.
But I have 2 inverters, the master and the slaver. They both have their own WIFI and the data of both is merged in the cloud.
Does anyone know how this can also be done in Home Assistant?

Doublet has already written a cool and perfect coding, but can it also be used for 2 inverters that are master and slaver?

Thanks in advanced for the help.

If the data is in the cloud then the api trick must get you the data somehow.
Can you share your response to : https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=202102060300yyyyyyy&sn=SWXXXXXXX

This is the respons of the slaver inverter:

{"exception":"Query success!","result":{"inverterSN":"XXXXXXXXXXXXXX","sn":"SWXXXXXXXX","acpower":106.0,"yieldtoday":1.3,"yieldtotal":712.6,"feedinpower":0.0,"feedinenergy":0.0,"consumeenergy":0.0,"feedinpowerM2":0.0,"soc":79.0,"peps1":0.0,"peps2":0.0,"peps3":0.0,"inverterType":"5","inverterStatus":"102","uploadTime":"2021-05-05 08:49:10","batPower":214.0,"powerdc1":0.0,"powerdc2":383.0},"success":true}

and this is the respons of the master inverter:

{"exception":"Query success!","result":{"inverterSN":"XXXXXXXXXXXXXX","sn":"SWXXXXXXXX","acpower":5820.0,"yieldtoday":5.9,"yieldtotal":1302.5,"feedinpower":199.0,"feedinenergy":597.77,"consumeenergy":1014.05,"feedinpowerM2":0.0,"soc":98.0,"peps1":0.0,"peps2":0.0,"peps3":0.0,"inverterType":"5","inverterStatus":"102","uploadTime":"2021-05-05 13:06:45","batPower":-758.0,"powerdc1":0.0,"powerdc2":5221.0},"success":true}

Good, this would suggest that you can create 2 sets of sensors following my guide: one for the master, one for the slave. With HA you can then create a 3rd set of sensors showing the addition of the two converters with the total production.

Ah, oke. Thanks for the info. This afternoon we will try it. Itā€™s all new for us, so we will see.
Could you maybe write me where the sensors are created in HA, in config.yaml or somewhere else?
Sorry for asking, but its really all new for me, but I would like to learn more about it.

You can create the sensors in configuration.yaml RESTful Sensor - Home Assistant

Thanks to your help we managed it to set up the sensors.
We see now all the details from the Master inverter and separately also from the Slaver inverter.
But at the end we tried to combine these numbers so we could get a total of everything, and something we did wrong, because the Ā“total energy usedĀ“ does not work.

So affter we have put the code for the Ā“total energy usedĀ“ below the sensors Master and Slave, we get in the configuration test a fault, but we do not see yet what we did wrong.

This is the code that we used for the Ā“total energy usedĀ“ and something is not right:

############

Gesamtverbrauch aktuell

  • platform: template
    total_energy_used:
    value_template: ā€˜{{ ((state.sensor.master_solax_now | float) +
    (state.sensor.slave_solax_now | float)}}ā€™
    friendly_name: ā€˜Gesamtverbrauch aktuellā€™
    unit_of_measurement: ā€œKWā€

.
This is the message that we get in the configuration test:

Invalid config for [sensor.template]: [total_energy_used] is an invalid option for [sensor.template]. Check: sensor.template->total_energy_used. (See ?, line ?).

.
Do you have a idea what we do wrong?

Please use the correct way to post code: put your code between 3 kommaā€™s as per the forum rules:

type or paste code here

So I assume you have two sensors for current PV, two sensors for todayā€™s PV and two for Total. Now we have to add them into 3 new sensors like:


    
  - platform: template
    sensors:
      pv_now:
        friendly_name: "PV Now"
        unit_of_measurement: W
        value_template: "{{ states('sensor.solax_now')|int + states('sensor.solax_now2')| int }}"
        icon_template: mdi:power-socket-de
        device_class: power
        
  - platform: template
    sensors:
      pv_today:
        friendly_name: "PV Today"
        unit_of_measurement: "kWh"
        value_template: "{{ (states('sensor.solax_today')|int + states('sensor.solax_today2')|int) }}"
        icon_template: mdi:solar-panel        

  - platform: template
    sensors:
      pv_total:
        friendly_name: "PV Total"
        unit_of_measurement: kWh
        value_template: "{{ states('sensor.solax_total')|int + states('sensor.solax_total2')|int }}"
        icon_template: mdi:chart-line

1 Like

Sorry that I did it wrong. I hope I do it now okƩ.
This is the total code in the config.yaml:

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

# Text to speech
tts:
  - platform: google_translate

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
#########################################################
#                                                       #
#         SOLAX CLOUD.   Master                         #
#                                                       #
#########################################################
sensor:
  - platform: rest
    resource: https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ ( value_json.result.yieldtotal | round(0) ) }}'
    name: "Master Solax total"
    unit_of_measurement: "KWh"

  - platform: rest
    resource: https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ ( value_json.result.acpower | round(0) ) }}'
    name: "Master Solax now"
    unit_of_measurement: "W"

  - platform: rest
    resource: https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ ( value_json.result.powerdc2 | round(0) ) }}'
    name: "Master Leistung Panel"
    unit_of_measurement: "W"

  - platform: rest
    resource: https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ value_json.result.yieldtoday }}'
    name: "Master Solax today"
    unit_of_measurement: "KWh"
    
  - platform: rest
    resource: https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: "{{ value_json.result.uploadTime }}"
    name: "Master Solax upload time"
    
  - platform: rest
    resource: https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: >
          {% if value_json.result.inverterStatus == '100' %}Wait
          {% elif value_json.result.inverterStatus == '101' %}Check
          {% elif value_json.result.inverterStatus == '102' %}Normal
          {% elif value_json.result.inverterStatus == '103' %}Fault
          {% elif value_json.result.inverterStatus == '104' %}Permanent Fault
          {% elif value_json.result.inverterStatus == '105' %}Update
          {% elif value_json.result.inverterStatus == '106' %}EPS Check
          {% elif value_json.result.inverterStatus == '107' %}EPS
          {% elif value_json.result.inverterStatus == '108' %}Self-test
          {% elif value_json.result.inverterStatus == '109' %}Idle
          {% elif value_json.result.inverterStatus == '110' %}Standby
          {% elif value_json.result.inverterStatus == '111' %}Pv Wake Up Bat
          {% elif value_json.result.inverterStatus == '112' %}Gen Check
          {% elif value_json.result.inverterStatus == '113' %}Gen Run
          {% else %}I dont know{% endif %}
    name: "Master Solax status"

#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
#########################################################


#########################################################
#                                                       #
#         SOLAX CLOUD.   Slave		                #
#                                                       #
#########################################################

  - platform: rest
    resource: https://www.eu.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ ( value_json.result.yieldtotal | round(0) ) }}'
    name: "Slave Solax total"
    unit_of_measurement: "KWh"

  - platform: rest
    resource: https://www.eu.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ ( value_json.result.acpower | round(0) ) }}'
    name: "Slave Solax now"
    unit_of_measurement: "W"

  - platform: rest
    resource: https://www.eu.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ ( value_json.result.powerdc2 | round(0) ) }}'
    name: "Slave Leistung Panel"
    unit_of_measurement: "W"

  - platform: rest
    resource: https://www.eu.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: '{{ value_json.result.yieldtoday }}'
    name: "Slave Solax today"
    unit_of_measurement: "KWh"
    
  - platform: rest
    resource: https://www.eu.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: "{{ value_json.result.uploadTime }}"
    name: "Slave Solax upload time"
    
  - platform: rest
    resource: https://www.eu.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=APITOKEN&sn=SWXXXXXXXXXX
    value_template: >
          {% if value_json.result.inverterStatus == '100' %}Wait
          {% elif value_json.result.inverterStatus == '101' %}Check
          {% elif value_json.result.inverterStatus == '102' %}Normal
          {% elif value_json.result.inverterStatus == '103' %}Fault
          {% elif value_json.result.inverterStatus == '104' %}Permanent Fault
          {% elif value_json.result.inverterStatus == '105' %}Update
          {% elif value_json.result.inverterStatus == '106' %}EPS Check
          {% elif value_json.result.inverterStatus == '107' %}EPS
          {% elif value_json.result.inverterStatus == '108' %}Self-test
          {% elif value_json.result.inverterStatus == '109' %}Idle
          {% elif value_json.result.inverterStatus == '110' %}Standby
          {% elif value_json.result.inverterStatus == '111' %}Pv Wake Up Bat
          {% elif value_json.resreult.inverterStatus == '112' %}Gen Check
          {% elif value_json.result.inverterStatus == '113' %}Gen Run
          {% else %}I dont know{% endif %}
    name: "Slave Solax status"

#########################################################
#                                                       #
#            END OF CONFIGURATION FILE                  #
#                                                       #
#########################################################

############
# Gesamtverbrauch aktuell
###
  - platform: template
    total_energy_used:
      value_template: '{{ ((state.sensor.master_solax_now | float) + 
      (state.sensor.slave_solax_now | float)}}'
      friendly_name: 'Gesamtverbrauch aktuell'  
      unit_of_measurement: "KW"
1 Like

YES this works.
We are really grateful, thank you so much for your help.

1 Like

I added :
scan_interval: 60
to one of the api calls to see if that will scan at 1 minute intervals instead of the default 5 minutes
I will tell you if it worksā€¦

Thanks for this @Doublet !

The default scan interval for the rest sensor is 30 seconds. The update frequency is 5 minutes on Solax side, so the scan interval isnā€™t going to change things.

I have two Solax inverters (X1 and X3) and I saw in the API documentation there is a request limit of 10000/day. So I changed the sensor a bit, with the purpose of making one rest call and extracting the data I need for the sensors.

## X3 ##
- platform: rest
  resource: https://www.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=202102060300yyyyyyy&sn=SWXXXXXXX
  name: "Solax X3"
  json_attributes_path: "$.result"
  json_attributes:
    - yieldtoday
    - yieldtotal
    - acpower
    - uploadTime
    - inverterStatus
  value_template: '1'  # dummy value, not used; avoids the "State max length is 255 characters" error
- platform: template
  sensors:
    solax_x3_today:
      friendly_name: "Solax X3 today"
      value_template: "{{ state_attr('sensor.solax_x3', 'yieldtoday') }}"
      unit_of_measurement: "KWh"
    solax_x3_total:
      friendly_name: "Solax X3 total"
      value_template: "{{ state_attr('sensor.solax_x3', 'yieldtotal') }}"
      unit_of_measurement: "KWh"
    solax_x3_now:
      friendly_name: "Solax X3 now"
      value_template: "{{ state_attr('sensor.solax_x3', 'acpower') }}"
      unit_of_measurement: "W"
    solax_x3_upload_time:
      friendly_name: "Solax X3 upload time"
      value_template: "{{ state_attr('sensor.solax_x3', 'uploadTime') }}"
    solax_x3_status:
      friendly_name: "Solax X3 status"
      value_template: >
        {% if state_attr('sensor.solax_x3', 'inverterStatus') == '100' %}Wait
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '101' %}Check
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '102' %}Normal
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '103' %}Fault
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '104' %}Permanent Fault
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '105' %}Update
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '106' %}EPS Check
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '107' %}EPS
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '108' %}Self-test
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '109' %}Idle
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '110' %}Standby
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '111' %}Pv Wake Up Bat
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '112' %}Gen Check
        {% elif state_attr('sensor.solax_x3', 'inverterStatus') == '113' %}Gen Run
        {% else %}I dont know{% endif %}

## X1 ##
- platform: rest
  resource: https://www.eu.solaxcloud.com:9443/proxy/api/getRealtimeInfo.do?tokenId=20210517200601yyyyyyyyyyyy&sn=SWXXXXXXXXX
  name: "Solax X1"
  json_attributes_path: "$.result"
  json_attributes:
    - yieldtoday
    - yieldtotal
    - acpower
    - uploadTime
    - inverterStatus
  value_template: '1'  # dummy value, not used; avoids the "State max length is 255 characters" error
- platform: template
  sensors:
    solax_x1_today:
      friendly_name: "Solax X1 today"
      value_template: "{{ state_attr('sensor.solax_x1', 'yieldtoday') }}"
      unit_of_measurement: "KWh"
    solax_x1_total:
      friendly_name: "Solax X1 total"
      value_template: "{{ state_attr('sensor.solax_x1', 'yieldtotal') }}"
      unit_of_measurement: "KWh"
    solax_x1_now:
      friendly_name: "Solax X1 now"
      value_template: "{{ state_attr('sensor.solax_x1', 'acpower') }}"
      unit_of_measurement: "W"
    solax_x1_upload_time:
      friendly_name: "Solax X1 upload time"
      value_template: "{{ state_attr('sensor.solax_x1', 'uploadTime') }}"
    solax_x1_status:
      friendly_name: "Solax X1 status"
      value_template: >
        {% if state_attr('sensor.solax_x1', 'inverterStatus') == '100' %}Wait
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '101' %}Check
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '102' %}Normal
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '103' %}Fault
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '104' %}Permanent Fault
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '105' %}Update
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '106' %}EPS Check
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '107' %}EPS
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '108' %}Self-test
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '109' %}Idle
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '110' %}Standby
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '111' %}Pv Wake Up Bat
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '112' %}Gen Check
        {% elif state_attr('sensor.solax_x1', 'inverterStatus') == '113' %}Gen Run
        {% else %}I dont know{% endif %}

And sensors to sum both inverters:

- platform: template
  sensors:
    solax_today:
      friendly_name: Solax today
      unit_of_measurement: kWh
      value_template: "{{ (states('sensor.solax_x1_today') | float) + (states('sensor.solax_x3_today') | float) }}"
    solax_now:
      friendly_name: Solax now
      unit_of_measurement: W
      value_template: "{{ (states('sensor.solax_x1_now') | float) + (states('sensor.solax_x3_now') | float) }}"
    solax_total:
      friendly_name: Solax total
      unit_of_measurement: KWh
      value_template: "{{ (states('sensor.solax_x1_total') | float) + (states('sensor.solax_x3_total') | float) }}"
    
2 Likes

@Bobbika Thanks for this extensive example.
I have the same setup of inverters so I could use it with very small alterations.

With the new energy management this became even more important to me.

Sadly it seems that there is no support for template sensors according to this post by @frenck.

I will try to contact Solax again to see if i can change their mind about the local API.
With my setup (X1 and X3 both with pocket lan adapter) the workaround connecting to the SSID locally does not work, obviously.

1 Like

I have send an extensive request to Solax Benelux to request to open up the local API again for Solax inverters. After my question they build the web api, but that is not really what we need.
My contact is on holiday until august 15th. If there is a response Iā€™ll post results here.

3 Likes

Got it working!! You can add the below code to your config for a sensor that you can use in the energy dashboard:

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'

image

6 Likes

Works with my solax X3

Thanks! This works great with my Solax X3