Documentation Index Fetch the complete documentation index at: https://mintlify.com/richard87/esphome-apiclient/llms.txt
Use this file to discover all available pages before exploring further.
Prerequisites
Before you begin, make sure you have:
Go 1.21 or later installed
An ESPHome device with the Native API component enabled
The device’s hostname or IP address and port (default port is 6053)
The encryption.key value from your ESPHome YAML (if the device uses encrypted connections)
The encryption key is a base64-encoded 32-byte string found in the api: section of your ESPHome YAML config: api :
encryption :
key : "your-base64-encoded-key-here"
Copy the value of key exactly as it appears.
Steps
Install the module
Add the library to your Go project: go get github.com/richard87/esphome-apiclient
Import the packages
Your Go file needs two import paths — the main client package and the generated protobuf types: import (
" context "
" fmt "
" log "
" time "
esphome " github.com/richard87/esphome-apiclient "
" github.com/richard87/esphome-apiclient/pb "
" google.golang.org/protobuf/proto "
)
Connect with DialWithContext
Use DialWithContext to connect with a parent context. The function signature is: func DialWithContext ( ctx context . Context , address string , timeout time . Duration , opts ... Option ) ( * Client , error )
Or use Dial if you don’t need context cancellation: func Dial ( address string , timeout time . Duration , opts ... Option ) ( * Client , error )
Connect to your device: ctx := context . Background ()
client , err := esphome . DialWithContext ( ctx , "mydevice.local:6053" , 5 * time . Second ,
esphome . WithEncryptionKey ( "base64-noise-psk" ),
esphome . WithClientInfo ( "my-app" ),
esphome . WithReconnect ( 10 * time . Second ),
)
if err != nil {
log . Fatal ( err )
}
defer client . Close ()
If your device does not use encryption, omit WithEncryptionKey. The client will connect using a plain (unencrypted) TCP connection instead.
Get device info
Fetch basic information about the connected device: info , err := client . DeviceInfo ()
if err != nil {
log . Fatal ( err )
}
fmt . Printf ( "Connected to %s (ESPHome %s ) \n " , info . Name , info . EsphomeVersion )
List entities and subscribe to states
Discover the device’s entities, then subscribe to live state updates: // Discover entities and populate the entity registry
client . ListEntities ()
for _ , s := range client . Entities (). Sensors () {
fmt . Printf ( " sensor: %s ( %s ) \n " , s . Name , s . UnitOfMeasurement )
}
// Subscribe to state updates
client . SubscribeStates ( func ( msg proto . Message ) {
switch m := msg .( type ) {
case * pb . SensorStateResponse :
entity := client . Entities (). ByKey ( m . Key )
fmt . Printf ( "sensor %s = %.4g \n " , entity . GetName (), m . State )
case * pb . SwitchStateResponse :
fmt . Printf ( "switch 0x %08X = %v \n " , m . Key , m . State )
}
})
Send a command
Control a switch by its key: client . SetSwitch ( 0x 12345678 , true )
The switch key is a uint32 that identifies the entity on the device. You can find keys by listing entities and inspecting the Key field of each entity response.
Complete example
Here is a full working program that puts all the steps together:
package main
import (
" context "
" fmt "
" log "
" time "
esphome " github.com/richard87/esphome-apiclient "
" github.com/richard87/esphome-apiclient/pb "
" google.golang.org/protobuf/proto "
)
func main () {
ctx := context . Background ()
client , err := esphome . DialWithContext ( ctx , "mydevice.local:6053" , 5 * time . Second ,
esphome . WithEncryptionKey ( "base64-noise-psk" ),
esphome . WithClientInfo ( "my-app" ),
esphome . WithReconnect ( 10 * time . Second ),
)
if err != nil {
log . Fatal ( err )
}
defer client . Close ()
// Get device info
info , _ := client . DeviceInfo ()
fmt . Printf ( "Connected to %s (ESPHome %s ) \n " , info . Name , info . EsphomeVersion )
// Discover entities
client . ListEntities ()
for _ , s := range client . Entities (). Sensors () {
fmt . Printf ( " sensor: %s ( %s ) \n " , s . Name , s . UnitOfMeasurement )
}
// Stream state updates
client . SubscribeStates ( func ( msg proto . Message ) {
switch m := msg .( type ) {
case * pb . SensorStateResponse :
entity := client . Entities (). ByKey ( m . Key )
fmt . Printf ( "sensor %s = %.4g \n " , entity . GetName (), m . State )
case * pb . SwitchStateResponse :
fmt . Printf ( "switch 0x %08X = %v \n " , m . Key , m . State )
}
})
// Send a command
client . SetSwitch ( 0x 12345678 , true )
<- ctx . Done ()
}
Next steps
Library guide Learn more about connecting, entity discovery, and subscriptions.
API reference Full reference for all public types and methods.
CLI tool Use the bundled CLI to inspect devices from the terminal.
Bluetooth proxy Use ESPHome devices as BLE proxies for advertisement scanning and GATT.