https://github.com/dewet22/givenergy-modbus
A python library to access GivEnergy inverters via Modbus TCP on a local network, with no dependency on the GivEnergy Cloud.
https://github.com/dewet22/givenergy-modbus
energy energy-monitoring inverter-control local modbus polling python
Last synced: about 1 month ago
JSON representation
A python library to access GivEnergy inverters via Modbus TCP on a local network, with no dependency on the GivEnergy Cloud.
- Host: GitHub
- URL: https://github.com/dewet22/givenergy-modbus
- Owner: dewet22
- License: other
- Created: 2022-01-03T12:56:28.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2026-05-27T00:43:34.000Z (about 1 month ago)
- Last Synced: 2026-05-27T01:13:12.661Z (about 1 month ago)
- Topics: energy, energy-monitoring, inverter-control, local, modbus, polling, python
- Language: Python
- Homepage: https://dewet22.github.io/givenergy-modbus/
- Size: 2.66 MB
- Stars: 25
- Watchers: 6
- Forks: 17
- Open Issues: 16
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# GivEnergy Modbus

[](https://pypi.org/project/givenergy-modbus/)
[](https://pypi.org/project/givenergy-modbus/)
[](https://github.com/dewet22/givenergy-modbus/actions?query=branch%3Amain)
[](https://codecov.io/github/dewet22/givenergy-modbus)
[](LICENSE)
[](https://github.com/astral-sh/ruff)
A Python library for communicating with GivEnergy inverters via Modbus TCP on a local network, with no dependency on the GivEnergy Cloud. Inspired by and originally built on [pymodbus](https://pymodbus.readthedocs.io/), it now provides its own asyncio-based framer, decoder and PDUs specific to the GivEnergy implementation.
> ⚠️ This project makes no representations as to its completeness or correctness. You use it at your own risk — if your
> inverter mysteriously explodes because you accidentally set the `BOOMTIME` register or you consume a MWh of
> electricity doing SOC calibration: you **really** are on your own. We make every effort to prevent you from shooting
> yourself in the foot, so as long as you use the client and its exposed methods, you should be perfectly safe.
* Documentation:
* GitHub:
* PyPI:
* Free software: Apache-2.0
## Features
* Reading all registers and decoding them into their representative datatypes
* Writing data to holding registers that are deemed to be safe to set configuration on the inverter
## How to use
The client is async. Use it inside an `asyncio` event loop; commands are plain functions that return request lists
which you send via `one_shot_command` or `execute`:
```python
import asyncio
from givenergy_modbus.client.client import Client
from givenergy_modbus.client import commands
from givenergy_modbus.model import TimeSlot
from givenergy_modbus.model.inverter import Model
async def main():
client = Client(host="192.168.99.99", port=8899)
await client.connect()
# Read current state first (needed for slot_map)
await client.refresh_plant(full_refresh=True)
plant = client.plant
# Write configuration to the device
await client.one_shot_command(commands.set_charge_target(80))
# set a charging slot from 00:30 to 04:30; slot_map selects correct registers for this model
await client.one_shot_command(
commands.set_charge_slot(1, TimeSlot.from_components(0, 30, 4, 30), plant.inverter.slot_map)
)
# set the inverter to charge from excess solar and discharge to meet demand
await client.one_shot_command(commands.set_mode_dynamic())
assert plant.inverter_serial_number == 'SA1234G567'
assert plant.inverter.model == Model.HYBRID
assert plant.inverter.enable_charge_target
assert plant.inverter.charge_slot_1 == TimeSlot.from_components(0, 30, 4, 30)
assert plant.inverter.model_dump() == {
'serial_number': 'SA1234G567',
'device_type_code': '3001',
'charge_slot_1': TimeSlot.from_components(0, 30, 4, 30),
...
}
assert plant.inverter.model_dump_json() == '{"serial_number": "SA1234G567", "device_type_code": "3001", ...'
assert plant.batteries[0].serial_number == 'BG1234G567'
assert plant.batteries[0].v_cell_01 == 3.117
assert plant.batteries[0].model_dump() == {
'bms_firmware_version': 3005,
'cap_design': 160.0,
...
}
assert plant.batteries[0].model_dump_json() == '{"serial_number": "BG1234G567", "v_cell_01": 3.117, ...'
await client.close()
asyncio.run(main())
```
## Credits
This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) and
the [waynerv/cookiecutter-pypackage](https://github.com/waynerv/cookiecutter-pypackage) project template.