esphome-native-api

Crates.ioesphome-native-api
lib.rsesphome-native-api
version2.0.6
created_at2025-04-26 22:58:09.569413+00
updated_at2026-01-17 00:13:06.134719+00
descriptionRust implementation of the ESPHome native API for communication with ESPHome devices, supporting both encrypted and plaintext connections.
homepagehttps://github.com/UbiHome/esphome-native-api
repositoryhttps://github.com/UbiHome/esphome-native-api
max_upload_size
id1650658
size6,176,383
(DanielHabenicht)

documentation

https://docs.rs/esphome-native-api

README

Documentation | GitHub | Crate | docs.rs


Rust Crate for the esphome native api

Implementation of the esphome native api for Rust.

This is still work in progress, so the API surface may change. But it is already quite usable. Just try the examples. The implementation is already used by UbiHome to make OS based devices available to Home Assistant.

Features

  • Full support for ESPHome native API protocol, including encryption. The crate can be used for Server and Client implementations.

  • Support for multiple ESPHome versions via feature flags (not yet implemented)

Usage

cargo add esphome_native_api

Look at the examples folder for reference implementations, e.g. encrypted_server.rs.

Version Compatibility

This crate only supports one ESPHome protocol version (marked by the default feature flag).

If you only need the Proto Messages you can install the crate with the feature flags enabled for the version you plan to use. Example:

[dependencies]
esphome-native-api = { version = "0.0.0", features = ["version_2025_12_1"] }

Basic Example

use esphome_native_api::esphomeapi::EspHomeApi;
use tokio::net::TcpStream;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to an ESPHome device
    let stream = TcpStream::connect("192.168.1.100:6053").await?;
    
    // Create API instance
    let mut api = EspHomeApi::builder()
        .name("my-client".to_string())
        .build();
    
    // Start communication
    let (tx, mut rx) = api.start(stream).await?;
    
    // Process messages
    while let Ok(message) = rx.recv().await {
        println!("Received: {:?}", message);
    }
    
    Ok(())
}

Using the Server API

The EspHomeServer provides a higher-level abstraction that manages entity keys internally (work in progress):

use esphome_native_api::esphomeserver::EspHomeServer;
use tokio::net::TcpStream;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stream = TcpStream::connect("192.168.1.100:6053").await?;
    
    let mut server = EspHomeServer::builder()
        .name("my-server".to_string())
        .build();
    
    let (tx, mut rx) = server.start(stream).await?;
    
    // Handle incoming messages
    while let Ok(message) = rx.recv().await {
        // Process message
    }
    
    Ok(())
}

Trivia

While reverse engineering the "missing" documentation of the API was reconstructed: https://ubihome.github.io/esphome-native-api/native_api/

Commit count: 115

cargo fmt