Async Python library for the BTicino/Netatmo API. Controls BTicino Classe 100X/300X video intercom systems via the Netatmo cloud.
Used by the bticino_intercom Home Assistant integration.
pip install pybticinoRequires Python 3.13 or later.
- Authentication: OAuth2 password grant with automatic token refresh and persistence support
- Home topology: fetch homes, modules, and their configuration
- Device control: lock/unlock doors, turn lights on/off
- Events: fetch call history with snapshots and vignettes
- WebSocket: real-time push notifications (call events, connection status, state changes)
- Re-subscribe: refresh OAuth token on existing connection without reconnecting
- WebRTC signaling: offer/answer/ICE exchange for live video calls (experimental)
import asyncio
from pybticino import AuthHandler, AsyncAccount
async def on_token_change(tokens):
"""Called when tokens are refreshed — persist them to avoid re-auth."""
print(f"New token expires at {tokens['expires_at']}")
async def main():
auth = AuthHandler(
"your_email@example.com",
"your_password",
token_callback=on_token_change, # optional: persist tokens
)
account = AsyncAccount(auth)
await account.async_update_topology()
for home_id, home in account.homes.items():
print(f"Home: {home.name} ({len(home.modules)} modules)")
status = await account.async_get_home_status(home_id)
events = await account.async_get_events(home_id, size=5)
await auth.close_session()
asyncio.run(main())To restore tokens from a previous session (skip initial auth):
auth = AuthHandler("email", "password", token_callback=on_token_change)
auth.set_tokens(
access_token=saved["access_token"],
refresh_token=saved["refresh_token"],
expires_at=saved["expires_at"],
)import asyncio
from pybticino import AuthHandler, WebsocketClient
async def on_message(message):
print(f"Event: {message.get('push_type')} - {message}")
async def main():
auth = AuthHandler("your_email@example.com", "your_password")
ws = WebsocketClient(auth, on_message)
# Option 1: run forever with auto-reconnect (recommended)
await ws.run_forever(reconnect_delay=30)
# Option 2: manual connect + listen
await ws.connect()
task = ws.get_listener_task()
if task:
await task
await ws.disconnect()
await auth.close_session()
asyncio.run(main())# Refresh token on existing connection without disconnecting.
# Call this periodically (e.g., every hour) to prevent token expiry.
await ws.resubscribe()| Method | Endpoint | Description |
|---|---|---|
async_update_topology() |
/api/homesdata |
Fetch homes and modules |
async_get_home_status(home_id) |
/syncapi/v1/homestatus |
Get module status |
async_set_module_state(home_id, module_id, state) |
/syncapi/v1/setstate |
Control devices |
async_get_events(home_id, size) |
/api/getevents |
Get event history |
async_get_turn_servers() |
/turn |
Fetch TURN/STUN ICE server credentials for WebRTC |
Events are delivered with push_type in format {DEVICE_TYPE}-{EVENT_TYPE}:
| push_type | Description |
|---|---|
BNC1-rtc |
Incoming WebRTC call (with SDP offer) |
BNC1-incoming_call |
Doorbell ring (with snapshot URL) |
BNC1-missed_call |
Unanswered call |
BNC1-accepted_call |
Call answered |
BNC1-connection |
Bridge connected |
BNC1-disconnection |
Bridge disconnected |
Full documentation at k-the-hidden-hero.github.io/pybticino
Key guides from reverse engineering:
- WebRTC Signaling Protocol — complete offer/answer/ICE flow, message formats, session state, two call modes
- WebRTC Audio Mechanism — how to activate the device microphone (requires real RTP audio packets)
- WebSocket Events — all push notification types and their JSON structures
- Reverse Engineering Notes — findings from decompiling the official BTicino/Netatmo app
Working example scripts in examples/:
| Script | Description |
|---|---|
webrtc_offer_mode.py |
On-demand video: send offer → receive answer → ICE → connected |
webrtc_answer_mode.py |
Answer incoming call: wait for doorbell → answer via signaling |
webrtc_audio_test.html |
Browser-based audio test with silence oscillator |
websocket_test.py |
Real-time push notification listener |
- bticino_intercom — Home Assistant custom integration
- bticino_ha_extras — Blueprints, Lovelace cards, and companion resources
pip install -e ".[test,dev]"
pytest tests/ -v
ruff check src/ tests/MIT