Asynchronous Python client for MELCloud Home.
aiomelcloudhome is an async client for the MELCloud Home API, focused on:
- Fetching account context (buildings and devices)
- Controlling Air-to-Air units
- Controlling Air-to-Water units
- Reading telemetry (energy and actual measurements)
The library is under active development and endpoint coverage will keep expanding.
pip install aiomelcloudhomeimport asyncio
from aiohttp import ClientSession
from aiomelcloudhome import MELCloudHome
async def main() -> None:
async with ClientSession() as session:
async with MELCloudHome(
username="your@email.com",
password="your_password",
session=session,
) as client:
context = await client.get_context()
for building in context.buildings:
print(f"Building: {building.name}")
for unit in building.air_to_air_units:
print(f"ATA: {unit.name} (room: {unit.room_temperature} C)")
for unit in building.air_to_water_units:
print(f"ATW: {unit.name} (tank: {unit.tank_water_temperature} C)")
if __name__ == "__main__":
asyncio.run(main())from aiomelcloudhome import MELCloudHome
client = MELCloudHome(access_token="YOUR_ACCESS_TOKEN")from aiomelcloudhome import ATAFanSpeed, ATAOperationMode, MELCloudHome
await client.control_ata_unit(
"ata-unit-id",
power=True,
operation_mode=ATAOperationMode.HEAT,
set_temperature=21.0,
set_fan_speed=ATAFanSpeed.AUTO,
)from aiomelcloudhome import ATWZoneMode
await client.control_atw_unit(
"atw-unit-id",
power=True,
operation_mode_zone1=ATWZoneMode.HEAT_ROOM_TEMPERATURE,
set_temperature_zone1=21.0,
set_tank_water_temperature=50.0,
)from datetime import UTC, datetime, timedelta
energy = await client.get_energy_telemetry(
"unit-id",
from_dt=datetime.now(UTC) - timedelta(days=1),
to_dt=datetime.now(UTC),
)
outdoor = await client.get_outdoor_temperature("ata-unit-id")Instead of polling get_context(), you can opt in to a live update stream. stream_updates()
connects to the MELCloud Home realtime WebSocket, reuses the client's existing authentication,
reconnects transparently, and yields a typed UnitStateDelta whenever a unit changes. Control,
telemetry and the initial state snapshot still use the REST API.
async for delta in client.stream_updates():
print(delta.unit_id, delta.unit_type, delta.changes)
# e.g. changes == {"SetTemperature": 21.0} or {"OperationMode": ATAOperationMode.COOL}The stream raises MelCloudHomeWebSocketError if the realtime channel cannot be established, so
you can fall back to polling.
For a long-lived listener that you need to start and stop (for example a Home Assistant
coordinator), use client.websocket() to hold a handle, run stream() in a background task, and
close() it on teardown:
ws = client.websocket()
task = asyncio.create_task(_listen(ws)) # _listen iterates `async for delta in ws.stream()`
# on shutdown (e.g. async_unload_entry):
await ws.close() # stops gracefully; stream() ends on its own
await taskMore examples can be found in the examples directory.
Project documentation and API reference: https://github.com/erwindouna/aiomelcloudhome
Contributions are welcome. Please open an issue or pull request.
For local development:
uv sync --all-groups && uv run pre-commit installRun checks:
uv run pre-commit run --all-filesRun tests:
uv run pytestUpdate snapshot tests:
uv run pytest --snapshot-updateMIT License
Copyright (c) 2026 Erwin Douna