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.1.0.tar.gz (22.9 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.1.0-py3-none-any.whl (25.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: luxmodbus-0.1.0.tar.gz
  • Upload date:
  • Size: 22.9 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.1.0.tar.gz
Algorithm Hash digest
SHA256 d76f0d72d8e74d7d24e8ef6e1b2a44df0895c87432c57b743273544535b8cd59
MD5 bf51637808442f1b5f65f407e18f9db4
BLAKE2b-256 678ae22da78670eb225e82183e63074cf503ebd43866cae586290030c64367d9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: luxmodbus-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.0 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c995f3ded1e49e2c72dd2c14687a5ab97db95d53601fc9c9852da498b4022d16
MD5 dc9cd001aec4b08854ff98dcd88fb8ca
BLAKE2b-256 3d025aa05762def6edc2b6012511aecebdad1fa73439cd8ae892e8fa5fa4b280

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