Getting data from a Solis (ginlong) inverter

Important: to save you time, make sure your inverter has a “status.html” page with these lines:

var webdata_now_p = “xxx”;
var webdata_today_e = “x.xx”;
var webdata_total_e = “xxx.x”;

The ‘x’ are your values. The script won’t work if that does not exist and, unfortunately, there seem to be many versions of that firmware. Back to the original post:

Hi,

this is a solution to get current power, daily & total yield from a Solis S6-GR1P type inverter with a wireless stick.
There is no need for a cloud with this setup.

What you need: the inverter with Wifi stick, the IP of the stick and your login information. Appdaemon with the requests module installed.

The script is pretty straightforward and not very elegant. It will run every minute, log into the inverter, get the “status.html” page and filter the three values from it. They will be stored in “sensor.solis_current_power”, “sensor.solis_energy_today” & “sensor.solis_total_energy” and can be accessed by HA as usual.

In the script, you need to change the IP address and the login info.

The script only does anything when the sun is up. It will write the values into the log and also if it fails to reach the inverter.

import appdaemon.plugins.hass.hassapi as hass
import requests
from requests.auth import HTTPBasicAuth

#
# scrape the inverters web page
#
# Args:
#

class SolisScrape(hass.Hass):

    def initialize(self):
        self.log("Solis scrape started")
        self.run_in(self.update, 0)
        # update every minute
        self.run_every(self.update, "now", 60)

    def update(self, kwargs):

        if self.sun_up():   # no sun, no fun
            # get the status page
            URL = "http://192.168.0.111/status.html"
            try:
                page = requests.get(URL, auth = HTTPBasicAuth('admin', 'admin'))
                # split it
                liste = page.text.split()
                # check were the interesting data is
                now_p_index = liste.index('webdata_now_p')
                today_e_index = liste.index('webdata_today_e')
                total_e_index = liste.index('webdata_total_e')
                # the values are always two indices behind, snip off excess "" & ;
                current_power = float(liste[now_p_index+2][1:-2])
                energy_today = float(liste[today_e_index+2][1:-2])
                total_energy = float(liste[total_e_index+2][1:-2])
                # Build the HA sensor entity with the values returned 
                entity = "sensor.solis_current_power"
                self.set_state(entity, state = current_power)
                entity = "sensor.solis_energy_today"
                self.set_state(entity, state = energy_today)
                entity = "sensor.solis_total_energy"
                self.set_state(entity, state = total_energy)
                logstring = f"Solis: Current: {current_power}W Today: {energy_today}kWh Total: {total_energy}kWh"
                self.log(logstring)
            except:
                self.log("Failed to reach inverter")    # do nothing
        else:   # no sun, no power
            entity = "sensor.solis_current_power"
            self.set_state(entity, state = 0)

Save it as “solisscrape.py”. Put this in your Apps.yaml:

solis_scrape:
  module: solisscrape
  class: SolisScrape

That should be it.

2 Likes

I’ve installed Appdaemon bu I can’t work out how to install the “requests module”

You go to Settings → Add-ons → Appdaemon into the Configuration tab. Add ‘requests’ to the python packages under options.

Actually, I’m not sure if requests doesn’t come preinstalled with AD anyway.

I’ve managed to get this working thanks.
I have 3 solar arrays all with solis inverters so how would I set this up for 3, I’ve had a go but it didn’t work
Thanks for for help

The easiest way would be to just triple it. Save the script under 3 different names, change IP and login in each script. You’ll also need to change the entity names in each script, else they would overwrite each other.
You’d also have to triple the entries in Apps.yaml. Again, different name for the app and the module (that is the filename without .py). Class is the same for all 3.

Great that’s working!!
Is there a way I can edit the entity for current power to remove the decimal place as my inverter only report full numbers so 100.0w would be 100w.

Replace “float” with “int”. That should do the trick.
My inverter also only does full numbers for current power and total energy, but I decided I would rather reformat that on the output side and keep the floats if I ever would want to process those values for some purpose.

Small edit to the script (I’ll also edit it on the top). Put that in the else branch of “if sun_up”. Then the current power will not be stuck at 20 over night.

        else:   # no sun, no power
            entity = "sensor.solis_current_power"
            self.set_state(entity, state = 0)

GREAT, thanks a lot. 2 out of 3 working OK.
My number 1 is the oldest inverter with the oldest wifi stick model and I have read of people having problems with them locking up so I’ll monitor the other 2 to see how they go.
Oddly No1 its still uploading to the Solis Cloud

Good morning Markus, unfortunately my current power stuck at 20 overnight even though I edited the code as per your instructions but then realised that I had not edited the "sensor.solis_current_power" to "sensor.solis_1_current_power"
BUT I’ve now lost communication with all 3 inverters
2022-09-18 08:17:09.194535 INFO solis_scrape_1: Failed to reach inverter

I’ve worked out what was stopping 1 & 2 working
I’d changed float to int on total_energy like I have done with current_power and it didn’t like it so I’ve now changed it back
Any ideas why I can’t remove the decimal place Markus
3 is still not working even with all 3 scrapes set at float

What do you see in the log file? If the script has an error, it will show up there.

I’m afraid I can’t help you much with ‘Failed to reach inverter’. The script just reads a web page. No fancy JavaScript calls or anything.
You can check the strength of the wireless signal. On my inverter, that is directly on the front page under ‘device information’. I have a signal quality of 66%, and it works fine.

A section from the appdaemon log

2022-09-18 16:59:20.268046 INFO solis_scrape_2: Solis scrape started
2022-09-18 16:59:20.300610 INFO solis_scrape_3: Solis scrape started
2022-09-18 16:59:20.321426 INFO AppDaemon: App initialization complete
2022-09-18 16:59:20.502529 INFO solis_scrape_1: Solis: Current: 50W Today: 1.9kWh Total: 662.0kWh
2022-09-18 16:59:20.527673 INFO solis_scrape_2: Solis: Current: 60W Today: 3.1kWh Total: 1374.0kWh
2022-09-18 16:59:20.621953 INFO solis_scrape_3: Failed to reach inverter
2022-09-18 16:59:20.685687 INFO solis_scrape_1: Solis: Current: 50W Today: 1.9kWh Total: 662.0kWh
2022-09-18 16:59:20.730109 INFO solis_scrape_3: Failed to reach inverter
2022-09-18 16:59:20.732391 INFO solis_scrape_2: Solis: Current: 60W Today: 3.1kWh Total: 1374.0kWh

Do you have any ideas why I can’t remove the decimal place in “Total”
It also appears that if I change a command to something appdaemon does not like I also get a “Failed to reach inverter” error
My no3 system is connected fine to my wifi and uploading to the Solis Cloud

I’ve changed it to int here and got that (also removed the ‘k’ - would be nice, though :slight_smile: )

2022-09-18 18:07:27.965111 INFO solis_scrape: Solis scrape started
2022-09-18 18:07:28.212738 INFO solis_scrape: Solis: Current: 20W Today: 0.2kWh Total: 52.0kWh

before:

2022-09-18 18:06:05.188407 INFO solis_scrape: Solis: Current: 20.0kW Today: 0.2kWh Total: 52.0kWh

That works without problems. Maybe your #3 inverter has a different website and the try: block fails on something else. You could try to run it without try: and see where it fails.
Btw you could run the script from the command line on your computer. Just remove anything HA related and put in print() instead.

Not sure what you mean about that

It’s the “Total” that’s the issue not “Today”

With the ‘k’ I meant, that I put a ‘kW’ behind current power which is, unfortunately, a bit optimistic.

Problem was, that the try: block masked the actual error. It looks like this:

2022-09-18 18:42:30.115800 WARNING solis_scrape: Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/appdaemon/threading.py", line 904, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/config/appdaemon/apps/solisscrape.py", line 35, in update
    total_energy = int(liste[total_e_index+2][1:-2])
ValueError: invalid literal for int() with base 10: '52.0'

Problem is, that you cannot convert ‘52.0’ directly to int. You have to go through float first. So the complete line looks like this:

            total_energy = int(float(liste[total_e_index+2][1:-2]))

Sorry for giving you a bit of wrong advice here. The devils as usual in the detail. The website looks like:

var webdata_now_p = "20";
var webdata_today_e = "0.20";
var webdata_total_e = "52.0";

You see, now_p is already an int, so you can convert directly with int(). But total_e comes as float, so you first have to convert the string to a float with float() and then with int() to int.

Thanks for your continued help Markus, it’s much appreciated.
I’d already changed the kW to W just hadn’t noticed that difference in your before & after
I’m at work now starting a night shift so won’t get an opportunity to try your suggestions until I get home in the morning
Does yours always round the “Current” output to the nearest 10

Yes, and it never goes below 20 even though there is definitely no output.

I noticed my mistake from your output.

This is the “Current Power” element from my inverter that isn’t currently working with Appdaemon

<div class="lab_r2" id="webdata_now_p" style="color:#666666;font-weight:bold;">---</div>

This is the “Current Power” element from 1 of my inverters that is working with Appdaemon

<div class="lab_r2" id="webdata_now_p" style="color:#666666;font-weight:bold;">20 W</div>

I’m hoping you can see the reason!! it’s not working

I’ve noticed the none working 1 does not give numbers to a decimal place like the other 2 inverters, does the code need adjusting for that and the “Current Power” just gives — instead of a number, but strangely it uploads a number to the Solis Cloud

You are on the wrong page. It is ‘/status.html’ that is evaluated. The normal front page uses some JavaScript and is not that easy to parse.