Giter VIP home page Giter VIP logo

pygoodwe's Introduction

pygoodwe

A command line tool and python library to query the GOODWE SEMS Portal APIs.

API Docs

Auto-generated documentation is here: https://yaleman.github.io/pygoodwe/

Installation

You need to have Python 3 and pip installed. Then:

python -m pip install pygoodwe

Determine the Station ID from the GOODWE site as follows. Open the Sems Portal. The Plant Status will reveal the Station ID in the URL. Example:

https://www.semsportal.com/powerstation/powerstatussnmin/11112222-aaaa-bbbb-cccc-ddddeeeeeffff

Then the Station ID is 11112222-aaaa-bbbb-cccc-ddddeeeeeffff.

To use example.py or the other examples, copy config.py.example to config.py and add your details.

Contributions

Please feel free to lodge an issue or pull request on GitHub.

Thanks

Disclaimer

GOODWE access is based on the undocumented API used by mobile apps. This could break at any time.

Example Code

Please check out example.py or the examples folder in the project repository for some simple example code.

pygoodwe's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar jb1985 avatar nelsbrock avatar tywjohn avatar verthezp avatar yaleman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pygoodwe's Issues

API logs me out on my iPhone

When I use the API to fetch data from the SEMS portal, it logs me out from my iPhone app and I need to log back in. This happens whenever the data is fetched (so roughly every 30 seconds) so it is very annoying. Is there a way around this? Thanks!

When no inverters, it doesn't fail gracefully

It should probably just raise a simpler error than "ugh, die".

2019-10-10 07:17:42,774 Failed to call GoodWe API
Traceback (most recent call last):
  File "/usr/local/bin/goodwe2pvoutput", line 69, in <module>
    do_the_thing()
  File "/usr/local/bin/goodwe2pvoutput", line 55, in do_the_thing
    password=CONFIG.get('goodwe', 'password')
  File "/usr/local/lib/python3.7/dist-packages/pygoodwe/__init__.py", line 338, in __init__
    super().__init__(system_id, account, password, skipload)
  File "/usr/local/lib/python3.7/dist-packages/pygoodwe/__init__.py", line 105, in __init__
    self.getCurrentReadings(raw=True)
  File "/usr/local/lib/python3.7/dist-packages/pygoodwe/__init__.py", line 351, in getCurrentReadin
    if len(self.data['inverter']):
KeyError: 'inverter'

GoodWe rate limit question (got IP banned)

I had been using it for a while to fetch data from my solar panels, and after a couple months my IP got banned. The app didn't work on my home network and the inverter was not able to send out data. I had fixed it by tunneling all GoodWe data through a VPN via my router, and after about a year my IP-ban got removed. But I digress.

Have you had any experience with, or is there any documentation on GoodWe's rate limit? I was polling their API 12 times per hour, with 5 minute intervals. I want to use this project again to act as a bridge between my GoodWe solar inverter and a MQTT broker, and I will probably fetch the data once every 30 minutes, and only between certain times when the sun is out as a safety measure.

Arguments not propagated in SingleInverter.get_current_readings

The arguments passed to SingleInverter.get_current_readings:

def get_current_readings(

are not forwarded to API.get_current_readings. When the number of maxretries is set to 1, it's still 5 due to the default value of 5 in API.get_current_readings. Also the recursive call should not happen in SingleInverter.get_current_readings as it already happens in API.get_current_readings.

Furthermore, the function should return data, but it returns retval set to None.

This is what the function should imho look like:

 def get_current_readings(
        self,
        raw: bool=True,
        retry: int=1,
        maxretries: int=5,
        delay: int=30,
        ) -> Any:
        """ grabs the data and makes sure self.data only has a single inverter """
        # update the data
        super().get_current_readings(raw, retry, maxretries, delay)
        # reduce self.data['inverter'] to a single dict from a list
        
        if self.data.get("inverter"):
            self.data["inverter"] = self.data["inverter"][0]
        return self.data

How to handle multiple inverters?

I now have 2 Goodwe inverters, and would like to be able to pull data for both. How can I achieve this? I would like to dump all data to JSON (I currently useprint(json.dumps(gw.data), file=f)

It seems that the used URL no longer seems to be available from the command line

When I try to readout some values using your library, I keep getting the following response:

ERROR:root:RequestException: 403 Client Error: Forbidden for url: https://semsportal.com/api/v1/PowerStation/GetMonitorDetailByPowerstationId
ERROR:root:RequestException: 403 Client Error: Forbidden for url: https://semsportal.com/api/v1/PowerStation/GetMonitorDetailByPowerstationId
ERROR:root:Failed to call GoodWe API url='https://semsportal.com/api/v1/PowerStation/GetMonitorDetailByPowerstationId'

I have been using it successfully for quite a while now, but recently it stopped working. Do you have any idea how to solve this? Or am I doing something wrong?

Data issues with multiple inverters

I will first explain my setup, and then the problems I am facing.

  1. GoodWe GW5048-EM Hybrid Inverter with an eSTORE 10.3kWh LiFePO4 battery attached with 6.1kW of PV (Inverter 1)
  2. GoodWe GW5048-EM Hybrid Inverter with with 6.6kW of PV and NO BATTERY attached. (Inverter 2)

To be clear, I think most of these may be issues with the portal, NOT your code, but I will mention it all here just in case.

When I was using just the first inverter, things were fine. Data being read was accurate. Adding the 2nd inverter to the mix made things a complete mess. Here are some of the issues:

  1. SOC instantly halved (Inverter 1 SOC at 80%, Inverter 2 SOC at 0%) SEMS displays 40% SOC... even if its aware there is no battery on the 2nd inverter.
  2. Power that I BUY from the grid is also doubled (I think the 'smart meters' are both measuring the same power coming into the property, and SEMS adds them together.. So if I am drawing 700W from the grid, its counted by both smart meters are shows 1400W)
  3. With just Inverter 1 connected "SelfUseOfPV" used to include the power put into the battery.. this no longer seems to be the case, as sometimes I will have charged the battery from 10% to 100%, yet "SelfUseOfPV" is only 3kWh for the day (this is completely wrong.. it would be more like 15-20kWh)
  4. Sometimes the portal shows the LOAD as something like 17W (as in the house is drawing 17w.. this is obviously incorrect)
  5. Sometimes the portal shows I am EXPORTING/SELLING more than my PV is generating, even whilst still charging the battery, and feeding the LOAD of the house.. eg, PV is generating 10kW, battery is charging at 2.6kW, load is 1kW, exporting/selling 12kW..

Im sure there are more issues, but it seems that the SEMS Portal is NOT a reliable source at all currently. I will be discussing this with GoodWe tomorrow, but do not have high hopes of them quickly fixing these issues.

Do you know if there is a way to get data directly from the inverter itself? I used to use RS485->USB on my old ABB/PowerOne inverter.

API Access

Hi, got this error since yesterday:

WARNING:root:HTTPSConnectionPool(host='globalapi.sems.com.cn', port=443): Max retries exceeded with url: /api/v1/PowerStation/GetMonitorDetailByPowerstationId (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1108)')))

Could change the global_url to : 'https://semsportal.com:443/api/'
or add an option to switch between the 2 or try the 1 url then the other?

Problem with API

since march i can't get this api working.

Is this API still working?

Errors running example.py

I'm trying to run the example.py.. I've set up my details in config.py and I can see that is coming through.

Apologies if this is something obvious (I'm new to python), but it fails with this output:

`Single Inverter
ERROR:root:<RequestsCookieJar[]>
ERROR:root:Done login, token: {"uid": "dd8c67fc-5fc2-4080-a8bd-6bec7f38744d", "timestamp": 1672275548366, "token": "79bda1384c81bb66878184fc4132952e", "client": "ios", "version": "v2.0.4", "language": "en"}

dict_keys(['info', 'kpi', 'powercontrol_status', 'images', 'weather', 'inverter', 'hjgx', 'homKit', 'isTigo', 'tigoIntervalTimeMinute', 'smuggleInfo', 'hasPowerflow', 'powerflow', 'hasGridLoad', 'isParallelInventers', 'isEvCharge', 'evCharge', 'hasEnergeStatisticsCharts', 'energeStatisticsCharts', 'energeStatisticsTotals', 'soc', 'environmental', 'equipment'])
"0V/0A/0W"
Battery voltage is: 0.0
Getting XLS file
ERROR:root:payload: {'str': '{"api": "v2/PowerStation/ExportPowerstationPac", "param": {"date": "2022-12-28", "pw_id": "66b874d7-9758-48bb-baa2-742d60c301c4", "img_base64": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+P///38ACfsD/QVDRcoAAAAASUVORK5CYII=", "img_width": 1, "img_height": 1, "is_removesoc": 0}}'}
ERROR:root:Failed to pull from https://au.semsportal.com/GopsApi/Post - response - {'language': 'zh_CN', 'function': None, 'hasError': True, 'msg': 'ver is not fund', 'code': 'UnknownVer', 'data': None, 'components': {'para': None, 'langVer': 176, 'timeSpan': 0, 'api': None, 'msgSocketAdr': None}}`

Calls seem to fail when PV flow is 0

I noticed at night when there is no generation, I don't even get data for other things like inverter temperature or voltage etc.
I have yet to investigate further. Unsure if this is the API returning no data when there is no generation or whether it is pygoodwe not handling it properly.

Explanation request

Hello,
Can you add a ReadMe with more information about this PyGoodWe?
How can you use it. How to get the information of the power station?
Functions like GetCurrentGeneration() or something like that.

data["v4"] = self.getLoadFlow()[0] results in Float object is not subscriptable error

Hey, I noticed that the function GetDataPvOutput() results in float object is not subscriptable error because of the following lines:

data["v4"] = self.getLoadFlow()[0] # power consumption
data["v5"] = self.get_inverter_temperature()[0] # inverter temperature
data["v6"] = self.getVoltage()[0] # voltage

After removing the list indices of [0] it works fine given that getLoadFlow returns a single float rather than a list.

New code:

data["v4"] = self.getLoadFlow() # power consumption
data["v5"] = self.get_inverter_temperature() # inverter temperature
data["v6"] = self.getVoltage() # voltage

Errors by testing pygoodwe import in IoBroker

I want import my Goodwe SEMS Data in IoBroker, so I used the work from https://forum.iobroker.net/topic/34626/goodwe-wechselrichter-und-iobroker. When im tested it following problem comes up. Im no specialist in python Syntax.

pi@Raspberry-Pi4:~ $ python /home/pi/pygoodwe-master/test.py
Traceback (most recent call last):
  File "/home/pi/pygoodwe-master/test.py", line 5, in <module>
    from pygoodwe import SingleInverter, API
  File "/home/pi/pygoodwe-master/pygoodwe/__init__.py", line 19
    def __init__(self, system_id: str, account: str, password: str, **kwargs):
                                ^
SyntaxError: invalid syntax

I imported the master and moving the config.py.example to config.py and enter data.

Can anyone help me to use the Script?

test_pygoodwe.py

Hi, thank you for your libary. I tried to install it, but when I run test_pygoodwe.py I only get the message:

test_pygoodwe.py::test_instantiate SKIPPED (Could not find data file 'testdata.json') [ 12%]
Skipped: Could not find data file 'testdata.json'

and so on for all the data. Can you may help me.
Have a nice Day!

How to use it?

Hello,

I have a Goodwe hybrid inverter and want to use your pygoodwe. But I dont know how to use it?!

Can you please write a little HowTo?

failed requests

Hi there
wondering if anyone else experienced issues with grabbing data.
everything worked fine for me for arround 9 monts, but since start of december its not working anymore and i keep getting these errors:

ERROR:root:RequestException: 403 Client Error: Forbidden for url: https://semsportal.com/api/v1/PowerStation/GetMonitorDetailByPowerstationId
ERROR:root:Failed to call GoodWe API url='https://semsportal.com/api/v1/PowerStation/GetMonitorDetailByPowerstationId'

seems to me like there has been some changes somewhere from SEMS side
anyone else experiencing this?

BR, Cravvler

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.