Solar PV intregration

In case you are not using node-red or do not want to use mqtt, the below script will create the sensors directly in HA. replace xxx with your values.

import requests, json 

session = requests.Session()
session.auth = ('xxx', 'xxx')
response = session.get('http://192.168.1.14/status.html')

solar_power_prod = 0
solar_energy_prod = 0

for line in response.iter_lines():

    line = str(line).split("'")[1]

    headers = {
            'Authorization': 'Bearer xxx',
            'Content-Type': 'application/json'
        }    

    ## create http sensor solar_power_prod
    if 'var webdata_now_p' in line:

        solar_power_prod =  int(float(line.replace('var webdata_now_p = "','').replace('";','')))
        
        url_hass = 'http://192.168.1.130:8123/api/states/sensor.solar_power_prod'
        data = json.dumps({'state': solar_power_prod, 'attributes': {'unit_of_measurement': 'W', 'friendly_name': 'solar_power_prod'}})
        response = requests.post(url_hass, verify=False, headers=headers, data=data)

    ## create http sensor solar_energy_prod
    if 'var webdata_today_e' in line:

        solar_energy_prod =  round(float(line.replace('var webdata_today_e = "','').replace('";','')),2)
        
        url_hass = "http://192.168.1.130:8123/api/states/sensor.solar_energy_prod"
        data = json.dumps({"state": solar_energy_prod, 'attributes': {'unit_of_measurement': 'kWh', 'friendly_name': 'solar_energy_prod'}})
        response = requests.post(url_hass, verify=False, headers=headers, data=data)

Hi, where do you guys get your user ID for Solarman data loggers? Tried to use the email from their app/web and the SN from the logger with no luck!
Am using a Huayu inverter with a WiFi dongle.
Lol, user=admin, pass=admin. So obvious I had not even tried. On the web page for the logger, there is an option to send data to another server. Anyone gone that route?

Yep many have tried to go to the alternate server route and failed.

The portal that all these guys use is called Solarman/Igen - they all just rebadge it.

Sometime in late 2019 IGEN started rolling out V5 of their protocol - Basically the inverter sends a hello packet and then waits for a magic packet to return - if it does not get the magic packet it does nothing - until someone works out how to crack this V5 protocol and the magic packet - then the 2nd server option is a no go.

A couple of alternatives

  1. Open up the WIFI stick - it has a small daughterboard in there - this can be disconnected and you can put a splitter in place - then find a ESP8266/ESP32 project with Modbus and MQTT - you purchase a small RS485/TTL (3.3.V) adapter from Ebay for about $2 each - connect this to the ESP chip

Essentially you are running your own datalogger in parallel with the one on the WIFI dongle and you can query the Modbus registers to your hearts content on the unit.

  1. Same as above but you can do it using a Rpi ZeroW instead of the ESP chip, which is small enough to fit in the case with the dongle - you then run one of the many python libraries to query modbus and output to MQTT

  2. Source the RS485 plug (on the Solis inverters it is VERY hard to find one) and do your own Modbus query from whatever device you like

Craig

Hi, I too have a Solis 4G Inverter which I would like to pull the data from / into HA, I’ve copied your Node-Red scrape and inputted my Username, Password & Local IP Address but Publish MQTT just constantly shows “connecting”
I have only used Node-Red a small amount and when I have I’ve generally followed peoples step by step guides.
Any help would be much appreciated

I worked it out just after publishing this message, I hadn’t inputted my MQTT Username & Password!!

[quote=“Frank_R, post:17, topic:70109”]
The scrape node does:
curl ‘http://:@192.168.x.x/status.html’

Then the grab nodes use regex to grab the values.

Until today I’d never heard of regex never mind use it!
Could you please give some advice on setting it up
I now have the inverter communicating via mqtt (I think) but do not know what to do or where to find the scraped data

When I carry out a ping check in Node-Red I get these messages

1/28/2021, 10:27:38 AMnode: Grab current power valuefunction : (error)

“TypeError: Cannot read property ‘1’ of null”

1/28/2021, 10:27:38 AMnode: Grab total power today valuefunction : (error)

“TypeError: Cannot read property ‘1’ of null”

1/28/2021, 10:27:38 AMnode: Grab total power valuefunction : (error)

“TypeError: msg.payload.match is not a function”

Can anyone offer assistance please

Difficult to troubleshoot.

  1. Can you ping your wifi stick and login to the web interface using a normal browser.

  2. Try this updated flow. After a certain Node-Red update (while ago, can’t remember) the ping node stopped working.

[{"id":"a6c69280.aefa","type":"tab","label":"Solis","disabled":false,"info":""},{"id":"8d3fd5ff.a575d8","type":"mqtt out","z":"a6c69280.aefa","name":"Publish MQTT Message","topic":"","qos":"","retain":"true","broker":"36d42be1.7a03e4","x":1150,"y":500,"wires":[]},{"id":"6315810.eba6a8","type":"ping","z":"a6c69280.aefa","mode":"timed","name":"Ping Solis Convertor","host":"192.168.2.25","timer":"60","inputs":0,"x":110,"y":280,"wires":[[]]},{"id":"9977c825.5888d8","type":"switch","z":"a6c69280.aefa","name":"Check if convertor is online","property":"payload","propertyType":"msg","rules":[{"t":"false"},{"t":"gt","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":200,"y":400,"wires":[["71244c20.72e364","b51741e5.39a3d"],["5af351cf.e8d92"]]},{"id":"24252177.a3d88e","type":"function","z":"a6c69280.aefa","name":"Grab current power value","func":"var parts = msg.payload.match(/webdata_now_p\\s=\\s\"(\\d+)\"/);\nmsg.payload = {\n    value: parts[1],\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":470,"y":480,"wires":[["e7aaad99.13a0c"]]},{"id":"5af351cf.e8d92","type":"exec","z":"a6c69280.aefa","command":"curl 'http://username:[email protected]/status.html'","addpay":true,"append":"","useSpawn":"false","timer":"10","oldrc":false,"name":"Scrape web interface","x":180,"y":480,"wires":[["24252177.a3d88e","35f76747.bda408","10bd3393.9a038c"],[],[]]},{"id":"71244c20.72e364","type":"change","z":"a6c69280.aefa","name":"Prepare message","rules":[{"t":"set","p":"topic","pt":"msg","to":"Solis_Power_Current","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":340,"wires":[["8d3fd5ff.a575d8"]]},{"id":"e7aaad99.13a0c","type":"change","z":"a6c69280.aefa","name":"Prepare message","rules":[{"t":"set","p":"topic","pt":"msg","to":"Solis_Power_Current","tot":"str"},{"t":"move","p":"payload.value","pt":"msg","to":"payload","tot":"msg"},{"t":"delete","p":"rc","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":480,"wires":[["a54e4318.609bb"]]},{"id":"35f76747.bda408","type":"function","z":"a6c69280.aefa","name":"Grab total power today value","func":"var parts = msg.payload.match(/webdata_today_e\\s=\\s\"(\\S+)\"/);\nmsg.payload = {\n    value: parts[1],\n};\nreturn msg;","outputs":1,"noerr":0,"x":480,"y":520,"wires":[["ec1f587c.99d7a8"]]},{"id":"ec1f587c.99d7a8","type":"change","z":"a6c69280.aefa","name":"Prepare message","rules":[{"t":"set","p":"topic","pt":"msg","to":"Solis_Power_Today","tot":"str"},{"t":"move","p":"payload.value","pt":"msg","to":"payload","tot":"msg"},{"t":"delete","p":"rc","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":520,"wires":[["8d3fd5ff.a575d8"]]},{"id":"10bd3393.9a038c","type":"function","z":"a6c69280.aefa","name":"Grab total power value","func":"var parts = msg.payload.match(/webdata_total_e\\s=\\s\"(\\S+)\"/);\nmsg.payload = {\n    value: parts[1],\n};\nreturn msg;","outputs":1,"noerr":0,"x":460,"y":560,"wires":[["8a30c6ed.9b75d8"]]},{"id":"8a30c6ed.9b75d8","type":"change","z":"a6c69280.aefa","name":"Prepare message","rules":[{"t":"set","p":"topic","pt":"msg","to":"Solis_Power_Total","tot":"str"},{"t":"move","p":"payload.value","pt":"msg","to":"payload","tot":"msg"},{"t":"delete","p":"rc","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":560,"wires":[["8d3fd5ff.a575d8"]]},{"id":"b51741e5.39a3d","type":"timecheck","z":"a6c69280.aefa","name":"Midnight","time":"23:58","x":500,"y":400,"wires":[["4869bc6c.1cf2c4"],[]]},{"id":"4869bc6c.1cf2c4","type":"change","z":"a6c69280.aefa","name":"Prepare message","rules":[{"t":"set","p":"topic","pt":"msg","to":"Solis_Power_Today","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":380,"wires":[["8d3fd5ff.a575d8"]]},{"id":"a54e4318.609bb","type":"function","z":"a6c69280.aefa","name":"to kW","func":"msg.payload = Number(msg.payload);\nmsg.payload = (msg.payload)/1000;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":890,"y":480,"wires":[["8d3fd5ff.a575d8"]]},{"id":"d3756928.2025d8","type":"ping","z":"a6c69280.aefa","mode":"triggered","name":"Ping Solis Convertor","host":"","timer":"20","inputs":1,"x":190,"y":240,"wires":[["9977c825.5888d8"]]},{"id":"2311af6d.9be32","type":"inject","z":"a6c69280.aefa","name":"Ping trigger","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"host\":\"192.168.2.25\",\"timeout\":15000}]","payloadType":"json","x":130,"y":160,"wires":[["d3756928.2025d8"]]},{"id":"36d42be1.7a03e4","type":"mqtt-broker","name":"mqtt_broker","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]
  1. If ping works again, please post output of the scrape node. maybe your web interface (and output) is slightly different. You can try regex101.com and paste your output in the text box, then tru the regex to see how it works.
1 Like

I’m new to setting anything up using mqtt, the only devices I’ve really done anything with that are mqtt are smart plugs and bulbs that I have flashed with tasmota and then they show as devices in mqtt
Questions & Answers

  1. Yes I can login using the wifi sticks local IP address
  2. I’ve done a ping test using Windows cmd and it passed ok
  3. I’ve loaded the new flow and everything appears OK and my mqtt broker log shows a connected
    1611922381: New connection from xxx.xx.xx.x on port 1883.
    1611922381: New client connected from xxx.xx.xx.x as Solis_Inverter (p2, c1, k60, u’MQTT’).
  4. Should this create an entry in my integrations in entities or devices?

Will this help?
Ive attached a debug to the scrape in node-red and this is the result
1/29/2021, 2:04:42 PMnode: Grab current power valuefunction : (error)

“TypeError: Cannot read property ‘1’ of null”

1/29/2021, 2:04:42 PMnode: Grab total power today valuefunction : (error)

“TypeError: Cannot read property ‘1’ of null”

1/29/2021, 2:04:42 PMnode: Grab total power valuefunction : (error)

“TypeError: Cannot read property ‘1’ of null”

1/29/2021, 2:04:42 PMnode: 73368a0f.e61e44192.168.1.115 : msg.payload : string[7425]

“ addCfg(‘wifi_on’,0x0f070200,‘enable’);↵addCfg(‘sta_ssid’,0x04df0200,‘KLS-5810G 2.4GHz’);↵addCfg(‘ap_ssid’,xxxxxxxx,‘AP_xxxxxxxx’);↵addCfg(‘lan_ip’,xxxxxxxx,‘xx.xx.xxx.xxx’);↵addCfg(‘sta_enable’,0x04d40100,‘1’);↵ var st_con1=”"; var st_con2=""; var st_con3=""; function status(re) { var st_en=window.parent.reTip(“3”); var st_dis=window.parent.reTip(“4”); if(re.charAt(0)==“1”) { st_con1=“3”; document.getElementById(“cover_remote_status_a”).innerHTML=st_en; }else { st_con1=“4”; document.getElementById(“cover_remote_status_a”).in…"
I’ve xxx some data
It does appear to communicate with the inverter
Thanks again for your assistance

When I login to my inverter via a web page the 1st page I see is this (is yours similar)

Device information

Device serial number

613xxxxxx

Firmware version

H4.01.51Y4.0.02W1.0.57(2017-08-312-D)

Wireless AP mode

Enable

SSID

AP_613xxxxxx

IP address

xx.xx.xxx.xxx

MAC address

xx:xx:xx:xx:xx:xx

Wireless STA mode

Enable

Router SSID

KLS-5810G 2.4GHz

Signal Quality

34%

IP address

192.168.1.115

MAC address

xx:xx:xx:xx:xx:xx

Cable mode

Disable

IP address

MAC address

Connected Inverter

Type

Ginlong

Number

1

Inverter serial number

Firmware version (main)

006

Firmware version (slave)


Inverter model

0

Rated power


Current power


Yield today

0 kWh

Total yield

1311 kWh

Alerts


Last updated

0 Min Ago

Remote server information

Remote server A

Pingable

Remote server B

Pingable

Remote server C

Unpingable

As I seem to have hit a brick wall using the node-red method I thought I’d try the script method
Unfortunately I’ve hit problems again early on
Having NEVER used scripts in HA I have zero experience
I’ve copied cpuram’s script into my scripts.yaml file then saved & carried out a “Check Configuration” before restarting HA but I get an error

Error loading /config/configuration.yaml: mapping values are not allowed here
in “/config/scripts.yaml”, line 10, column 34

ANY assistance with either this method or the node-red method would be very much appreciated

@xion2000 I was able to add a PV sensor without any scripts or mqtt, just by calling inverter stick http (adjust ip/password values for your setup):

configuration.yaml

sensor:
  - platform: rest
    resource: http://192.168.1.14/status.html
    authentication: basic
    username: admin
    password: XXXXX
    unit_of_measurement: 'W'
    value_template: '{{ value | regex_findall_index("var webdata_now_p = \"(\d+)\"")}}'
    device_class: power
    name : Solis
2 Likes

Thanks Iknop I’ve tried that but still no success
I’ve logged into the wifi stick / Solis Inverter and this is my status screen (I’ve edited some data out)

Device information
Device serial number
613496541
Firmware version
H4.01.51Y4.0.02W1.0.57(2017-08-312-D)
Wireless AP mode
Enable
SSID
xxxxxxxxxx
IP address
xx.xx.xxx.xxx
MAC address
xx:xx:xx:xx:xx:xx
Wireless STA mode
Enable
Router SSID
xxxxxxxxxxxxxxx
Signal Quality
24%
IP address
192.168.1.115
MAC address
xx:xx:xx:xx:xx:xx
Cable mode
Disable
IP address
MAC address
Connected Inverter
Type
Ginlong
Number
1
Inverter serial number
Firmware version (main)
006
Firmware version (slave)

Inverter model

0
Rated power


Current power

Yield today
0 kWh
Total yield
1313 kWh
Alerts

Last updated
0 Min Ago
Remote server information
Remote server A
Remote server B
Remote server C

What I find strange is “Current Power” always shows ---- but if I login to the Ginlong v2 website (or the old version 1 website which is still running) its uploading data fine

Thanks very much never thought to just scrape off the invertor panel, I now use a modified version! I added a timer that loops back around so it posts every minute and i used a node red entity so it just updates that instead of broadcasting to mqtt. The ping stuff didn’t seem to work so i killed all that and it seems to run fine.

Its not perfect as a cloud goes over and it dumps the input down for the minute but its enough to know if its a high solar or low solar output day which will be impacting my aircon settings shortly.


image
image

2 Likes

Did some research on this today. The file status.html is created each time the master.js and subsequently slave.js have been called. In my case, it was empty and only contained some horizontal lines.

The thing is that for populating the status.html page, the javascript file ‘status.js’ calls a json function through AJAX. If you run that against your Ginlong convertor, it should provide a json output. Try this:
http://p.q.r.s/status.json?CMD=inv_query
p.q.r.s obviously the IP address of your convertor.

Package that into a sensor:

- platform: rest
  resource: http://192.168.1.4/status.json?CMD=inv_query
  name: Solar power
  json_attributes:
    - i_pow_n
    - i_eday
    - i_eall
  value_template: '{{ value_json.name }}'
- platform: template
  sensors:
    power_now:
      friendly_name: "Current power"
      value_template: '{{ states.sensor.solar_power.attributes["i_pow_n"] }}'
      unit_of_measurement: W
    energy_today:
      friendly_name: "Energy today"
      value_template: '{{ states.sensor.solar_power.attributes["i_eday"] }}'
      unit_of_measurement: kWh

Worked for me.

– EDIT –
The inverter itself also consumes energy. It seems to be 224W, because this is the figure it remains reporting, even when the output power drops to zero. At the end of the day we are focused on what the solar panels deliver to the grid and as such we need to reduce the power with that consumed power.

Likewise we are reducing the produced energy the same way. In the returned JSON file, the inverter reports the ‘uptime’ (g_time in seconds), but that figure is highly inaccurate. Specifically during cloudy days the inverter may shut down if the produced solar energy is not sufficient to even power the inverter. So I am using the time the sun rose above the horizon. This is the latest code:

- platform: template
  sensors:
    power_now:
      friendly_name: "Current power"
      value_template: >-
        {% if is_state("sun.sun", "above_horizon") -%}
          {{ states.sensor.solar_power.attributes["i_pow_n"]-224 }}'
        {%- endif %}
      unit_of_measurement: W
    energy_today:
      friendly_name: "Energy today"
      value_template: >-
        {% if is_state("sun.sun", "above_horizon") -%}
          {% set uptime = as_timestamp(now()) - as_timestamp(states.sun.sun.last_changed) + 3600-%}
          {{ (states.sensor.solar_power.attributes["i_eday"]|float-((224/1000)*(uptime/3600)))|round(3)}}
        {%- endif %}
      unit_of_measurement: kWh

Good luck

1 Like

Hello

I think it depends on version of logger.
Mine is:
Firmware version (main)001B
Firmware version (slave)002B
Everything in my browser is on the same IP adress, there is no other sub-sites.


So it dosen’t work
http://192.168.x.x/status.html
or
http://192.168.x.x/status.json?CMD=inv_query

I tried to reduce only to IP adres but any of above example dosen’t work.
Do you have any idea what to check or change?

regards

It must be a firmware issue then. Here’s mine, which works perfectly OK.
image

So yours does not produce any output on http://192.168.1.8/status.json?CMD=inv_query ?
Can you go into developer mode in Google Chrome to try and find the source of the information that displays the page? From there you may run into some kind of json request.

Confirm,
http://192.168.1.8/status.json?CMD=inv_query
I got:
ERROR:404 Not Found
And I think it’s the matter of firmware.
In my side there is no information about “Brand”, and “Last updated” is only “0”, “1” and nothing.
But…
It is also matter of my little experience …
In my browser there is no site status.html but the way of scraping the page is working…
So I define the sensors (like lknop proposed) and … it works! :slight_smile:
I think I will not drill down the case, thanks all for help

regards
atryda

Did u get it in homeassistant?
How to grab data as I have same problem as yours.
Please guide

Yes, sure

I defined two sensors in config.yaml:
Replace xxxxx with your own password and change IP to yours.
But I know that there are a few version of this page, so I am not sure this will work for you

regards

  - platform: rest
   resource: http://192.168.1.8/status.html
   authentication: basic
   username: admin
   password: admin
   unit_of_measurement: 'W'
   value_template: '{{ value | regex_findall_index("var webdata_now_p = \"(\d+)\"")}}'
   device_class: power
   name: "Solis current power"
 - platform: rest
   resource: http://192.168.1.8/status.html
   authentication: basic
   username: admin
   password: admin
   unit_of_measurement: 'kWh'
   value_template: '{{ value | regex_findall_index("var webdata_today_e = \"(\S+)\"")}}'
   device_class: power
   name: "Solis energy today"
1 Like

Dear, o u get results?
as i dont
and did you upgrade device?
invalid config for [sensor.rest]: invalid template (TemplateSyntaxError: unexpected char ‘“’ at 32) for dictionary value @ data[‘value_template’]. Got ‘‘{{ value | regex_findall_index(“var webdata_now_p = “(\d+)””)}}’’. (See ?, line ?)

Yes, it works:
solis1

Mine PV was instaled October 2020, so I didn’t upgrade any firmware.

I suppose it could be the matter of your enviroment.
What kind of instalatian have you?
Mine is HA OS on t630 terminal.
I have such parameters:

version core-2021.3.2
installation_type Home Assistant OS
dev false
hassio true
docker true
virtualenv false
python_version 3.8.7
os_name Linux
os_version 5.4.99
arch x86_64
timezone Europe/Warsaw

What has happen if you on terminal console put such commend:
curl ‘http://admin:[email protected]/status.html’ | grep ‘var webdata_now’
Of course replace xxxxx with password :wink:

Have you any data?

regards