growatt-protocol
The protocol a Growatt datalogger speaks to its server over TCP 5279, as a standalone Python library. Framing, obfuscation, checksums, record decoding, register semantics, and the commands for reading and writing inverter registers.
No dependencies. Standard library only, no compiled extension, so it installs anywhere Python runs. A test walks the source and fails on any import outside the standard library, so that stays true.
pip install growatt-protocol
Records are self-describing
The useful thing about this protocol, and the reason this library is small: a telemetry record states the Modbus register ranges it carries.
datalogger serial | inverter serial | timestamp | group count | group…
group := start register (2B) | end register (2B) | one 16-bit word per register
So decoding reads register numbers off the wire rather than indexing a per-model table of byte offsets. That is what lets a handful of register profiles replace the dozens of model-specific layout files other implementations need, and it means a malformed record fails loudly instead of decoding into plausible-looking nonsense.
Decoding a record
from growatt_protocol import Frame, Framer, parse_register_record
from growatt_protocol.registers import decode_registers, resolve_profile
framer = Framer() # TCP splits and coalesces; reassembly is required
for raw in framer.feed(chunk):
payload = parse_register_record(Frame(raw))
match = resolve_profile([(g.start, g.end) for g in payload.groups])
decoded = decode_registers(match.profile, payload.registers)
print(payload.inverter_serial, decoded.values["output_power"], "W")
Register meaning varies by inverter family — register 13 is PV3 power under one
protocol, grid frequency under another, battery charge power on an off-grid unit — but
the group range identifies the block, so resolve_profile picks the right one from the
record itself. The exception is the off-grid SPF series, whose 0-based block is
indistinguishable from Protocol II; that one has to be passed as an override.
Running a server
import asyncio
from growatt_protocol import GrowattServer, ServerConfig
def on_record(record):
print(record.payload.inverter_serial, record.payload.registers)
async def main():
server = GrowattServer(ServerConfig(port=5279), on_record=on_record)
await server.start()
await asyncio.Event().wait()
asyncio.run(main())
The server answers what a datalogger expects: acknowledgements before decoding, ping echoes, and — importantly — a clock update after the device announces itself. Without that last one a datalogger announces, waits, gives up and reconnects forever, never sending a single telemetry record.
Testing without hardware
from growatt_protocol.testing import FakeDatalogger
device = FakeDatalogger(chunk_size=1) # one byte per write, to prove reassembly
await device.connect("127.0.0.1", server.port)
await device.send_data()
FakeUpstream stands in for the Growatt cloud, and can be killed mid-session to exercise
relay fallback.
License
MIT, except the register definitions under registers/, which are Apache-2.0 and derived
from
Homeassistant-Growatt-Local-Modbus.
See NOTICE. This project is not derived from johanmeijer/grott, which carries no
license; full provenance is recorded in the
repository.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file growatt_protocol-0.6.0.tar.gz.
File metadata
- Download URL: growatt_protocol-0.6.0.tar.gz
- Upload date:
- Size: 75.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a11920e98de1bb4069c7dd6a65abb7b8925b80bd94e086d878e387d001255442
|
|
| MD5 |
875e55c0835a5e3739d992bd0a4a1a22
|
|
| BLAKE2b-256 |
69aef90fbae83d93002b3ae0958fdfcd0105ae5787d32ae63bc3f8cc12a212e5
|
Provenance
The following attestation bundles were made for growatt_protocol-0.6.0.tar.gz:
Publisher:
publish.yml on FezVrasta/growatt-datalogger
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
growatt_protocol-0.6.0.tar.gz -
Subject digest:
a11920e98de1bb4069c7dd6a65abb7b8925b80bd94e086d878e387d001255442 - Sigstore transparency entry: 2742659627
- Sigstore integration time:
-
Permalink:
FezVrasta/growatt-datalogger@3a30fb37015e0f2e80e7873e8ba443bd4eccde07 -
Branch / Tag:
refs/tags/growatt-protocol-v0.6.0 - Owner: https://github.com/FezVrasta
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3a30fb37015e0f2e80e7873e8ba443bd4eccde07 -
Trigger Event:
push
-
Statement type:
File details
Details for the file growatt_protocol-0.6.0-py3-none-any.whl.
File metadata
- Download URL: growatt_protocol-0.6.0-py3-none-any.whl
- Upload date:
- Size: 68.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60681961bff1b309470b06d95ca7012e2c0b85073d7be4296a51c32804811c8b
|
|
| MD5 |
e06aa04362a7b3140a0acb5b1e258b39
|
|
| BLAKE2b-256 |
f38669dd8afc386826345421aa8ff164d5665904fbabc5269355fac10b71dbe0
|
Provenance
The following attestation bundles were made for growatt_protocol-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on FezVrasta/growatt-datalogger
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
growatt_protocol-0.6.0-py3-none-any.whl -
Subject digest:
60681961bff1b309470b06d95ca7012e2c0b85073d7be4296a51c32804811c8b - Sigstore transparency entry: 2742659692
- Sigstore integration time:
-
Permalink:
FezVrasta/growatt-datalogger@3a30fb37015e0f2e80e7873e8ba443bd4eccde07 -
Branch / Tag:
refs/tags/growatt-protocol-v0.6.0 - Owner: https://github.com/FezVrasta
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3a30fb37015e0f2e80e7873e8ba443bd4eccde07 -
Trigger Event:
push
-
Statement type: