wattpilot-api
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
asyncioandwebsockets, 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 561py.typedmarker - 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:
- If the
authRequiredmessage includes ahashfield, that algorithm is used - Otherwise, if
devicetypeiswattpilot_flex, bcrypt is used - 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.
Metadata
Release files for wattpilot-api 1.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wattpilot_api-1.5.0.tar.gz | 42.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wattpilot_api-1.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 90.9 kB
Release files / wattpilot_api-1.5.0.tar.gz
| Download URL | wattpilot_api-1.5.0.tar.gz |
|---|---|
| Size | 42.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bcb980746834d3297d9b65d148d96290f220ce20c71a38fd5f811913bb8211c4
|
|
BLAKE2b-256 checksum How to use checksums |
a31bf45220bc41b8828147e162d45beee02d9491be907abc4e3b06c4edcc57db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 20, 2026.
Transparency logRelease files / wattpilot_api-1.5.0-py3-none-any.whl
| Download URL | wattpilot_api-1.5.0-py3-none-any.whl |
|---|---|
| Size | 48.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c098ff13afb872c9554a0a890df344eaf5ff170321c14b968cbe0c808b85949
|
|
BLAKE2b-256 checksum How to use checksums |
497a52be1df65b70a4906b444c67f9f130b63766d6d78ee81e5dabb941defd21
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 20, 2026.
Transparency log