Async Python client for the Brofer Cloud VMC API
Project description
pybrofer
Async Python client for the Brofer Cloud VMC (Ventilation with Heat Recovery) API.
Built to work cleanly inside Home Assistant integrations, but usable in any async Python application.
Disclaimer
This project is not affiliated with, endorsed by, or supported by Brofer or Brofer Web Services in any way. Use at your own risk.
Installation
pip install pybrofer
Or with uv:
uv add pybrofer
Requires Python 3.12+. The only runtime dependency is aiohttp.
Quick start
import asyncio
import aiohttp
from pybrofer import authenticate, BroferClient
async def main():
async with aiohttp.ClientSession() as session:
# 1. Authenticate — returns a short-lived Bearer token
token = await authenticate(
session,
base_url="https://api.broferwebservices.it",
username="your@email.com",
password="yourpassword",
access_token="your-device-access-token", # from the Brofer app
)
# 2. Create a client and query your device
client = BroferClient(session, token)
state = await client.get_state("your-device-id")
print(state.ventilation_speed) # e.g. "home"
print(state.indoor_temperature) # e.g. 21.5
print(state.is_filter_dirty) # True / False
# 3. Change ventilation mode
await client.set_ventilation_speed("your-device-id", "boost")
asyncio.run(main())
API reference
authenticate(session, base_url, username, password, access_token, *, ssl=True) → str
Authenticates with the Brofer Cloud API using HTTP Basic Auth and a device access token, and returns a Bearer token for use with BroferClient.
| Parameter | Type | Description |
|---|---|---|
session |
aiohttp.ClientSession |
Caller-managed session |
base_url |
str |
API base URL (e.g. "https://api.broferwebservices.it") |
username |
str |
Brofer account email |
password |
str |
Brofer account password |
access_token |
str |
Device-specific token from the Brofer app |
ssl |
bool |
Set to False to skip TLS verification (not recommended) |
Raises BroferAuthError on bad credentials, BroferConnectionError on network failure.
BroferClient(session, access_token, *, ssl=True)
The caller owns the aiohttp.ClientSession — the client never creates one internally.
get_state(device_id) → VMCState
Fetches the current state of a VMC unit from GET /bridges/{device_id}/data.
set_ventilation_speed(device_id, speed)
Posts a ventilation mode change to POST /bridges/{device_id}/ventilation-speed.
Valid speeds: "away", "home", "boost", "party". Raises ValueError for unknown values.
update_token(new_token)
Replaces the stored Bearer token in place — useful when a coordinator re-authenticates and needs to hand the new token to an existing client instance.
VMCState
Frozen dataclass returned by get_state.
| Field | Type | Description |
|---|---|---|
read_at |
datetime |
Timestamp the bridge read the state |
is_online |
bool |
Whether the device is reachable |
filter_dirty |
int |
Raw filter status (0 = clean, 1 = dirty) |
outdoor_temperature |
float |
Outdoor temperature in °C |
indoor_temperature |
float |
Indoor temperature in °C |
ventilation_speed |
str |
Current mode ("away", "home", "boost", "party") |
is_filter_dirty |
bool |
Computed property — True when filter needs replacement |
Exceptions
All exceptions inherit from BroferError.
| Exception | Raised when |
|---|---|
BroferAuthError |
HTTP 401/403, or no token in auth response |
BroferAPIError |
Any other non-2xx response (exposes status_code, response_body) |
BroferConnectionError |
Transport-level failure (DNS, timeout, SSL) |
Development
uv sync # install all dependencies
uv run pytest # tests + coverage
uv run ruff check src tests # lint
uv run ruff format src tests # format
uv run mypy # type check
CI runs on Python 3.12 and 3.13. Coverage must stay above 80%.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pybrofer-0.1.0.tar.gz.
File metadata
- Download URL: pybrofer-0.1.0.tar.gz
- Upload date:
- Size: 5.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f69bbd2a956df8534b826c3dbc0ee9cca12ce5575cba12923d3882f9e2b5f9c1
|
|
| MD5 |
a192d2137ed8c1816bd6b0d55d5e7fff
|
|
| BLAKE2b-256 |
f1d05461651e709493f167d29aa7412fa4db32d229c1e7b05d12251f0c712ad8
|
Provenance
The following attestation bundles were made for pybrofer-0.1.0.tar.gz:
Publisher:
publish.yml on tiagomota/pybrofer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pybrofer-0.1.0.tar.gz -
Subject digest:
f69bbd2a956df8534b826c3dbc0ee9cca12ce5575cba12923d3882f9e2b5f9c1 - Sigstore transparency entry: 1331633730
- Sigstore integration time:
-
Permalink:
tiagomota/pybrofer@14a901274590375d2e888345efb6231231ee1cd4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/tiagomota
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@14a901274590375d2e888345efb6231231ee1cd4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pybrofer-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pybrofer-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27c9b0d4b98003cc570f56e43203911d51365ea6d9b231ab2416a320fc7795c2
|
|
| MD5 |
04a0ff7b2ca09235d135722b41eb10c7
|
|
| BLAKE2b-256 |
07671d0c8b56caf877b7aa5df288bedf2805264f882afd902870024ce32bcf42
|
Provenance
The following attestation bundles were made for pybrofer-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on tiagomota/pybrofer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pybrofer-0.1.0-py3-none-any.whl -
Subject digest:
27c9b0d4b98003cc570f56e43203911d51365ea6d9b231ab2416a320fc7795c2 - Sigstore transparency entry: 1331633805
- Sigstore integration time:
-
Permalink:
tiagomota/pybrofer@14a901274590375d2e888345efb6231231ee1cd4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/tiagomota
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@14a901274590375d2e888345efb6231231ee1cd4 -
Trigger Event:
push
-
Statement type: