My journey to get Solax PV data into HA.
Inverter: X1-Boost-Air-Mini
Firmware: 2.033.20
Cloud
At first I used the Solax cloud data: Solax cloud sensors
It works but the polling frequency is limited and your data is shared with 3rd parties in China.
Local: Inverse proxy
So I used a spare raspberry Pi and turned it into an inverse proxy to get the data direct: Inverse proxy
It works but… the Pi is always on and it adds to the complexity of my HA system
Use custom firmware
@Davosje and others flashed the dongle firmware with custom firmware. Unfortunately this did not work for me.
Direct access
@mf76130 wrote a great post direct which I used as a bases. I had to tweak the settings quite a bit, that is why I am writing this post. One of the key changes was suggested by @markvan for the headers.
So this is what I did:
Connect the solax inverter to your wifi net and give it fixed IP address (192.168.2.88 in my case)
Block internet access for this IP address in your router
Create a Rest sensor. This sensor is pulling the data from the inverter:
XXXXX is the inverter SN
- platform: rest
authentication: digest
scan_interval: 5
resource: http://192.168.2.88/
payload: "optType=ReadRealTimeData&pwd=XXXXXX"
method: POST
headers:
X-Forwarded-For: 5.8.8.8
name: "solax_rest_local"
json_attributes:
- type
- SN
- ver
- Data
- Information
value_template: 'OK' # dummy value, not used; avoids the "State max length is 255 characters" error
Next create a bunch of detailled template sensors:
- platform: template
- sensor:
- name: solax_local
state: >
{% if not state_attr('sensor.solax_rest_local', 'sn') == "XXXXXXXXX" %}{{ now().strftime("%H:%M:%S") }}
{% else %}{{ (states('sensor.solax_local')) }}{% endif %}
attributes:
sn: >-
{% if not state_attr('sensor.solax_rest_local', 'sn') == "XXXXXXXXX" %}{{ (state_attr('sensor.solax_rest_local', 'sn')) }}
{% else %}{{ (state_attr('sensor.solax_local', 'sn')) }}{% endif %}
ver: >-
{% if not state_attr('sensor.solax_rest_local', 'sn') == "XXXXXXXXX" %}{{ (state_attr('sensor.solax_rest_local', 'ver')) }}
{% else %}{{ (state_attr('sensor.solax_local', 'ver')) }}{% endif %}
type: >-
{% if not state_attr('sensor.solax_rest_local', 'sn') == "XXXXXXXXX" %}{{ (state_attr('sensor.solax_rest_local', 'type')) }}
{% else %}{{ (state_attr('sensor.solax_local', 'type')) }}{% endif %}
Data: >-
{% if not state_attr('sensor.solax_rest_local', 'sn') == "XXXXXXXXX" %}{{ (state_attr('sensor.solax_rest_local', 'Data')) }}
{% else %}{{ (state_attr('sensor.solax_local', 'Data')) }}{% endif %}
Information: >-
{% if not state_attr('sensor.solax_rest_local', 'sn') == "XXXXXXXXX" %}{{ (state_attr('sensor.solax_rest_local', 'Information')) }}
{% else %}{{ (state_attr('sensor.solax_local', 'Information')) }}{% endif %}
- name: "Solax Inverter Temperature"
state: "{{ state_attr('sensor.solax_local', 'Data')[7] | int(default=0) }}"
unit_of_measurement: "°C"
device_class: "temperature"
- name: "Solax Energy today"
unit_of_measurement: "kWh"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[8] }}"
device_class: energy
state_class: measurement
icon: mdi:solar-panel
- name: "Solax Energy Total"
unit_of_measurement: "kWh"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[9] }}"
device_class: energy
state_class: total_increasing
icon: mdi:chart-line
- name: "Solax DC Voltage"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[2] | float }}"
unit_of_measurement: "V"
device_class: "voltage"
- name: "Solax DC Current"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[0] }}"
unit_of_measurement: "A"
device_class: "current"
- name: "Solax DC Power"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[11] }}"
unit_of_measurement: "W"
device_class: "power"
icon: mdi:power-socket-de
- name: "Solax AC Output Voltage"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[5] }}"
unit_of_measurement: "V"
device_class: "voltage"
- name: "Solax AC Current"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[4] }}"
unit_of_measurement: "A"
device_class: "current"
- name: "Solax AC Power"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[6] }}"
unit_of_measurement: "W"
device_class: "power"
icon: mdi:power-socket-de
- name: "Solax AC Frequency"
state: "{{ state_attr('sensor.solax_rest_local', 'Data')[50] | float }}"
unit_of_measurement: "Hz"
device_class: "frequency"
icon: mdi:music-clef-treble
- name: "Solax Inverter Operation Mode"
state: >
{% if state_attr('sensor.solax_local', 'Data')[68] == 0 %}Waiting
{% elif state_attr('sensor.solax_local', 'Data')[68] == 1 %}Checking
{% elif state_attr('sensor.solax_local', 'Data')[68] == 2 %}Normal
{% elif state_attr('sensor.solax_local', 'Data')[68] == 3 %}Off
{% elif state_attr('sensor.solax_local', 'Data')[68] == 4 %}Permanent Fault
{% elif state_attr('sensor.solax_local', 'Data')[68] == 5 %}Updating
{% elif state_attr('sensor.solax_local', 'Data')[68] == 6 %}EPS Check
{% elif state_attr('sensor.solax_local', 'Data')[68] == 7 %}EPS Mode
{% elif state_attr('sensor.solax_local', 'Data')[68] == 8 %}Self Test
{% elif state_attr('sensor.solax_local', 'Data')[68] == 9 %}Idle
{% elif state_attr('sensor.solax_local', 'Data')[68] == 10 %}Standby
{% else %}I dont know{% endif %}
- name: "Solax Inverter Nominal Power"
state: "{{ state_attr('sensor.solax_rest_local', 'Information')[0] | float | round(0) }}"
unit_of_measurement: "kW"
- name: "Solax Module SN"
state: "{{ state_attr('sensor.solax_rest_local', 'sn') }}"
- name: "Solax module fw version"
state: "{{ state_attr('sensor.solax_rest_local', 'ver') }}"
- name: "Solax type"
state: "{{ state_attr('sensor.solax_rest_local', 'type') }}"
- name: "Solax Inverter SN"
state: "{{ state_attr('sensor.solax_rest_local', 'SN') }}"
- name: "Solax Inverter Information"
state: "{{ state_attr('sensor.solax_rest_local', 'Information') }}"
- name: "Solax Inverter Data"
state: "{{ state_attr('sensor.solax_rest_local', 'Data') }}"
Have fun with your private local PV data!