Coder Social home page Coder Social logo

dewet22 / givenergy-modbus Goto Github PK

View Code? Open in Web Editor NEW
19.0 7.0 15.0 1.04 MB

A python library to access GivEnergy inverters via Modbus TCP on a local network, with no dependency on the GivEnergy Cloud.

License: Other

Python 99.83% Makefile 0.17%
energy inverter-control modbus python energy-monitoring local polling

givenergy-modbus's People

Contributors

britkat1980 avatar dependabot[bot] avatar dewet22 avatar dominic-kua avatar holdestmade avatar jakekeeys avatar

Stargazers

 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  avatar

givenergy-modbus's Issues

Do not set battery_soc_reserve as part of set_mode_storage

Feature request:

When used with a Gen2 Inverter : Setting battery_soc_reserve to 100 stops any discharge. Can this be removed from set_mode_storage ? Currently calling set_mode_storage for either Timed Export/Disharge on gen2 effectively disables the battery from discharge.

def set_mode_storage()
........
 ret.extend(set_shallow_charge(100))  # r110=100

I dont think that the portal or app set this value when Timed Discharge or Timed Export is selected. Is it needed for Gen1 firmware ?

Intermittent results when querying the Inverters

  • GivEnergy Modbus version: givenergy-modbus-0.10.1
  • Python version: 3.11
  • Operating System: MacOS 12.6.2

Description

Describe what you were trying to get done.

Run this simple python script in PyCharm IDE to grab the battery and inverter info. Would just expect a clean exit

import json
import logging
import datetime
import time
from givenergy_modbus.client import GivEnergyClient
from givenergy_modbus.model.inverter import Model
from givenergy_modbus.model.battery import Battery
from givenergy_modbus.model.plant import Plant
from os.path import exists
import os

client = GivEnergyClient(host='192.168.0.70')

p = Plant(number_batteries=1)

client.refresh_plant(p, full_refresh=True)
GEInv = p.inverter
GEBat = p.batteries

Tell us what happened, what went wrong, and what you expected to happen.

Sometimes it works and sometimes it doesn't, it's completely random.

When it works it exits cleanly (and if I add the code to print out an inverter or battery setting, it prints the correct value)

When it fails I see this

Did not receive expected response type: ReadHoldingRegistersResponse != ReadInputRegistersResponse
Returned base register (0) does not match that from request (60).
Traceback (most recent call last):
File "/Users/richard/PycharmProjects/pythonProject3/venv/giv.py", line 17, in
GEInv = p.inverter
^^^^^^^^^^
File "/Users/richard/PycharmProjects/pythonProject3/venv/lib/python3.11/site-packages/givenergy_modbus/model/plant.py", line 32, in inverter
return Inverter.from_orm(self.inverter_rc)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "pydantic/main.py", line 578, in pydantic.main.BaseModel.from_orm
File "pydantic/main.py", line 1056, in pydantic.main.validate_model
File "/Users/richard/PycharmProjects/pythonProject3/venv/lib/python3.11/site-packages/givenergy_modbus/model/register_getter.py", line 69, in get
return getattr(self._obj, key, default)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/richard/PycharmProjects/pythonProject3/venv/lib/python3.11/site-packages/givenergy_modbus/model/register_cache.py", line 26, in getattr
val = self[register]
~~~~^^^^^^^^^^
KeyError: HR:120

The ability to query the inverters and batteries directly in this way is very interesting to us, so I'd love to get this working and stable if I can

Wondering if it could be poor comms quality as our 3 inverters have wifi dongles for connectivity.

Querying inverter fails with ValueError: hour must be in 0..23

  • GivEnergy Modbus version: 0.10.1
  • Python version: 3.10.2
  • Operating System: Manjaro Linux

Description

I was trying to query my Giv-AC 3.0 but the code fails

What I Did

This is my test code

from givenergy_modbus.client import GivEnergyClient
from givenergy_modbus.model.plant import Plant

client = GivEnergyClient(host="192.168.99.99")

p = Plant(number_batteries=1)
client.refresh_plant(p, full_refresh=True)

print(p.inverter.json())

and it fails with the following error

Traceback (most recent call last):
  File "/home/martin/test/./test.py", line 8, in <module>
    print(p.inverter.json())
  File "/home/martin/test/.env/lib/python3.10/site-packages/givenergy_modbus/model/plant.py", line 32, in inverter
    return Inverter.from_orm(self.inverter_rc)
  File "pydantic/main.py", line 562, in pydantic.main.BaseModel.from_orm
  File "pydantic/main.py", line 1001, in pydantic.main.validate_model
  File "/home/martin/test/.env/lib/python3.10/site-packages/givenergy_modbus/model/register_getter.py", line 61, in get
    return self.get(f'{key}_start'), self.get(f'{key}_end')
  File "/home/martin/test/.env/lib/python3.10/site-packages/givenergy_modbus/model/register_getter.py", line 69, in get
    return getattr(self._obj, key, default)
  File "/home/martin/test/.env/lib/python3.10/site-packages/givenergy_modbus/model/register_cache.py", line 27, in __getattr__
    return register.convert(val)
  File "/home/martin/test/.env/lib/python3.10/site-packages/givenergy_modbus/model/register.py", line 155, in convert
    return self.type.convert(val, self.scaling.value)
  File "/home/martin/test/.env/lib/python3.10/site-packages/givenergy_modbus/model/register.py", line 49, in convert
    return time(hour=int(f'{value:04}'[:2]), minute=int(f'{value:04}'[2:]) % 60)
ValueError: hour must be in 0..23

After some debug it seems discharge_slot_1 end time is 2400. As a work around i added the following to givenergy_modbus/model/register.py when handling time

if value >= 2400:
  value = 0

This fixed the issues and i can now query the inverter. All the other values look correct.

pymodbus 3.x support

Description

I'm using givenergy-local integration in Home Assistant, which uses this library. I also use home-assistant-solaredge-modbus integration to monitor my Solaredge inverter.

The Solaredge integration (and the -multi one as well) uses pymodbus >= 3.1.1. Is there any chance to upgrade this project to use a more modern version of pymodbus (currently ^2.5.3)?

Thanks.

Unable to connect to the new All In One

  • GivEnergy Modbus version: Downloaded today 9th June
  • Python version: 3.11
  • Operating System: Windows 11

Description

Unable to connect to the All In One on GivTCP, or directly from Windows

What I Did

givenergy-modbus -h 192.168.0.8 dump-registers -b 2
To assist Mark Cracknall

Result from AIO attached, compared to the AC3 on the same network

AC3 response.txt
AIO response.txt

CLI failing - latest version

  • GivEnergy Modbus version: head
  • Python version: 3.10.8
  • Operating System: MAC, Monterey + Brew

Description

I'm trying to get the latest version to work, tried to CLI but it seems not to work with the API, see below.

What I Did

treforsouthwell@Trefors-MacBook-Pro-2 givenergy-modbus % python3 givenergy_modbus/cli.py -h 192.168.0.141 dump-registers
Traceback (most recent call last):
File "/Users/treforsouthwell/Library/CloudStorage/OneDrive-Personal/Code/givenergy/givenergy-modbus/givenergy_modbus/cli.py", line 184, in
main(obj={}) # pragma: no cover
File "/Users/treforsouthwell/homebrew/lib/python3.10/site-packages/click/core.py", line 1130, in call
return self.main(*args, **kwargs)
File "/Users/treforsouthwell/homebrew/lib/python3.10/site-packages/click/core.py", line 1055, in main
rv = self.invoke(ctx)
File "/Users/treforsouthwell/homebrew/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/Users/treforsouthwell/homebrew/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/Users/treforsouthwell/homebrew/lib/python3.10/site-packages/click/core.py", line 760, in invoke
return __callback(*args, **kwargs)
File "/Users/treforsouthwell/homebrew/lib/python3.10/site-packages/click/decorators.py", line 26, in new_func
return f(get_current_context(), *args, **kwargs)
File "/Users/treforsouthwell/Library/CloudStorage/OneDrive-Personal/Code/givenergy/givenergy-modbus/givenergy_modbus/cli.py", line 71, in dump_registers
ctx.obj['CLIENT'].refresh_plant(plant=plant, full_refresh=True)
AttributeError: 'Coordinator' object has no attribute 'refresh_plant'. Did you mean: 'refresh_count'?

Cannot determine model number from serial number

When trying to retrieve information about my inverter I get the error:

Traceback (most recent call last):
File "/config/custom_components/givenergy_local/config_flow.py", line 48, in async_step_user
serial_no = await read_inverter_serial(self.hass, user_input)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/config/custom_components/givenergy_local/config_flow.py", line 27, in read_inverter_serial
serial_no: str = plant.inverter.inverter_serial_number
^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/givenergy_modbus/model/plant.py", line 32, in inverter
return Inverter.from_orm(self.inverter_rc)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "pydantic/main.py", line 577, in pydantic.main.BaseModel.from_orm
File "pydantic/main.py", line 1102, in pydantic.main.validate_model
File "/usr/local/lib/python3.11/site-packages/givenergy_modbus/model/inverter.py", line 212, in compute_model
values['inverter_model'] = Model.from_serial_number(values['inverter_serial_number'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/givenergy_modbus/model/inverter.py", line 39, in from_serial_number
raise UnknownModelError(f"Cannot determine model number from serial number {serial_number}")
givenergy_modbus.model.inverter.UnknownModelError: Cannot determine model number from serial number FA2308****

All information from the battery is able to be received correctly without error.

Thank you in advance.

Addition to README

The README has lots of good examples of how to set registers, but would it be possible to add an example showing how to query.

Need a fresh release

This code is in use in another givenergy integration, which is broken for us due to the missing serial number prefix. Apparently the other integration requires a release on this in order to use the fix which my partner submitted (01224c7) which has been merged.

Its been over a year since a new version was released. Could one be done?
Thanks.

FYI prometheus-givenergy

Dewet,

Based on your great work I built https://github.com/barry-scott/prometheus-givenergy that uses the current version pymodbus to implement a prometheus exporter for GivEnergy.

I did this because I found that updating givenergy-modbus code to the latest version of dependencies was difficult. In part because I am not familiar with some of the libraries you are using and in part because pymodbus V3 API is not compatible with pymodbus V2 API.

I have credited you in the readme for prometheus-givenergy.

Thanks for releasing this project and the documentation in framer.py that has been very helpful.

Barry
[email protected]

missing model from model.inverter

  • GivEnergy Modbus version:
  • Python version:
  • Operating System:

Description

Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.

What I Did

import datetime
import json
from givenergy_modbus.client import GivEnergyClient
from givenergy_modbus.model.inverter import Model
from givenergy_modbus.model.plant import Plant

client = GivEnergyClient(host="192.168.1.xx")

p = Plant(number_batteries=1)
client.refresh_plant(p, full_refresh=True)

data = json.loads(p.inverter.json())

print(data)
####What happened
givenergy_modbus.model.inverter.UnknownModelError:
Cannot determine model number from serial number EA230XXXX
'EA': cls.Gen2 is missing from the inverter list can it be added please.

Serial number cannot be decoded on a 5.0 Gen 2 inverter

  • GivEnergy Modbus version: 0.10.1
  • Python version: 3.9, 3.10

Description

I am using the library as part of a Home Assistant integration. I've been working with someone who has a 5.0 Gen 2 inverter, and is unable to get my integration working.

The root cause appears to be in the serial number to model decoding function.

What I Did

The following script has been used to debug the issue:
https://github.com/cdpuk/givenergy-local/blob/master/scripts/debug.py

We can successfully read the registers and print details with plant.inverter_rc, however decoding the values fails as the registers that would normally hold the serial number seem to hold other data.

Traceback (most recent call last):
  File "U:\debug.py", line 68, in <module>
    main()
  File "U:\debug.py", line 64, in main
    debugger.display_decoded_data()
  File "U:\debug.py", line 45, in display_decoded_data
    print(self.plant.inverter.json(indent=2))
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\givenergy_modbus\model\plant.py", line 32, in inverter
    return Inverter.from_orm(self.inverter_rc)
  File "pydantic\main.py", line 562, in pydantic.main.BaseModel.from_orm
  File "pydantic\main.py", line 1048, in pydantic.main.validate_model
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\givenergy_modbus\model\inverter.py", line 212, in compute_model
    values['inverter_model'] = Model.from_serial_number(values['inverter_serial_number'])
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\givenergy_modbus\model\inverter.py", line 39, in from_serial_number
    raise UnknownModelError(f"Cannot determine model number from serial number {serial_number}")
givenergy_modbus.model.inverter.UnknownModelError: Cannot determine model number from serial number  D 1 1 0 2

Patching the library such that it returns an "Unknown" model when decoding fails gets everything working. All other decoded values appear correctly. I was unable to identify another set of registers that hold the serial number in the expected format.

I have the complete output from this script, including all register values, if required.

The "Unknown" approach certainly seems most straightforward, but I appreciate there may be other reasons to raise instead.

It's worth noting that the log messages contain the correct serial number (from the underlying modbus library?). Perhaps this would be a more reliable source for the serial number property.

givenergy_modbus INFO Decoded response 4/ReadInputRegistersResponse({check: 0xe55a, inverter_serial_number: EDnnnnnnnn, base_register: 0x0000, register_count: 0x003c, data_adapter_serial_number: WGnnnnnnnn, padding: 0x008a, slave_address: 0x0032})

GivEnergyClient missing from code?

  • GivEnergy Modbus version: N/A
  • Python version: N/A
  • Operating System: N/A

Description

Describe what you were trying to get done.
Fork or download the code

Tell us what happened, what went wrong, and what you expected to happen.
The downloaded or forked code is not the same as that installed by pip install.

This is probably my ignorance of github but the code here does not seem complete and is structured differently to the pip install givenergy-modbus code
E.g. the main class is GivEnergyClient but I can't find it anywhere in the code...

This is a great project and I have a couple of minor mods I would like to contribute.

Thanks
Mike

'Coordinator' object has no attribute 'refresh_plant'

  • GivEnergy Modbus version: 75e7ab7
  • Python version: Python 3.8.9
  • Operating System: MacOS 12.5

Description

The dump-registers command fails to run.

The refresh_plant member function seems to have been removed in 1180ce1.

What I Did

python3 cli.py --host "192.168.1.188" dump-registers --batteries 2

Traceback (most recent call last):
  File "cli.py", line 184, in <module>
    main(obj={})  # pragma: no cover
(...)
  File "cli.py", line 71, in dump_registers
    ctx.obj['CLIENT'].refresh_plant(plant=plant, full_refresh=True)
AttributeError: 'Coordinator' object has no attribute 'refresh_plant'

Example for async client

Could you provide an example of how to use the new client structure? The original client.py file has gone, and I'd like to bring the async capability into GivTCP.

Hybrid Gen3 Serial Number not recognised (FA*******)

  • GivEnergy Modbus version: 0.10.1
  • Python version: 3.11
  • Operating System: HAOS

Description

Trying to use the HA GivEnergy local package from HACS
(https://github.com/cdpuk/givenergy-local)

What I Did

Input Inverter IP in the Config Wizard, which failed with the following in the logs

Failed to validate inverter configuration
Traceback (most recent call last):
File "/config/custom_components/givenergy_local/config_flow.py", line 48, in async_step_user
serial_no = await read_inverter_serial(self.hass, user_input)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/config/custom_components/givenergy_local/config_flow.py", line 27, in read_inverter_serial
serial_no: str = plant.inverter.inverter_serial_number
^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/givenergy_modbus/model/plant.py", line 32, in inverter
return Inverter.from_orm(self.inverter_rc)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/pydantic/main.py", line 577, in from_orm
values, fields_set, validation_error = validate_model(cls, obj)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/pydantic/main.py", line 1102, in validate_model
values = validator(cls_, values)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/givenergy_modbus/model/inverter.py", line 212, in compute_model
values['inverter_model'] = Model.from_serial_number(values['inverter_serial_number'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/givenergy_modbus/model/inverter.py", line 39, in from_serial_number
raise UnknownModelError(f"Cannot determine model number from serial number {serial_number}")
givenergy_modbus.model.inverter.UnknownModelError: Cannot determine model number from serial number FA

Individual start and end time control

Could v1.0 allow individual setting of start and end times for timeslots rather than just both together.
This is useful for automations and manual control in HA through GivTCP.
It would prevent some race conditions when trying to set a single start or end slot.

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.