Skip to main content

Async library to read SolaX inverters over UART using the Pocket USB protocol

Project description

aiosolax-uart

PyPI version Python versions License Test codecov Ruff pre-commit

Async Python library to read SolaX inverters over the Pocket USB protocol — the byte-level protocol that the SolaX Pocket WiFi / Pocket USB dongle speaks. Any inverter that accepts a Pocket dongle should be reachable with this library, whether the user connects a real dongle or replaces it with a USB-to-TTL adapter (CP2102, CH340, FT232, …) or an ESPHome serial proxy.

The wire protocol is AA 55 framing at 9600 baud, 8N1. Originally reverse-engineered by xdubx; hybrid-inverter extensions contributed by 70p4z.

Install

pip install aiosolax-uart

Quickstart

import asyncio
from aiosolax_uart import SolaxClient

async def main() -> None:
    async with SolaxClient("/dev/ttyUSB0") as client:
        info = await client.get_device_info()
        print(f"Connected: {info.model.name} (serial {info.inverter_serial})")

        live = await client.get_live_data()
        print(f"AC power: {live.grid_power} W, today: {live.energy_today} kWh")
        if live.import_power is not None:
            print(
                f"House grid: imp={live.import_power}W "
                f"exp={live.export_power}W self={live.self_consumption_power}W"
            )
        if live.battery_soc is not None:
            print(f"Battery: {live.battery_soc}% @ {live.battery_voltage}V")

asyncio.run(main())

The library also works against an ESPHome serial proxy — pass an esphome://host[:port]/?port_name=...&noise_psk=... URL in place of /dev/ttyUSB0.

Supported inverters

The library handles two payload families. Which fields are populated on a given inverter depends on what that inverter actually reports.

Family Models Status
X1 grid-tie X1 Mini (G2/G3), X1 Air, X1 Boost (G3.3/G4), X1 Smart Verified (X1 with CT clamp, May 2026)
X1 Hybrid X1 Hybrid G3 / G4.1+ Decoder present, unverified — needs hardware testers
X3 grid-tie X3 Mega G2, X3 Mic/Pro G2, X3 Forth Same wire protocol, unverified
X3 Hybrid X3 Hybrid G2 / G4.2+ Decoder present, unverified — needs hardware testers

If you can run await client.get_device_info() against your inverter and get a sensible response, please open an issue with the output so the model code can be added to the MODELS registry.

API

SolaxClient

  • SolaxClient(port: str, *, dongle_serial: str = "AIOSOLAX01", baudrate: int = 9600)
  • async connect() -> None — open serial, register with the inverter
  • async close() -> None
  • async get_device_info() -> DeviceInfo — inverter serial, model code, dongle serial. Cached for use by get_live_data().
  • async get_live_data() -> LiveData — instantaneous values + lifetime energy totals. Dispatches to the right decoder using the cached model code.
  • Use as async with SolaxClient(...) as client: to handle setup/teardown.

Data models

  • DeviceInfo — static device info plus a .model property that looks up the entry in MODELS.
  • LiveData — every field that any inverter family can report. Common fields (AC, PV, temperature, energy_total, energy_today, runtime) are always populated; CT, battery, EPS and RTC fields are None when not available.

Model registry

from aiosolax_uart import MODELS, lookup_model

MODELS[5000]  # InverterModel(code=5000, name='X1 (5kW)', family=InverterFamily.X1_GRID_TIE)
lookup_model(0xFFFF)  # InverterModel(code=65535, name='Unknown (65535)', family=InverterFamily.UNKNOWN)

Protocol reference

Frame layout: AA 55 [total_size] [ctrl] [func] [payload...] [chk_lo chk_hi] with a 16-bit little-endian additive checksum over all preceding bytes.

Direction ctrl func Description
Host → 0x02 0x01 Register dongle (10-char ASCII serial)
Host → 0x01 0x05 Read inverter serial / model code
Inv ← 0x01 0x85 Serial response (40-byte payload)
Host → 0x01 0x0C Read live data
Inv ← 0x01 0x8C Live-data response (200 / 210+ bytes depending on family)

The handshake is: open serial → broadcast register frame → wait for the inverter to echo it back → poll live data on a cadence.

Development

uv sync
uv run pytest

Contributing

If your inverter isn't in the MODELS registry yet:

  1. Run a small script that prints await client.get_device_info() against your inverter.
  2. Open an issue with the model code and the inverter's name (from the sticker).

If you have a hybrid inverter, the offsets in _decode_hybrid_extras() need verification. A 220-byte capture of await client.get_live_data() plus your battery's known voltage/SoC right when you took the capture would let us validate the offsets.

License

Apache 2.0

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

aiosolax_uart-0.1.0.tar.gz (11.2 kB view details)

Uploaded Source

Built Distribution

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

aiosolax_uart-0.1.0-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: aiosolax_uart-0.1.0.tar.gz
  • Upload date:
  • Size: 11.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for aiosolax_uart-0.1.0.tar.gz
Algorithm Hash digest
SHA256 09f9c3b00230c70674d1d4f6c7206370a714dc1ac7349aa07d68f459892a5b66
MD5 0cc377c7282a1d410d9fa0c18f60d62c
BLAKE2b-256 4a1d662d909546ee4fffe3b437e037c0fdfcba7361200bae10c226d1608b0459

See more details on using hashes here.

Provenance

The following attestation bundles were made for aiosolax_uart-0.1.0.tar.gz:

Publisher: publish.yml on jesserockz/aiosolax-uart

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: aiosolax_uart-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for aiosolax_uart-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 238947f30cd0a4ec2e44aa038b0e839e51d4bfe527290598493f1efc06641b71
MD5 3cb010e5f850d825d88967d6533511ab
BLAKE2b-256 d4c9d931751976f0991d2724e61c3e58e62dc0a7598c7b871ec7ac09f0e0ce97

See more details on using hashes here.

Provenance

The following attestation bundles were made for aiosolax_uart-0.1.0-py3-none-any.whl:

Publisher: publish.yml on jesserockz/aiosolax-uart

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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