Solax X1 Hybrid G4 (local & cloud API)

Hi,

I have an X1 Boost string inverter, as opposed to the Hybrid. The Yield data appears to be in the same place in the output for both types of inverter, but other fields are in different places (PV1 power and PV2 power for example … I’m still working out which position in the array they are in).

BTW, the “Solax Dashboard AC Daily Yield” entity that I tested appears to be working correctly in the energy dashboard.

FYI had Issue with not reconnecting with inverter when router reset as it assigned a different Local IPv4 address to the inverter. Overcame this with IP reservation in the router settings. Might sound simple and people might know this ,but I am sure many do not. Did the same for home assistant just in case

1 Like

Hi Kamil,
Thanks for your great work! I have a Pocket Wifi version 2 so I uploaded the modified firmware from ChriSoft and was able to use the HA Solax integration from which I then copied and adapted all your nice sensor templates. :wink: :clap:
That seemed easier for me than use the REST platform with reverse proxy that somehow worked weird.

I’m now trying to get the automation for the hot water heater working but then I’m stuck trying to understand your binary sensor template. I don’t understand your OR statements and don’t see how the set states will make the binary sensor go from on to off to use in the automation as I don’t see any if or trigger.

Could you try to explain me in plain words what it is doing? (I’m pretty bad at templating…)

TIA

1 Like

Hi KamilB, thanks for this great way to get the data from LAN out of the Solax invertor. I was struggeling a lot with cloundrelated time-outs and slow refresh rates.

I have all scripts working, but all the LAN sensors doesn’t show any data. The Cloud sensors are working fine. When I do CURL via cli I get all data fine:

{“type”:“X1-Boost-Air-Mini”,“SN”:“SW…”,“ver”:“2.033.20”,“Data”:[5.3,0.0,392.5,0.0,8.7,233.2,2034,33,4.9,335.8,0,2084,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00,0.00,0,0,0,0,0,0,0,50.00,0,0,0,0,0,0,0,0,0,0.00,0,0,0,0,0.00,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],“Information”:[5.000,4,“X1-Boost-Air-Mini”,“XB…”,1,2.18,0.00,1.36,0.00]}

So you can see I have a X1-Boost invertor (I have removed the serialnumbers from the output above). Is there something different with the mapping of the data?

I hope you can assist a little to get me running with Solax LAN.

Thank you!

1 Like

This worked great thank you very much for the simple instructions!

With the API documentation having a maximum 10,000 a day limit, I have changed the rate to 9 seconds. Is there a way to change the poll frequency dependent on time of day? Live data is useful during daylight hours but can be updated less in the evening/night as it would only be battery changes. The reason for asking is that it seems that with the high frequency the Solax Cloud app struggles with timeouts.

1 Like

Hi @ColinRobbins. I think I’ve managed to get the off-peak charging working pretty well, but there is one remaining scenario for which I’m not sure yet what’s the best strategy:

  • we get plenty of sunshine and the battery gets charged to full
  • by 0030 the next day (when the night tariff starts) the charge level is well above the charge from grid target (e.g. 50% left with target being 10%)
  • forced charge set from 0030 to 0430, allowed discharge 0000-2359
  • it seems that battery won’t discharge at all during the forced charge period
    What I’d like is to let the battery discharge until it drops to the new target rather than keep using off-peak grid and saving the battery for peak use. Any thoughts?

@leigh258 sorry, I don’t know how to make the poll frequency dynamic. I believe the API day limit only applies to the cloud API, doesn’t it? I haven’t seen any timeouts using the local connection and I poll every 5 seconds.

Hi @Freakandel. Unfortunately these mappings from an array to actual properties seem to differ from inverter to inverter. Maybe yours is one of those: solax/solax/inverters at 5fdb6d18acd78350b33fd645f69b4eb301167a72 · squishykid/solax · GitHub
Otherwise you might need to decode it yourself. Best way probably is to use the ‘local’ connection in the Solax app and while it’s refreshing the values, run the curl command to see which ones match. It’s a real shame that Solax don’t publish these mappings for us to use. Not sure how else to help…

1 Like

@patitocanardo give me a few days and I will try to describe the binary sensor idea better - just finishing a similar one for hot water immersion with Sonoff Powr3.

1 Like

My batter takes 2 hours to charge from the grid, so have reduced the forceCharge window down to 0230 to 0430. Not perfect, but works for now - May need a better solution in summer.

If only we could decode the time parameter, maybe we could start to set the time window automatically.

You could make it dynamic, by setting it to a very high value like 3600. Then using an automation to force an update iOS f whatever time pattern you want.

I’ve set mine to 10 seconds, and have not seen any timeouts for a long time.

I’ve managed to decode the time parameters so I can both read and set the charge and discharge times from HA. I’ll try do get some time later tonight or during the weekend to write up an explanation.

2 Likes

The calculation to decode the parameters is actually not too tricky. The trickiest part is that they reverse the process when setting compared to reading the data which was what threw me off to begin with.
Basically the value being read is a 16 bit value where the first 8 bits are the minutes and the last 8 bits is the hour, and when setting the time it’s the other way around (so first 8 bits are hours and last 8 bits are minutes).
Because I don’t know how to use bit shift with templates, I used division and modulo instead.
So practically calculating the time from value 6404 (using Forced Charge Period End Time from @kamilb google sheet) you would take 6404/256 = 25.015625 to get the minutes (remove the decimals to get 25) and 6404%256 = 4 to get the hour, meaning that 6404 = 4:25.
If we instead would like to set the time 4:25 we would do 4*256+25=1049 and set 1049 to register 38.

Here is the code for my sensors which hopefully makes it make more sense

### Battery settings charge/discharge ###
  - name: "Solax Battery Setting Start Charge"
    state: "{{'%02d' % ((state_attr('sensor.solax_local_settings', 'Data')[7])%256 | int(default=0)) }}:{{'%02d' %((state_attr('sensor.solax_local_settings', 'Data')[7])/256) | int(default=0)}} "
  - name: "Solax Battery Setting Stop Charge"
    state: "{{'%02d' % ((state_attr('sensor.solax_local_settings', 'Data')[8])%256 | int(default=0)) }}:{{'%02d' % ((state_attr('sensor.solax_local_settings', 'Data')[8])/256) | int(default=0)}} "
  - name: "Solax Battery Setting Start Discharge"
    state: "{{'%02d' % ((state_attr('sensor.solax_local_settings', 'Data')[9])%256 | int(default=0)) }}:{{'%02d' % ((state_attr('sensor.solax_local_settings', 'Data')[9])/256) | int(default=0)}} "
  - name: "Solax Battery Setting Stop Discharge"
    state: "{{'%02d' % ((state_attr('sensor.solax_local_settings', 'Data')[10])%256 | int(default=0)) }}:{{ '%02d' % ((state_attr('sensor.solax_local_settings', 'Data')[10])/256) | int(default=0)}} "

The template used to calculate the value to set

level: '{{ (states(''input_number.hour'') | int)*256 + (states(''input_number.minutes'') | int) }}'

And my rest command to read the settings from the inverter

  - scan_interval: 3600
    resource: !secret solax_local_ip
    payload: !secret solax_local_settings_payload
    method: POST
    sensor:
      name: "solax_rest_local_settings"
      value_template: "{{ '[' ~ value.split(',')[28] ~ ',' ~ value.split(',')[29] ~ ',' ~ value.split(',')[30] ~ ',' ~ value.split(',')[31] ~ ',' ~ value.split(',')[32] ~ ',' ~ value.split(',')[33] ~ ',' ~ value.split(',')[34] ~ ',' ~ value.split(',')[36] ~ ',' ~ value.split(',')[37] ~ ',' ~ value.split(',')[38] ~ ',' ~ value.split(',')[39] ~ ',' ~ value.split(',')[53] ~ ']' }}"

Hope this helps someone, feel free to ask questions if the write up was unclear!

4 Likes

My solax cloud api request is not working anymore does anyone else have this issue?

HTTP Status 404 – Not Found when running request through web browser

The app has not been working for me all day, so probably they are having some issues with the cloud api (main reason I started looking into the local api).

1 Like

Using fused spur with energy monitoring myself, would be nice to see what you come up with, I just used standard automation using grid,battery sensor values to switch on and off. Using solar supplimented by battery to run immersion heater. Saves on gas/oil also when run same time as boiler

Hello,

I’ve been trying to connect the solax locally against homeassistant for some time and I finally succeeded but attacking the solax wifi ip. I’m trying to do it against the local ip of the solax home network but it doesn’t work for me. Do you have any idea why it doesn’t work?

I’m no sure where I found the code below online, but it has been working fine for me for the last few weeks so you can use the code below to access it locally.

  - platform: rest
    name: solaxx1data
    resource: http://192.168.1.77/?optType=ReadRealTimeData    # Local IP of Solax Pocket Wifi
    method: POST
    headers: 
      X-Forwarded-For: 5.8.8.8
    scan_interval: 5
    timeout: 4
    value_template: 'OK'
    json_attributes:
      - type
      - SN
      - ver
      - Data
      - Information

HI. I´ve gotten the online sensors part working but they tend to time out for a while, and then return with data. Is there a way to avoid the break in sensor data? graphs seem to not like the interrupted flow of data.

I use the template sensor setup like this to just use the last value until it reads the data again. I found good solid wifi signal to the dongle helps a lot.

  - platform: template
    sensors:
      solaxx1_energytoday:
        friendly_name: SolaxX1 ENERGYTODAY
        unit_of_measurement: "kWh"
        value_template: >
          {% if is_state('sensor.solaxx1data', 'unavailable') %}
            {{ states('sensor.solaxx1_energytoday') }}
          {% else %}
            {{ state_attr("sensor.solaxx1data", "Data")[8] }}
          {% endif %}
        icon_template: mdi:home-lightning-bolt-outline
        device_class: "energy"
        attribute_templates:
          state_class: total_increasing
          time_stamp: >
            {{ now() }}