Skip to main content

voltkeeper

CLI tool for Bluetti power stations — scan, connect, and read battery data over BLE.

Install

Quick run (no clone required)

uvx --from git+https://github.com/mikemccllstr/voltkeeper voltkeeper --help

This downloads and runs the tool in an isolated environment. Replace --help with any command or subcommand.

From source

git clone https://github.com/mikemccllstr/voltkeeper
cd voltkeeper
uv run voltkeeper --help

Usage

Scan for devices

voltkeeper scan

Displays all nearby Bluetti devices and shows the exact command to connect to each one.

Options:

  • -t, --timeout FLOAT Scan timeout in seconds (default: 10.0)

Read battery status

voltkeeper status                  # auto-scan for devices, then pick one
voltkeeper status AA:BB:CC:DD:EE:FF  # connect directly

Output:

  • Battery SOC (%)
  • Pack voltage
  • Charging status
  • Time to full / time to empty (context-dependent)
  • DC load, AC load, and total load (watts)

Options:

  • -t, --timeout FLOAT Scan timeout in seconds (default: 10.0, used only when no address given)
  • -v, --verbose Display all available device information (power meters, energy totals, PV strings, grid, loads, temperatures, software versions, writable controls, and device capabilities)

Probe a device (register sweep)

voltkeeper probe AA:BB:CC:DD:EE:FF -o device.yaml

Connects to the device, sweeps all known register blocks, and writes a YAML profile. Useful for device reverse-engineering and new-model support.

Validate a profile

voltkeeper validate-profile device.yaml

Parses the register blocks in a probe YAML and flags fields with suspect values (stuck-at-zero, all-0xFFFF, out of range).

Annotate changing registers (interactive)

voltkeeper annotate AA:BB:CC:DD:EE:FF -o draft.yaml

Live-polls the device and highlights byte-level changes in real time. Prompts for field names at each changed offset, saving annotations incrementally to a YAML draft. Press Ctrl-C to stop.

Write device settings

voltkeeper write AA:BB:CC:DD:EE:FF ac_output on
voltkeeper write AA:BB:CC:DD:EE:FF dc_output off
voltkeeper write AA:BB:CC:DD:EE:FF charging_mode turbo

Writable fields (see --verbose output for current values):

  • switches: ac_output, dc_output, power_off, dc_eco_mode, ac_eco_mode, power_lifting, alarm_sound — on/off
  • charging_mode — standard/turbo/silent
  • numeric: battery_range_start, battery_range_end, lcd_timeout, led_color, soc_low, soc_high, inv_voltage, inv_freq, working_mode

MQTT publish

voltkeeper mqtt-publish AA:BB:CC:DD:EE:FF --broker 192.168.1.100

Continuously polls the device over BLE and publishes state to an MQTT broker. Supports Home Assistant MQTT auto-discovery (on by default).

Options:

  • --serial TEXT Device serial number (overrides BLE lookup for MQTT topic)
  • --broker TEXT MQTT broker hostname (required)
  • --port INTEGER MQTT broker port (default: 1883)
  • --username TEXT MQTT broker username
  • --password TEXT MQTT broker password
  • --interval INTEGER Seconds between polling cycles (default: 0 = as fast as possible)
  • --ha-config MODE Home Assistant discovery mode: normal, none, advanced (default: normal)
  • --restart-on-source-change Exit cleanly when source code changes, so systemd restarts the process

MQTT listen — shutdown watchdog

voltkeeper mqtt-listen --serial 2409000123456 --broker 192.168.1.100

Subscribes to the device's MQTT topic and watches battery SOC. When SOC drops below the threshold, initiates a system shutdown after a grace period. The shutdown is latched — once triggered, it cannot be cancelled by SOC recovery (use systemctl stop to abort before the grace period expires).

Options:

  • --serial TEXT Device serial number (or provide ADDRESS for BLE lookup)
  • --broker TEXT MQTT broker hostname (required)
  • --port INTEGER MQTT broker port (default: 1883)
  • --username TEXT MQTT broker username
  • --password TEXT MQTT broker password
  • --shutdown-at INTEGER SOC % threshold for shutdown (default: 10)
  • --grace-period INTEGER Seconds below threshold before shutdown (default: 60)
  • --restart-on-source-change Exit cleanly when source code changes

ADDRESS may be omitted if --serial is provided (useful when running on a different machine without BLE).

Generate systemd service

voltkeeper load-test [OPTIONS] ADDRESS

Runs a controlled battery discharge test. Coaches you through setup, then logs device stats every N seconds to a CSV file until the battery reaches 0%.

Options:

  • -o, --output PATH CSV output file (default: ac2a_load_test_YYYYMMDD_HHMMSS.csv)
  • -i, --interval SECONDS Sample interval, minimum 15s (default: 60)
  • -l, --expected-load W Known load wattage for analysis reference
  • -p, --phase TEXT Label for this test phase (useful for multi-phase testing)

Example:

voltkeeper load-test AA:BB:CC:DD:EE:FF -l 500 -p "500W heater on AC"

The test will:

  1. Prompt you to fully charge, connect a load, and disconnect charging
  2. Verify prerequisites (SOC ≥ 95%, no grid/PV input)
  3. Poll every N seconds — logging SOC, voltage, current, AC/DC/PV/grid power, temperatures, device time estimate, and two energy measurements:
    • Computed — trapezoidal integration of measured power × time
    • Register — the device's own totalDCEnergy register (for validation)
  4. Warn if grid or PV charging is detected (> 10 W)
  5. End when SOC reaches 0%, BLE connection drops, or you press Ctrl-C
  6. Print a summary with capacity, average load, min voltage, and max temp

The CSV has 17 columns with a comment header block; empty cells for failed BLE reads are Excel-friendly.

Generate systemd services

MQTT publish service

voltkeeper mqtt-publish-service AA:BB:CC:DD:EE:FF --broker 192.168.1.100

Generates a systemd unit file for mqtt-publish.

Options mirror the mqtt-publish command plus:

  • --user NAME System user to run as (default: current user)
  • --exec PATH Path to voltkeeper executable (default: auto-detect)
  • -o, --output PATH Write to file instead of stdout

MQTT listen service

voltkeeper mqtt-listen-service --serial 2409000123456 --broker 192.168.1.100

Generates a systemd unit file for mqtt-listen.

Options mirror the mqtt-listen command plus:

  • --user NAME System user to run as (default: root, needed for shutdown)
  • --exec PATH Path to voltkeeper executable (default: auto-detect)
  • -o, --output PATH Write to file instead of stdout

Installing a generated service

sudo cp voltkeeper-*.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now voltkeeper-*.service
  • -o, --output PATH Write to file instead of stdout

Install the generated file:

sudo cp voltkeeper-mqtt-*.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now voltkeeper-mqtt-*.service

Help

voltkeeper --help
voltkeeper status --help
voltkeeper scan --help
voltkeeper probe --help
voltkeeper mqtt-publish --help
voltkeeper mqtt-listen --help
voltkeeper load-test --help
voltkeeper --version

Requirements

  • Python 3.13+
  • Linux with BlueZ, macOS 11+, or Windows 10 build 19041+ (BLE support)
  • Bluetooth adapter with scan capability

On Linux, the BLE adapter may require elevated privileges (CAP_NET_ADMIN or sudo). On macOS, the device's BLE MAC address may be reported as a UUID rather than a hardware address — use the UUID directly with voltkeeper.

The tool reads plain Modbus RTU over BLE from Bluetti power stations. Encrypted devices (AES-CBC over BLE) are supported; the handshake is handled automatically.

Testing

uv run pytest                 # unit tests (fast, no BLE required)
uv run pytest -m integration  # integration tests (requires BLE adapter)

Development

See docs/FINDINGS.md for reverse-engineering notes and protocol details helpful when enhancing this tool.

Contributing a new device

See docs/CONTRIBUTING_DEVICES.md for the step-by-step guide to capturing the data needed to add support for a new Bluetti device model. Maintainers receiving such a submission should follow docs/MAINTAINING.md.

Metadata

Release files for voltkeeper 2026.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for voltkeeper 2026.5
File Size Uploaded Provenance
voltkeeper-2026.5.tar.gz 356.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for voltkeeper 2026.5
File Interpreter ABI Platform
voltkeeper-2026.5-py3-none-any.whl Python 3 none any Details

Total release size: 425.9 kB

Release files / voltkeeper-2026.5.tar.gz

Download URL voltkeeper-2026.5.tar.gz
Size 356.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b849a5b2cfcfae86e17fcd463b5f50ab0a3f0c97ce77ff7d00d337f554b07251
BLAKE2b-256 checksum
How to use checksums
4dcf580bfbfee5fd98635e102e2020c3529eab6f9ae60a5f93555eae6133dc43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Release files / voltkeeper-2026.5-py3-none-any.whl

Download URL voltkeeper-2026.5-py3-none-any.whl
Size 69.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aabc9201c3674e2dc08e4c877fe02bb0841c6375e094dd90d0ae4e34ae156bc0
BLAKE2b-256 checksum
How to use checksums
d5f65b4f083ed022c91a0fba7ff5aec86f8601e87328849963c9425a561c7c15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

Security for voltkeeper 2026.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for voltkeeper-2026.5.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

2026.5 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page