Solax X1 Hybrid G4 (local & cloud API)

Glad you got it sorted. I’ve been using the modbus/tcp solution for almost 12 months and have had zero issues :slight_smile:

1 Like

That’s interesting, that’s different to how my SolaX behaves. I have two inverters - the one with the battery is always online. What model is yours? It seems that no two SolaX models behave the same way!
Another way to achieve what you want, is to change the operating mode to ‘backup’ while charging the car. That should stop the battery discharging unless the grid power fails. Then set it back to ‘self-use’ when done.
Whether that will keep the inverter online for API access, though, only testing will find out!

I have found the problem:
image
The sensor does not exist even if is in the sensor.yaml with “solax_rest_local” and “solax_rest_local_settings” (both working)… any suggestion?
Thanks for all

Problem solved adding some other sensor to sensor.yaml… i haven’t touch the solax_rest_cloud sensor…i don’t understand…

Hi, Solax Hybrid G4 7.5kw with pocket LAN 3.0 works with Home Assistant ? Can I use official integration?

Thanks a lot

@kamilb thank you so much for your guide. I’ve just got a Solax system and the dongle’s open SSID just really freaked me out.

I came across this reverse engineering repo to get the local data translation. Have you had a look at it? https://github.com/nazar-pc/solax-local-api-docs/blob/fe4d46346fb3936963e8c31ada53b870f0d73b61/Data2.txt

Witam. U mnie też działają sensory. Mam tylko jedno pytanie, czy można to pokazać w jakiś ładnych wykresach.

Been trying to get this to work but keep getting 401 unauthorized error message, I’ve changed the REG_NO and can access the inverter using a web browsers on the same network, only thing is, it doesn’t ask for a password to access the site and I think this might be complicating the process? any thoughts as I’m slowly going out my mind!

I’ve tried admin, ADMIN, Admin, the inverter 4 digit pin, blank (removing the pwd prompt) and all sorts… this really is the last part of a puzzle as we use Agile and I would really like some intelligence as to when the batteries are charging etc

(full error code content: “\r\n\r\nError\r\n<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">\r\n\r\n

401 Unauthorized.

\r\n”
status: 401)

Just a Note for Connections with Wifi Sticks V2 (tested with Version 2.033.20 and 2.034.22).

It seems not necessary using a reverse Proxy setup with nginx to map the IP 5.8.8.8 or use downgraded Firmware to access the API on a local IP, its enough to add a “X-Forwarded-For: 5.8.8.8” header to the request.

The device shows up at my local Network as “MXCHIP”. Using:

curl --header “X-Forwarded-For: 5.8.8.8” -X POST “http://192.168.178.22/?optType=ReadRealTimeData&pwd=&”

returns the JSON data.

Important, it seems to be necessary to have the “&” at the end of the URL, otherwise my stick just crashes.

If this works, adding the following lines in your YAML configuration of the REST API allows direct access on the local IP:

rest:

  • authentication: digest
    scan_interval: 20
    resource: http://192.168.178.22
    payload: “optType=ReadRealTimeData&pwd=&”
    method: POST
    headers:
    Content-Type: “application/x-www-form-urlencoded”
    X-Forwarded-For: “5.8.8.8”
    sensor:
1 Like

Hi Kamil,

Thanks for your very clear instructions, I’ve been reading countless posts on this topic for my Inverter + Cloud API only use case.

I’ve implemented your (cloud) instructions and have all my sensors available as entities, however not getting any data from Solax…yet. Will contintue to investigate.

One particular issue I am getting is 5 x errors related to Unit of Measurement, any suggestions?

Logger: homeassistant.components.sensor
Source: components/sensor/init.py:732
integration: Sensor (documentation, issues)
First occurred: 6:13:24 AM (1 occurrences)
Last logged: 6:13:24 AM

Entity sensor.solax_cloud_grid_power (<class ‘homeassistant.components.template.sensor.SensorTemplate’>) is using native unit of measurement ‘W’ which is not a valid unit for the device class (‘energy’) it is using; expected one of [‘kWh’, ‘MJ’, ‘GJ’, ‘Wh’, ‘MWh’]; Please update your configuration if your entity is manually configured, otherwise create a bug report at Issues · home-assistant/core · GitHub

Hi @riccid. This looks like a config error - worth testing out getting of the data using something like curl or postman first. Also, worth experimenting with the entity config (e.g. changing units, or commenting certain ones out).

(Please disregard - I was missing:
“sensor powercalc_label: !include powercalc.yaml”
from my config.yaml)

sigh

Hi Kamil,

You were correct, my issue was a simple (aka moronic) one, I was using the incorrect serial number in my API url.

I have another issue after adding all the cloud based components in your post. Currently I can add Energy from Grid and Energy to Grid in the Energy dashboard, however when I attempt to add Solar production there are no ‘current’ value sensors I can use.

Any thoughts as to why? Is this an issue within my Powercalc.yaml or have I perhaps missed a step?

Bizzarely I have also been able to build a dashboard that provides a whole bunch of API based feeds from the Inverter.

Nice work. Just confirming that I have local access working directly without a proxy.

X1 - G2 with Pocket WiFi 3.0. The data is different though being its a a X1-G2 so I’m working on a map for that.

You don’t need to add an “&” if your using the pocket v3.

- platform: rest
  name: "solax_rest_local"
  scan_interval: 10
  resource: !secret solax_local_ip
  payload: !secret solax_local_realtime_payload
  method: POST
  headers:
    Content-Type: "application/x-www-form-urlencoded"
    X-Forwarded-For: "5.8.8.8"
  authentication: digest
  json_attributes:
        - sn
        - ver
        - type
        - Data
        - Information
  value_template: OK -  {{ now().strftime("%H:%M:%S") }}

Good morning
I wanted to share with you an informative integration that I find practical, it is a battery charge and recharge estimation based on Node-RED. This is of course to be adapted according to your capacity, for my part I have 6000w.

[{"id":"a4c4fbb082a29c5e","type":"function","z":"823ffcb27199a3e4","name":"function 2","func":"let soc = msg.payload\nlet payload_batt = msg.payload_batt\n\nlet kwh_resten_batteri = 6000-((6000 * soc) / 100)\nlet heur_centieme = ((kwh_resten_batteri / payload_batt).toFixed(2)).toString().split(\".\")\nlet heur = parseInt(heur_centieme[0])\n//let heur = heur_centieme[0]\n\nlet centieme = parseInt(heur_centieme[1])\nlet minute = Math.round((60 * centieme) / 100)\n\n//let heur_Minute = (heur + \"h\" + minute).toString()\nlet heur_Minute = heur + \".\" + minute\n\nreturn {heur: heur, minute: minute,heur_Minute: heur_Minute}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":360,"wires":[["19d909b16ed213fe"]]},{"id":"641f1388717bd659","type":"api-current-state","z":"823ffcb27199a3e4","name":"batterie charge","server":"ee46c249.bf5b7","version":3,"outputs":2,"halt_if":"0","halt_if_type":"num","halt_if_compare":"is_not","entity_id":"sensor.solax_local_battery_use_in","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload_batt","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":220,"y":360,"wires":[["a4c4fbb082a29c5e"],[]]},{"id":"9ef483368eba2406","type":"poll-state","z":"823ffcb27199a3e4","name":"soc","server":"ee46c249.bf5b7","version":3,"exposeAsEntityConfig":"","updateInterval":"1","updateIntervalType":"num","updateIntervalUnits":"minutes","outputInitially":false,"outputOnChanged":false,"entityId":"sensor.solax_local_battery_soc","stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is_not","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":70,"y":380,"wires":[["641f1388717bd659","4ce0b3598691af76"]]},{"id":"19d909b16ed213fe","type":"ha-sensor","z":"823ffcb27199a3e4","name":"batt heur charge","entityConfig":"4a7f66909dbb5d8f","version":0,"state":"heur_Minute","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":540,"y":360,"wires":[["c911df0b83ab7abd"]]},{"id":"da14648fa965217f","type":"function","z":"823ffcb27199a3e4","name":"function 3","func":"let soc = msg.payload - 10\nlet payload_batt = msg.payload_batt\n\nlet kwh_resten_batteri = ((6000 * soc) / 100)\nlet heur_centieme = ((kwh_resten_batteri / payload_batt).toFixed(2)).toString().split(\".\")\nlet heur = parseInt(heur_centieme[0])\n//let heur = heur_centieme[0]\n\nlet centieme = parseInt(heur_centieme[1])\nlet minute = Math.round((60 * centieme) / 100)\n\nlet heur_Minute = (heur + \".\" + minute).toString() \n//let heur_Minute = heur + \".\" + minute\n\nreturn {heur: heur, minute: minute,heur_Minute: heur_Minute,}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":420,"wires":[["6e442fb0705d776a"]]},{"id":"4ce0b3598691af76","type":"api-current-state","z":"823ffcb27199a3e4","name":"batterie decharge","server":"ee46c249.bf5b7","version":3,"outputs":2,"halt_if":"0","halt_if_type":"num","halt_if_compare":"is_not","entity_id":"sensor.solax_local_battery_use_out","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload_batt","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":230,"y":420,"wires":[["da14648fa965217f"],[]]},{"id":"b7b85832ab9e96b8","type":"debug","z":"823ffcb27199a3e4","name":"heur decharge","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"heur_Minute","targetType":"msg","statusVal":"","statusType":"auto","x":760,"y":420,"wires":[]},{"id":"6e442fb0705d776a","type":"ha-sensor","z":"823ffcb27199a3e4","name":"batt heur decharge","entityConfig":"5d26a678d03e588e","version":0,"state":"heur_Minute","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":570,"y":420,"wires":[["b7b85832ab9e96b8"]]},{"id":"c911df0b83ab7abd","type":"debug","z":"823ffcb27199a3e4","name":"heur charge","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"heur_Minute","targetType":"msg","statusVal":"","statusType":"auto","x":730,"y":360,"wires":[]},{"id":"ee46c249.bf5b7","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false},{"id":"4a7f66909dbb5d8f","type":"ha-entity-config","server":"ee46c249.bf5b7","deviceConfig":"e27b7c4e474e94ed","name":"batt heur charge","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"batt heur charge"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false},{"id":"5d26a678d03e588e","type":"ha-entity-config","server":"ee46c249.bf5b7","deviceConfig":"66d7642f45afe0a7","name":"batt heur decharge","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"batt heur decharge"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false},{"id":"e27b7c4e474e94ed","type":"ha-device-config","name":"batt heur charge","hwVersion":"","manufacturer":"Node-RED","model":"","swVersion":""},{"id":"66d7642f45afe0a7","type":"ha-device-config","name":"batt heur decharge","hwVersion":"","manufacturer":"Node-RED","model":"","swVersion":""}]

I would like to ask a question, do you have any problems in system/logs with RESTful?
Because I installed the core version 2024.7.2 and every morning I have a crash at 5 a.m., restarting it works, so I put back 2024.6.4 but I have RESTful problems.

Enregistreur: homeassistant.components.rest.data
Source: components/rest/data.py:127
intégration: RESTful (documentation, problèmes)
S’est produit pour la première fois: 17 juillet 2024 à 17:16:06 (112 occurrences)
Dernier enregistrement: 14:07:36

Error fetching data: http://192.168.10.171/ failed with

IP is that of the solax WIFI key.

Hi, I am trying to connect to my X3-Hybrid-G4 connected to my network with PocketLAN. It seems to be getting an IP address of 192.168.1.186.

If I send it the curl command from a terminal I get this (SN Hidden):

% curl -d "optType=ReadRealTimeData&pwd=XXXXX" -X POST http://192.168.1.186 
curl: (7) Failed to connect to 192.168.1.186 port 80 after 15 ms: Couldn't connect to server

Any ideas on whats happening?

Hi
For me everything works correctly on a CMD, there is “%” too much.

curl -d "optType=ReadRealTimeData&pwd=XXXXX" -X POST http://192.168.1.186 
{"sn":"XXXXX","ver":"3.009.03","type":15,"Data":[2323,24,529,5002,2641,2681,4,4,122,119,2,17586,0,233,11810,65266,65206,31,96,2551,0,2957,0,55,100,0,35,3603,0,0,0,0,0,0,14551,2,228,6,529,40,256,1314,900,152,350,257,233,33,33,387,1,1,0,0,18000,0,65008,65535,65387,65535,0,0,0,0,0,0,0,0,0,0,1886,0,61937,65535,3000,0,62536,65535,1444,0,0,0,0,0,0,246,28,41,0,0,0,0,0,0,0,0,0,0,1,3851,788,6152,603,256,9509,0,0,0,0,0,1,1197,65508,65201,3312,3309,58343,69,21302,14389,18757,12600,16689,12611,14130,21302,14389,18757,12600,16689,12611,14130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,513,257,770,1,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,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,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,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,0,0,0,0,0,0],"Information":[5.000,15,"XXXXX",8,1.31,0.00,1.30,1.04,0.00,1]}

The first step would be to connect to the Wi-Fi key with IP: 192.168.1.186 with Chroms for example.

I’m using the cloud API to get data into Home Assistant. I have a SOLAX POWER POCKET LAN 2.0 adaptor. Is it possible to gather data locally? I’ve tried to follow the thread but haven’t succeeded.

Hi

It has been a huge help with this post and all the good input.
I have now got most of it working, but I need a way to set the inverter not to export power when there are negative prices.

Today, I use the app or web and set Export Control to 0. Maybe there are other options that do the same, but otherwise,

I would like help with what to call similar to solax_local_set_battery_grid_charge_level_payload: ‘optType=setReg&pwd=REG_NO&data={“num”:1,“Data”:[{“reg”:31,“val”:“{{ level }}”}]}’, which can change the value of Export Control.

I hope someone can help me get this to work. Thank you in advance.

Just to get it out there, I’m working on a integration for this: