Framing, register map, and discovery for the LuxPower inverter Modbus protocol (HA-free).
Project description
luxmodbus
Framing, register map, and discovery for the LuxPower inverter Modbus protocol.
Report Bug · Request Feature
Table of Contents
About The Project
luxmodbus is a small, dependency-free Python library for the LuxPower
inverter Modbus protocol — packet framing, the declarative register map, and
register discovery. It has no Home Assistant dependency and is the protocol
core consumed by the Lumen Home Assistant
integration. Because it imports nothing from Home Assistant, it can be tested
entirely offline against captured packet bytes.
Status
Early. Implemented so far:
protocol.py— frame encode/decode (LuxPower TCP envelope + inner Modbus RTU data frame), read/write request builders, and read-response unpacking. No I/O, no register-meaning knowledge.registers.py— declarative address → meaning map (the single source of truth) with a decode engine and a bounds-checkedencode_valuefor writes.discovery.py— passive diff-and-log engine: compares observed registers against the known map and records the unknown with a rolling value history.
Getting Started
This project uses uv.
git clone https://github.com/totaldebug/luxmodbus.git
cd luxmodbus
uv sync
uv run nox -s tests
Usage
from luxmodbus import Frame, decode_inputs
frame = Frame.decode(raw_bytes) # validates prefix + CRC
data = frame.data_frame() # inner Modbus frame
# raw register values -> {key: scaled value}
values = decode_inputs({1: 2503, 4: 530, 5: (90 << 8) | 88})
# {"pv1_voltage": 250.3, "battery_voltage": 53.0, "soc": 88, "soh": 90}
The Frame
LuxPower wraps a modified Modbus RTU "data frame" inside a TCP envelope:
prefix(2)=A1 1A | protocol(u16 LE) | frame_length(u16 LE) | reserved(1)=01 |
tcp_function(1) | dongle_serial(10) | data_length(u16 LE) | data_frame(N) | crc16(u16 LE)
frame_length = total_len - 6data_length = len(data_frame) + 2(the trailing CRC)crc16is the standard Modbus CRC (poly0xA001, init0xFFFF) over the data frame, appended little-endian.
The inner data frame:
action(1) | device_function(1) | inverter_serial(10) | register(u16 LE) | value
See docs/capturing-packets.md for how to capture
real packets and turn them into test fixtures.
Provenance
Clean-room: the protocol facts (field layout, CRC algorithm, function codes, register meanings) are taken from the official Lux Power Modbus RTU specification and validated against real packet bytes. No code is copied from other implementations.
Contributing
Contributions are welcome. Please open an issue first to discuss changes, then
ensure uv run nox -s tests passes (style, types, docstring coverage, and the
test suite) before opening a PR.
License
Distributed under the MIT License. See LICENSE for more information.
Project details
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 luxmodbus-0.3.1.tar.gz.
File metadata
- Download URL: luxmodbus-0.3.1.tar.gz
- Upload date:
- Size: 25.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0442bdab1029e922705b8d6701ab96f7ba6c97b47e23ae21b517ca81d7b07fce
|
|
| MD5 |
e93697c1c714ce6692598f507fce3279
|
|
| BLAKE2b-256 |
d71cc1d6a5cc9505cb84f6262b228268500873b5e3ded0785f00cd4162e6c221
|
File details
Details for the file luxmodbus-0.3.1-py3-none-any.whl.
File metadata
- Download URL: luxmodbus-0.3.1-py3-none-any.whl
- Upload date:
- Size: 27.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd861574f76cf608220cce8a89ef8135de78fa2aaaf45f0d8ecd65b643b289ad
|
|
| MD5 |
716a9012e07dd069527d8044e980094a
|
|
| BLAKE2b-256 |
07c28508d48281890b5caaa58a1b5e7b6cdd27d254784a39ace0a959e2d5f606
|