Skip to main content

Async Python library to connect to a Fronius Wattpilot Wallbox

Project description

wattpilot-api

CI PyPI version Python versions codecov License: MIT Ask DeepWiki

Async Python library for Fronius Wattpilot Wallbox devices.

Connects to Wattpilot EV chargers over WebSocket using a reverse-engineered API (the same protocol used by the official Wattpilot.Solar mobile app). Provides real-time property synchronization, an MQTT bridge, Home Assistant discovery, and an interactive CLI shell.

Features

  • Fully async — built on asyncio and websockets, compatible with Home Assistant
  • All Wattpilot hardware — supports standard (V2) and Flex models via PBKDF2 and bcrypt authentication
  • 388+ properties — access every charger property in real time
  • MQTT bridge — publish properties and subscribe to commands via aiomqtt
  • Home Assistant discovery — automatic entity creation with proper device classes
  • Interactive shell — async CLI with TAB completion via prompt_toolkit
  • Type-safe — full type hints, mypy --strict, PEP 561 py.typed marker
  • 100% test coverage — 241 unit tests + 18 integration tests

Requirements

  • Python 3.12+
  • Local network access to a Fronius Wattpilot charger

Installation

pip install wattpilot-api

For development:

pip install -e ".[dev]"

Quick Start

As a library

import asyncio
from wattpilot_api import Wattpilot, LoadMode

async def main():
    async with Wattpilot("192.168.1.100", "your_password") as wp:
        # Read properties
        print(f"Serial: {wp.serial}")
        print(f"Firmware: {wp.firmware}")
        print(f"Power: {wp.power:.2f} kW")
        print(f"Amperage: {wp.amp} A")
        print(f"Car connected: {wp.car_connected}")
        print(f"Mode: {LoadMode(wp.mode).name}")

        # Set charging amperage
        await wp.set_power(16)

        # Set charging mode
        await wp.set_mode(LoadMode.ECO)

        # Register a callback for property changes
        def on_change(name, value):
            print(f"{name} = {value}")

        unsub = wp.on_property_change(on_change)

        # Access all 388+ raw properties
        for key, value in sorted(wp.all_properties.items()):
            print(f"  {key} = {value}")

        unsub()  # unsubscribe when done

asyncio.run(main())

Interactive shell

export WATTPILOT_HOST=192.168.1.100
export WATTPILOT_PASSWORD=your_password
wattpilotshell

With MQTT and Home Assistant

export WATTPILOT_HOST=192.168.1.100
export WATTPILOT_PASSWORD=your_password
export MQTT_ENABLED=true
export MQTT_HOST=your_mqtt_broker
export HA_ENABLED=true
wattpilotshell

Supported Hardware

Device Auth Status
Wattpilot Home (V2) PBKDF2 Tested
Wattpilot Home FLEX 11 C6 bcrypt Supported
Wattpilot Home FLEX 22kW bcrypt Supported
Wattpilot (cloud via Fronius API) PBKDF2 Supported

Authentication is auto-detected:

  1. If the authRequired message includes a hash field, that algorithm is used
  2. Otherwise, if devicetype is wattpilot_flex, bcrypt is used
  3. Otherwise, PBKDF2 is used (default)

API Reference

Wattpilot Client

from wattpilot_api import Wattpilot

# Constructor
wp = Wattpilot(
    host="192.168.1.100",
    password="your_password",
    serial=None,           # auto-detected from device
    cloud=False,           # True for Fronius cloud connection
    connect_timeout=30.0,  # seconds
    init_timeout=30.0,     # seconds
)

# Connect / disconnect
await wp.connect()
await wp.disconnect()

# Or use as async context manager
async with Wattpilot("192.168.1.100", "password") as wp:
    ...

Properties

Property Type Description
wp.connected bool Connection status
wp.serial str Device serial number
wp.name str Device name
wp.manufacturer str Manufacturer ("fronius")
wp.device_type str Device type ("wattpilot_V2", "wattpilot_flex")
wp.version str Firmware version
wp.amp int Current amperage setting
wp.mode int Charging mode (3=Default, 4=Eco, 5=NextTrip)
wp.car_connected int Car status (1=No car, 2=Charging, 3=Ready, 4=Complete)
wp.allow_charging bool Whether charging is allowed
wp.voltage1/2/3 float Phase voltages
wp.amps1/2/3 float Phase currents
wp.power1/2/3 float Phase power (kW)
wp.power float Total power (kW)
wp.frequency float Grid frequency (Hz)
wp.energy_counter_since_start float Session energy (Wh)
wp.energy_counter_total float Lifetime energy (Wh)
wp.error_state int Error code
wp.cable_type int Cable capacity (A)
wp.cable_lock int Lock mode
wp.access_state int Access state
wp.phases list Phase configuration
wp.all_properties dict All 388+ raw properties

Commands

await wp.set_power(16)                    # Set amperage (6-32)
await wp.set_mode(LoadMode.ECO)           # Set charging mode
await wp.set_property("fna", "MyCharger") # Set any writable property

Callbacks

# Sync or async callbacks supported
unsub = wp.on_property_change(lambda name, value: print(f"{name}={value}"))
unsub()  # unsubscribe

unsub = wp.on_message(lambda msg: print(msg["type"]))
unsub()

Enums

from wattpilot_api import LoadMode, CarStatus, ErrorState, AccessState, CableLockMode

LoadMode(wp.mode)           # LoadMode.DEFAULT / ECO / NEXTTRIP
CarStatus(wp.car_connected) # CarStatus.NO_CAR / CHARGING / READY / COMPLETE

Exceptions

from wattpilot_api import WattpilotError, AuthenticationError, ConnectionError

try:
    await wp.connect()
except AuthenticationError:
    print("Wrong password")
except ConnectionError:
    print("Cannot reach device")

MQTT Bridge

The MqttBridge class publishes property changes to MQTT and subscribes to set commands.

from wattpilot_api import Wattpilot, MqttBridge, MqttConfig
from wattpilot_api.definition import load_api_definition

api_def = load_api_definition()
config = MqttConfig(host="localhost", port=1883)

async with Wattpilot("192.168.1.100", "password") as wp:
    bridge = MqttBridge(wp, config, api_def)
    await bridge.start()
    # ... bridge publishes property changes to MQTT
    await bridge.stop()

Home Assistant Discovery

from wattpilot_api import HomeAssistantDiscovery, HaConfig

ha = HomeAssistantDiscovery(wp, bridge, HaConfig(enabled=True), api_def)
await ha.discover_all()
await ha.publish_initial_values()

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests (100% coverage required)
pytest --cov=wattpilot_api --cov-report=term-missing --cov-fail-under=100

# Run integration tests against a real device
WATTPILOT_HOST=192.168.1.100 WATTPILOT_PASSWORD=password pytest -m integration -v

# Lint and type check
ruff check src/ tests/
mypy src/wattpilot_api/

# Pre-commit (runs ruff, ruff-format, mypy)
pre-commit run --all-files

Project Structure

src/wattpilot_api/
├── __init__.py          # Public API exports
├── client.py            # Async WebSocket client
├── auth.py              # PBKDF2 + bcrypt authentication
├── models.py            # Enums and dataclasses
├── exceptions.py        # Exception hierarchy
├── definition.py        # YAML property metadata loader
├── mqtt.py              # Async MQTT bridge
├── discovery.py         # Home Assistant MQTT discovery
├── shell.py             # Async CLI shell
├── py.typed             # PEP 561 marker
└── resources/
    └── wattpilot.yaml   # Property definitions (3300+ lines)

API Sources

The WebSocket API has been reverse-engineered from multiple sources:

Changelog

See CHANGELOG.md for version history, migration guide, and upstream issue fixes.

License

MIT License — see LICENSE for details.

Disclaimer

This project uses a reverse-engineered API and is not officially supported by Fronius. Use at your own risk.

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

wattpilot_api-1.1.0.tar.gz (40.8 kB view details)

Uploaded Source

Built Distribution

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

wattpilot_api-1.1.0-py3-none-any.whl (46.1 kB view details)

Uploaded Python 3

File details

Details for the file wattpilot_api-1.1.0.tar.gz.

File metadata

  • Download URL: wattpilot_api-1.1.0.tar.gz
  • Upload date:
  • Size: 40.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wattpilot_api-1.1.0.tar.gz
Algorithm Hash digest
SHA256 b498d6130980b22e21605c2e7b8eea4faa2ddec94678840f8e75a7b8206b9cdc
MD5 2191dd2af64cd43dd40c66972dd7ff94
BLAKE2b-256 9a64441715396ae5ed17fe477858e047533c700a92b57b363e4a6bf0a791f29e

See more details on using hashes here.

Provenance

The following attestation bundles were made for wattpilot_api-1.1.0.tar.gz:

Publisher: publish.yml on ruaan-deysel/wattpilot-api

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

File details

Details for the file wattpilot_api-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: wattpilot_api-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 46.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wattpilot_api-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 68ba752b83f797a3d5b8fb231715c3dd793fed122768bb630d562c581f2f05f1
MD5 9157151b6ee6b29db695eb60143ff3c1
BLAKE2b-256 79fd9f009504e503f44d3ba8ea6cea2d5c950b6f4f88ac4c6dcf475eaa51860b

See more details on using hashes here.

Provenance

The following attestation bundles were made for wattpilot_api-1.1.0-py3-none-any.whl:

Publisher: publish.yml on ruaan-deysel/wattpilot-api

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