Skip to main content

Framing, register map, and discovery for the LuxPower inverter Modbus protocol (HA-free).

Project description

Release Stargazers codecov

Contributors Forks Issues

MIT License


luxmodbus

Framing, register map, and discovery for the LuxPower inverter Modbus protocol.


Report Bug · Request Feature
Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. The Frame
  5. Provenance
  6. Contributing
  7. License

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-checked encode_value for writes.
  • discovery.py — passive diff-and-log engine: compares observed registers against the known map and records the unknown with a rolling value history.

(back to top)

Getting Started

This project uses uv.

git clone https://github.com/totaldebug/luxmodbus.git
cd luxmodbus
uv sync
uv run nox -s tests

(back to top)

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}

(back to top)

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 - 6
  • data_length = len(data_frame) + 2 (the trailing CRC)
  • crc16 is the standard Modbus CRC (poly 0xA001, init 0xFFFF) 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.

(back to top)

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.

(back to top)

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.

(back to top)

License

Distributed under the MIT License. See LICENSE for more information.

(back to top)

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

luxmodbus-0.2.0.tar.gz (24.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

luxmodbus-0.2.0-py3-none-any.whl (26.1 kB view details)

Uploaded Python 3

File details

Details for the file luxmodbus-0.2.0.tar.gz.

File metadata

  • Download URL: luxmodbus-0.2.0.tar.gz
  • Upload date:
  • Size: 24.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","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

Hashes for luxmodbus-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c449f25394c5f01a88146f7553c1cd90ec5b78d15a927fb03a13e9e203abf846
MD5 6a5118dfa2746b82be5a30904d50d7b7
BLAKE2b-256 a19df6ca2fdde8fd49984a5ca883507ede3bf65fa62e28ec16b1a4e55b8ab3b0

See more details on using hashes here.

File details

Details for the file luxmodbus-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: luxmodbus-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 26.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","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

Hashes for luxmodbus-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d8fe14307d117d2515e623f1d0db8c9fbe18483f54e812d4db488912fc06969d
MD5 60897fb70cd7d58e4e73efd43c126895
BLAKE2b-256 9f2a0e1a8c481974a1583f1b8da1541f266601e1fec059fc6741f699bf17202b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page