A high-level typed Python SDK for building applications on top of the Home Assistant REST and WebSocket APIs.
Unlike low-level Home Assistant clients that expose raw service calls and entity state payloads, this library provides domain-oriented accessors and intent-driven APIs designed for application development.
- Async context manager with automatic WebSocket connection and state priming
- Typed domain accessors: air quality, binary sensor, climate, cover, event, fan, humidifier, light, lock, media player, scene, sensor, switch, timer, vacuum, valve
- Intent-specific methods over raw service calls (e.g.
light.set_brightness(200)instead oflight.turn_on(brightness=200)) - Real-time state change listeners with granular attribute and state-transition filtering
- Synchronous blocking wrapper for scripts, REPL, and Jupyter
- Automatic WebSocket reconnection with exponential backoff
- Configurable service routing policy (
ws,rest, orauto) - Plugin system for third-party domain extensions via entry points
- Fully typed (PEP 561) with strict mypy enforcement
- Single runtime dependency (
aiohttp)
- Python 3.11+
- A running Home Assistant instance
- A long-lived access token from Home Assistant
pip install haclientOr install from source:
git clone https://github.com/graphras-com/HaClient.git
cd HaClient
pip install .from haclient import HAClient
async with HAClient.from_url("http://localhost:8123", token="YOUR_TOKEN") as ha:
light = ha.light("kitchen")
await light.set_brightness(200)
await light.set_kelvin(3000)
switch = ha.switch("garage_door")
await switch.off()
# Listen for state changes
sensor = ha.sensor("outdoor_temperature")
sensor.on_value_change(lambda old, new: print(f"Temp: {old} -> {new}"))from haclient import SyncHAClient
with SyncHAClient.from_url("http://localhost:8123", token="YOUR_TOKEN") as ha:
light = ha.light("kitchen")
light.set_brightness(200)
player = ha.media_player("living_room")
player.set_volume(0.5)Create a client with HAClient.from_url() or by passing a ConnectionConfig directly:
base_url-- Base URL of your Home Assistant instance (e.g.http://localhost:8123)token-- Long-lived access token generated from the Home Assistant UIreconnect-- Enable automatic WebSocket reconnection (default:True)ping_interval-- WebSocket keepalive interval in seconds (default:30)request_timeout-- Timeout for REST and WS commands in seconds (default:30)verify_ssl-- Verify SSL certificates (default:True)service_policy-- Service call routing:"ws","rest", or"auto"(default:"auto")
Store tokens securely using environment variables or a secrets manager. Do not commit tokens to version control.
Install development dependencies:
pip install -e ".[dev]"Run tests:
pytestRun tests with coverage:
pytest --cov=haclient --cov-report=term-missingLint and format:
ruff check src tests
ruff format --check src testsType checking:
mypy src- Never commit Home Assistant tokens or secrets to the repository
- Gitleaks runs on every CI pipeline execution to detect accidentally committed secrets
- The
.gitignoreexcludes.envfiles by default
GitHub Actions workflows handle:
- Lint -- Ruff check and format verification
- Type Check -- Strict mypy analysis
- Tests -- Pytest matrix across Python 3.11/3.12/3.13 with 95% coverage threshold
- Secrets Scan -- Gitleaks full-history scan
- Release -- Automated GitHub release on
v*tags - Dependabot -- Weekly dependency updates for pip and GitHub Actions
Contributions are welcome. Please open an issue or pull request. Follow existing code style and ensure all CI checks pass before submitting.
Apache-2.0 -- see LICENSE.