aioesphomeapi Python Library

repository·main·Indexed 41 days ago

https://github.com/esphome/aioesphomeapi

A Python library for interacting with ESPHome devices via the Native API. It provides capabilities for state subscription, device information retrieval, and secure communication. Key features include control of lights, switches, fans, covers, climate devices, and media players, as well as advanced support for Bluetooth proxies, Serial/UART proxies, Z-Wave proxies, and raw IR/RF transmissions.

Tokens
6.3K
Snippets
22
Records
25
Agent score
2%

What's inside aioesphomeapi

  1. Set up a development environment

    main

    For development, it is recommended to use a Python virtual environment and install the package in editable mode. To update protobuf definitions, use the provided Docker/Podman image.

    # Setup virtualenv
    $ python3 -m venv .
    $ source bin/activate
    
    # Install package and test dependencies
    $ pip3 install -e .
    $ pip3 install -r requirements/test.txt
    
    # Run linters & test
    $ script/lint
    
    # Update protobuf definitions (requires docker or podman)
    $ docker run --rm -v $PWD:/aioesphomeapi ghcr.io/esphome/aioesphomeapi-proto-builder:latest
  2. Install aioesphomeapi

    main

    Install the aioesphomeapi module from PyPI using pip.

    An optional Cython extension is available for improved performance. The module attempts to build it automatically if a C compiler and Python development headers are present. To prevent the build attempt, set the environment variable SKIP_CYTHON=1.

    $ pip3 install aioesphomeapi
  3. Configure ESPHome device for Native API

    main

    To use aioesphomeapi, the ESPHome device must have the api: component enabled in its configuration.

    For secure communication, it is highly recommended to use encryption with a key. You can generate a 32-byte base64 key using openssl rand -base64 32.

    # Enable the Native API
    api:
    
    # Recommended: Enable encryption
    api:
      encryption:
        key: !secret api_encryption_key
  4. Connect to an ESPHome device using APIClient

    main

    Use aioesphomeapi.APIClient to establish a connection.

    • For modern devices (ESPHome 2026.1.0+): Use noise_psk for encryption. Password authentication has been removed.
    • For older devices: Use the password argument.

    After initializing the client, you must call await api.connect(login=True) to establish the session.

    import aioesphomeapi
    import asyncio
    
    async def main():
        # Connect with encryption
        api = aioesphomeapi.APIClient(
            "api_test.local",
            6053,
            noise_psk="YOUR_ENCRYPTION_KEY",
        )
        await api.connect(login=True)
    
        # Connect to older devices with password
        # api = aioesphomeapi.APIClient("device.local", 6053, password="MyPassword")
    
    asyncio.run(main())
  5. Subscribe to device state changes

    main

    You can listen for real-time state updates from the device by using api.subscribe_states(callback). The callback function will be executed whenever a state change occurs.

    import aioesphomeapi
    import asyncio
    
    async def main():
        api = aioesphomeapi.APIClient(
            "api_test.local",
            6053,
            noise_psk="YOUR_ENCRYPTION_KEY",
        )
        await api.connect(login=True)
    
        def change_callback(state):
            """Print the state changes of the device.""
            print(state)
    
        # Subscribe to the state changes
        api.subscribe_states(change_callback)
    
        # Keep the loop running to receive updates
        while True:
            await asyncio.sleep(1)
    
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        pass
  6. Retrieve device information and entities

    main

    Once connected via APIClient, you can access device metadata and its available services/entities using the following methods:

    • api.api_version: Returns the API version of the device's firmware.
    • await api.device_info(): Returns detailed information about the device.
    • await api.list_entities_services(): Returns a list of all entities and services available on the device.
    import aioesphomeapi
    import asyncio
    
    async def main():
        api = aioesphomeapi.APIClient(
            "api_test.local",
            6053,
            noise_psk="YOUR_ENCRYPTION_KEY",
        )
        await api.connect(login=True)
    
        # Get API version
        print(api.api_version)
    
        # Show device details
        device_info = await api.device_info()
        print(device_info)
    
        # List all entities of the device
        entities = await api.list_entities_services()
        print(entities)
    
    asyncio.run(main())
  7. Use CLI tools for logs and discovery

    main

    The package includes two CLI tools:

    • aioesphomeapi-logs: Used for watching device logs.
    • aioesphomeapi-discover: Used for discovering devices on the network.
    aioesphomeapi-logs --help
    
    aioesphomeapi-discover --help
  8. Control Home Assistant Entities via Client

    main

    The Client class allows for subscribing to Home Assistant states and services, as well as manually sending state updates.

    Subscriptions

    • subscribe_home_assistant_states(on_state_sub: Callable[[str, str | None], None], ...): Subscribes to Home Assistant state changes.
    • subscribe_home_assistant_states_and_services(on_state: Callable[[EntityState], None], on_service_call: Callable[[HomeassistantServiceCall], None], on_state_sub: Callable[[str, str | None], None], ...): A highly efficient method that subscribes to all state updates and service calls in a single request by sending multiple subscription requests at once.

    Sending States

    • send_home_assistant_state(entity_id: str, attribute: str | None, state: str): Manually sends a Home Assistant state update to the device.
    # Example: Subscribing to all states and services efficiently
    await client.subscribe_home_assistant_states_and_services(
        on_state=lambda state: print(f"State: {state}"),
        on_service_call=lambda call: print(f"Service: {call}"),
        on_state_sub=lambda ent, state: print(f"Sub: {ent} is {state}")
    )
  9. List entities and services on a device

    main

    To discover what entities (sensors, lights, etc.) and services are available on the device, use:

    • await list_entities_services(): Returns a tuple of (list[EntityInfo], list[UserService]).
    • await device_info_and_list_entities(): A more efficient method that fetches both device info and the entity list in a single network packet to reduce latency. Returns (DeviceInfo, list[EntityInfo], list[UserService]).
    entities, services = await client.list_entities_services()
    for entity in entities:
        print(f"Entity: {entity.name}, State: {entity.state}")
  10. Control water heaters with water_heater_command()

    main

    Use water_heater_command() to control water heater entities. It supports setting the mode, target_temperature, and granular away or on states using WaterHeaterCommandField flags.

    client.water_heater_command(
        key=456,
        mode=1,
        target_temperature=50.0,
        away=True
    )
  11. Control various entity types via command methods

    main

    The Client class provides specific command methods for different ESPHome entity types:

    • number_command(key, state, device_id): Sets a numeric value.
    • date_command(key, year, month, day, device_id): Sets a date.
    • time_command(key, hour, minute, second, device_id): Sets a time.
    • datetime_command(key, epoch_seconds, device_id): Sets a datetime via epoch.
    • select_command(key, state, device_id): Sets a selection state (string).
    • siren_command(key, state, tone, volume, duration, device_id): Controls a siren.
    • button_command(key, device_id): Triggers a button press.
    • lock_command(key, command, code, device_id): Controls a lock.
    • valve_command(key, position, stop, device_id): Controls a valve.
    • text_command(key, state, device_id): Sets a text state.
    • update_command(key, command, device_id): Triggers an update.
    • alarm_control_panel_command(key, command, code, device_id): Controls an alarm panel.
  12. Manage Serial Proxy via Client

    main

    The Client class provides methods to interact with a serial proxy component on an ESPHome device. You can subscribe to or unsubscribe from serial proxy instances and flush the serial port.

    Note on Acknowledgments: If the device's API version is older than 1.16, the client will send the request but will not wait for an acknowledgment (returning None). If the device lacks a proxy component entirely, calls will raise a TimeoutAPIError.

    Serial Proxy Methods

    • serial_proxy_subscribe_await_response(instance: int, timeout: float = 10.0): Subscribes to a specific serial proxy instance and waits for confirmation.
    • serial_proxy_unsubscribe_await_response(instance: int, timeout: float = 10.0): Unsubscribes from a specific serial proxy instance and waits for confirmation.
    • serial_proxy_flush(instance: int, timeout: float = 10.0): Flushes the serial port and awaits confirmation.

    Z-Wave Proxy Methods

    • zwave_proxy_subscribe(): Synchronously sends a subscription request for the Z-Wave proxy.
    • zwave_proxy_unsubscribe(): Synchronously sends an unsubscription request.
    • zwave_proxy_subscribe_await_response(timeout: float = 10.0): Subscribes and awaits confirmation.
    • zwave_proxy_unsubscribe_await_response(timeout: float = 10.0): Unsubscribes and awaits confirmation.
    # Example: Subscribing to a serial proxy instance
    await client.serial_proxy_subscribe_await_response(instance=1)
    
    # Example: Flushing a serial port
    await client.serial_proxy_flush(instance=1)