Skip to main content

Async Python library to connect to a Fronius Wattpilot Wallbox

Project description

wattpilot-api

CI PyPI version Python versions Coverage License: MIT

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.0.0.tar.gz (37.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.0.0-py3-none-any.whl (43.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: wattpilot_api-1.0.0.tar.gz
  • Upload date:
  • Size: 37.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.0.0.tar.gz
Algorithm Hash digest
SHA256 10062bb0e946386e8fbcfb8b731f7da321154a16ac19a299f68f79c544d0d3ab
MD5 85eb4b8a82ecef8bfb402e89972ba283
BLAKE2b-256 859452c2d06dbe84cd024e22f21087840f09406fa578519639f60b2de4fbb4ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for wattpilot_api-1.0.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.0.0-py3-none-any.whl.

File metadata

  • Download URL: wattpilot_api-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 43.2 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.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2004ad12ebc0932a7974abf877c821093b5235b740b225743cddec525d37b0f0
MD5 daf947c8f5635d52b8318ddd8de5ea58
BLAKE2b-256 2c2d575131ec6fa2a3e4e71accc1b132288452ca84b94f32ea9254992b9e7dc6

See more details on using hashes here.

Provenance

The following attestation bundles were made for wattpilot_api-1.0.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