Documentation
¶
Overview ¶
Package esphomedevice implements the device side of the ESPHome native API, so a Go program can present itself to Home Assistant as an ESPHome device.
Index ¶
- Constants
- Variables
- func NewMessage(id uint32) (proto.Message, bool)
- type Action
- type Announce
- type Arg
- type ArgType
- type Base
- type BinarySensor
- type BluetoothFeature
- type BluetoothProxy
- func (b *BluetoothProxy) Active() bool
- func (b *BluetoothProxy) Advertise(ads []*api.BluetoothLERawAdvertisement) error
- func (b *BluetoothProxy) Handle(_ context.Context, c *Conn, msg proto.Message) error
- func (b *BluetoothProxy) Report(state ScannerState) error
- func (b *BluetoothProxy) Subscribed() bool
- type Button
- type Call
- type Camera
- type ColorMode
- type Conn
- type ConnCloser
- type Description
- type Device
- type Entities
- func (e *Entities) Actions() []Action
- func (e *Entities) Add(ents ...Entity) error
- func (e *Entities) AddActions(actions ...*Action) error
- func (e *Entities) Descriptions() []Description
- func (e *Entities) Handle(ctx context.Context, c *Conn, msg proto.Message) error
- func (e *Entities) Listen(fn func(State)) (cancel func())
- func (e *Entities) Press(object string) error
- func (e *Entities) Run(name string, c Call) (any, error)
- func (e *Entities) States() []State
- type Entity
- type EntityCategory
- type Event
- type ExternalWakeWord
- type Handler
- type HandlerFunc
- type Info
- type Light
- type LightState
- type MediaCommand
- type MediaFormat
- type MediaPlayer
- type MediaPlayerCommand
- type MediaPlayerFeature
- type MediaPlayerState
- type MessageInfo
- type Number
- type PSK
- type PipelineEvent
- type ScannerState
- type Select
- type Sensor
- type SensorStateClass
- type Server
- func (s *Server) Broadcast(msg proto.Message) error
- func (s *Server) Close() error
- func (s *Server) FireEvent(name string, data map[string]string) error
- func (s *Server) ListenAndServe(ctx context.Context) error
- func (s *Server) Log(level api.LogLevel, line string)
- func (s *Server) LogsSubscribed() bool
- func (s *Server) Reconnect()
- func (s *Server) Serve(ctx context.Context, ln net.Listener) error
- type State
- type Switch
- type Text
- type TextSensor
- type TimerEvent
- type Update
- type UpdateCommand
- type UpdateState
- type VoiceEvent
- type VoiceFeature
- type VoiceSatellite
- func (v *VoiceSatellite) APIAudio() bool
- func (v *VoiceSatellite) AnnounceFinished(success bool) error
- func (v *VoiceSatellite) ConnClosed(c *Conn)
- func (v *VoiceSatellite) EndAudio() error
- func (v *VoiceSatellite) Handle(ctx context.Context, c *Conn, msg proto.Message) error
- func (v *VoiceSatellite) SendAudio(data []byte) error
- func (v *VoiceSatellite) StartTurn(wakeWordPhrase string, settings *api.VoiceAssistantAudioSettings) error
- func (v *VoiceSatellite) StopTurn() error
- func (v *VoiceSatellite) Subscribed() bool
- type VoiceTimerEvent
- type WakeWord
Constants ¶
const ( APIVersionMajor = 1 APIVersionMinor = 12 )
API version we advertise. Major mismatches make Home Assistant disconnect; minor mismatches only warn.
const ( ScannerIdle = api.BluetoothScannerState_BLUETOOTH_SCANNER_STATE_IDLE ScannerStarting = api.BluetoothScannerState_BLUETOOTH_SCANNER_STATE_STARTING ScannerRunning = api.BluetoothScannerState_BLUETOOTH_SCANNER_STATE_RUNNING ScannerFailed = api.BluetoothScannerState_BLUETOOTH_SCANNER_STATE_FAILED ScannerStopping = api.BluetoothScannerState_BLUETOOTH_SCANNER_STATE_STOPPING ScannerStopped = api.BluetoothScannerState_BLUETOOTH_SCANNER_STATE_STOPPED )
const ( ColorModeOnOff = api.ColorMode_COLOR_MODE_ON_OFF ColorModeBrightness = api.ColorMode_COLOR_MODE_BRIGHTNESS ColorModeRGB = api.ColorMode_COLOR_MODE_RGB )
const ( MediaPlayerIdle = api.MediaPlayerState_MEDIA_PLAYER_STATE_IDLE MediaPlayerPlaying = api.MediaPlayerState_MEDIA_PLAYER_STATE_PLAYING MediaPlayerPaused = api.MediaPlayerState_MEDIA_PLAYER_STATE_PAUSED // MediaPlayerAnnouncing is in the protocol, and Home Assistant has no case for it: its state // mapper raises a KeyError on every update carrying it, so the entity stops updating. Report // playing instead. MediaPlayerAnnouncing = api.MediaPlayerState_MEDIA_PLAYER_STATE_ANNOUNCING )
const ( MediaPlayerPlay = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_PLAY MediaPlayerPause = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_PAUSE MediaPlayerStop = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_STOP MediaPlayerMute = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_MUTE MediaPlayerUnmute = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_UNMUTE MediaPlayerVolumeUp = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_VOLUME_UP MediaPlayerVolumeDown = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_VOLUME_DOWN MediaPlayerToggle = api.MediaPlayerCommand_MEDIA_PLAYER_COMMAND_TOGGLE )
The commands Home Assistant can send.
const ( TextPlain = api.TextMode_TEXT_MODE_TEXT TextPassword = api.TextMode_TEXT_MODE_PASSWORD )
How Home Assistant presents a text entity.
const ( NumberAuto = api.NumberMode_NUMBER_MODE_AUTO NumberBox = api.NumberMode_NUMBER_MODE_BOX NumberSlider = api.NumberMode_NUMBER_MODE_SLIDER )
Number is a tunable scalar, used for thresholds, gain and volume. How Home Assistant presents a number. Auto lets it decide, which gives a slider for a short range; Box asks for a typed value.
const ( UpdateNone = api.UpdateCommand_UPDATE_COMMAND_NONE UpdateInstall = api.UpdateCommand_UPDATE_COMMAND_UPDATE UpdateCheck = api.UpdateCommand_UPDATE_COMMAND_CHECK )
const ( CategoryNone = api.EntityCategory_ENTITY_CATEGORY_NONE CategoryConfig = api.EntityCategory_ENTITY_CATEGORY_CONFIG CategoryDiagnostic = api.EntityCategory_ENTITY_CATEGORY_DIAGNOSTIC )
const DefaultESPHomeVersion = "2026.5.1"
DefaultESPHomeVersion is reported when Info leaves ESPHomeVersion empty. It tracks a recent release, because Home Assistant compares the reported one against minimums of its own.
const DefaultPort = 6053
const DefaultVoiceFeatures = FeatureVoiceAssistant | FeatureAPIAudio
DefaultVoiceFeatures matches what ESPHome always sets. The rest are conditional there: Speaker when a speaker is configured, Timers when timers are, MultiChannelAudio when a second mic source exists, and Announce together with StartConversation when a media_player is present — ESPHome sets that pair as a unit.
Variables ¶
var ( ErrNoSubscriber = errors.New("esphomedevice: no voice assistant subscriber") ErrTurnInProgress = errors.New("esphomedevice: a voice turn is already running") )
var ErrDisconnect = errors.New("esphomedevice: client disconnected")
Functions ¶
Types ¶
type Action ¶
type Action struct {
Name string
Args []Arg
// Run does the work. What it returns becomes the answer; nil means there is none. An error reaches
// the caller as a failed action with its message.
Run func(Call) (any, error)
// Answers says the action has something to say. Home Assistant refuses return_response on one that
// does not, and refuses to wait for one that says it only ever answers.
Answers bool
}
An Action is something Home Assistant can call on the device, registered as esphome.<node>_<name>. Unlike an entity it holds no state: it takes arguments, does something, and may answer.
Answering is how a device serves what a state cannot carry — bytes, or a list. Home Assistant decodes the answer as JSON and gives it to whoever called with return_response, so Answers must marshal to a JSON object.
type Announce ¶
type Announce struct {
MediaID string
Text string
PreannounceMediaID string
StartConversation bool
}
Announce is Home Assistant asking the device to speak something outside a turn.
type ArgType ¶
type ArgType int
ArgType is what an argument carries. Home Assistant checks a call against these before it arrives.
type Base ¶
type Base struct {
// ObjectID is the stable identifier the entity key is derived from. Changing it
// makes Home Assistant treat the entity as a new one.
ObjectID string
Name string
Icon string
Category EntityCategory
DisabledByDefault bool
// DeviceID puts the entity on one of Info.Devices rather than the device itself.
DeviceID uint32
// contains filtered or unexported fields
}
Base carries the fields every entity domain shares.
type BinarySensor ¶
func (*BinarySensor) Get ¶
func (b *BinarySensor) Get() bool
func (*BinarySensor) Set ¶
func (b *BinarySensor) Set(v bool)
type BluetoothFeature ¶
type BluetoothFeature uint32
BluetoothFeature is what a proxy tells Home Assistant it can do, in Info.BluetoothFeatures.
const ( BluetoothPassiveScan BluetoothFeature = 1 << iota BluetoothActiveConnections BluetoothRemoteCaching BluetoothPairing BluetoothCacheClearing BluetoothRawAdvertisements BluetoothStateAndMode BluetoothConnectionParams )
type BluetoothProxy ¶
type BluetoothProxy struct {
// OnSubscribed fires when Home Assistant starts or stops wanting advertisements.
OnSubscribed func(subscribed bool)
// OnMode fires when Home Assistant chooses active or passive scanning. Active asks the
// controller to request scan responses, which is a transmission rather than a listen.
OnMode func(active bool)
// contains filtered or unexported fields
}
BluetoothProxy forwards BLE advertisements to Home Assistant.
Use it as a Handler, usually via Chain alongside Entities. Scanning belongs to the caller: this carries what the radio found and never touches hardware.
func (*BluetoothProxy) Active ¶
func (b *BluetoothProxy) Active() bool
Active reports whether Home Assistant asked for active scanning.
func (*BluetoothProxy) Advertise ¶
func (b *BluetoothProxy) Advertise(ads []*api.BluetoothLERawAdvertisement) error
Advertise sends a batch of reports, and gives up the subscription if the connection has gone: nothing tells a handler that a client disappeared, so a failed write is the notice.
func (*BluetoothProxy) Report ¶
func (b *BluetoothProxy) Report(state ScannerState) error
Report tells Home Assistant what the radio is doing.
func (*BluetoothProxy) Subscribed ¶
func (b *BluetoothProxy) Subscribed() bool
Subscribed reports whether Home Assistant is listening.
type Call ¶
type Call struct {
// contains filtered or unexported fields
}
Call is one invocation's arguments, by name.
type Camera ¶ added in v0.0.9
type Camera struct {
Base
// Image is asked for a JPEG when Home Assistant wants one. It runs on the connection's
// goroutine, so a camera that takes its time holds that connection up.
Image func() ([]byte, error)
}
Camera is a still picture Home Assistant asks for, rather than a state the device pushes.
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
Conn is a single Home Assistant connection. Writes are safe from multiple goroutines; the ESPHome transports carry a per-direction nonce, so frames must not interleave.
func (*Conn) ClientInfo ¶
ClientInfo reports the client's self-description from HelloRequest, e.g. "Home Assistant".
func (*Conn) LogsSubscribed ¶
LogsSubscribed reports whether the client asked for logs at all, whatever the level.
func (*Conn) StatesSubscribed ¶
StatesSubscribed reports whether the client asked for entity state updates. Pushing state before then is wasted work.
type ConnCloser ¶ added in v0.0.15
type ConnCloser interface{ ConnClosed(*Conn) }
type Description ¶ added in v0.0.17
type Description struct {
Object string `json:"id"`
Kind string `json:"kind"`
Info json.RawMessage `json:"info"`
}
type Device ¶
Device is a sub-device. ID must be non-zero and unique, since zero means the device itself.
type Entities ¶
type Entities struct {
// contains filtered or unexported fields
}
Entities holds the device's entity set and answers the messages that operate on it: ListEntities, the initial state dump after SubscribeStates, and the per-domain command requests. Use it as a Server's Handler.
Wrap it with Chain to combine with other handlers, such as a voice satellite.
func NewEntities ¶
func NewEntities() *Entities
func (*Entities) Add ¶
Add registers entities. A duplicate key means two of them share an ObjectID, which silently breaks state routing: whichever one Home Assistant hears about, updates from the other go nowhere. That is always a bug in the caller, so nothing is registered when it happens — the set is left as it was.
func (*Entities) AddActions ¶
AddActions registers what Home Assistant may call. Two actions of one name would leave one of them unreachable, so a duplicate registers nothing.
func (*Entities) Descriptions ¶ added in v0.0.17
func (e *Entities) Descriptions() []Description
type Entity ¶
type Entity interface {
// Object is the identifier the entity is known by, which is what a caller holding a list of
// entities can say about them: Key is a hash and the rest of the interface is unexported.
Object() string
Key() uint32
// contains filtered or unexported methods
}
Entity is one Home Assistant entity exposed by the device. Implementations live in this package; describe and state are unexported so the set stays closed.
type EntityCategory ¶
type EntityCategory = api.EntityCategory
type Event ¶
type Event struct {
Base
DeviceClass string
// Types are the event types this entity can emit. Home Assistant rejects any type not
// declared here.
Types []string
}
Event is something that happens rather than something with a state, such as a button press. Home Assistant records each occurrence and its type, so automations can trigger on them.
type ExternalWakeWord ¶
type ExternalWakeWord struct {
ID string
Phrase string
TrainedLanguages []string
ModelType string
Size uint32
Hash string
URL string
}
ExternalWakeWord is a model Home Assistant is offering, served from its custom_wake_words directory. The device downloads URL and should check the result against Hash and Size before using it.
type Handler ¶
Handler receives messages the connection does not answer itself. Returning messages from Handle sends them back on the same connection.
Handle runs on the connection's read loop, so blocking work belongs in a goroutine. Messages are delivered in order, so the library cannot dispatch them concurrently.
func Chain ¶
Chain runs handlers in order, stopping at the first error.
It passes bindServer through to whichever handlers want it. Without that, chaining Entities with anything else silently loses every state update: the server binds its handler by type, a plain func is not bindable, and only the states sent on connect would ever reach Home Assistant.
type HandlerFunc ¶
HandlerFunc adapts a function to Handler.
type Info ¶
type Info struct {
Name string
FriendlyName string
MACAddress string
Manufacturer string
Model string
Version string
SuggestedArea string
// ProjectName is "<manufacturer>.<model>"; Home Assistant splits it at the dot into those two.
ProjectName string
// ESPHomeVersion is the ESPHome release to report being. It describes the protocol spoken rather
// than the program speaking it, which is why it is separate from Version. Empty reports
// DefaultESPHomeVersion.
ESPHomeVersion string
// VoiceFeatures advertises voice satellite capability. Leave zero on devices that
// aren't satellites; Home Assistant won't offer voice for them.
VoiceFeatures VoiceFeature
// BluetoothFeatures advertises Bluetooth proxy capability. Leave zero on devices that are not
// proxies; Home Assistant won't register a scanner for them.
BluetoothFeatures BluetoothFeature
// Devices are sub-devices entities can be assigned to, by Base.DeviceID. Home Assistant shows
// each as its own device page under this one.
Devices []Device
}
Info is what a device reports in response to DeviceInfoRequest. Name is also the hostname Home Assistant identifies the device by, so it must be stable.
type Light ¶
type Light struct {
Base
SupportedColorModes []ColorMode
Effects []string
// OnCommand runs when Home Assistant changes the light. If nil the command is
// applied directly. When the device drives the ring itself, the callback is where
// precedence between satellite state and user control gets resolved.
OnCommand func(LightState)
// contains filtered or unexported fields
}
Light is an RGB light. For EchoLocal this is the LED ring, which the device also drives from satellite state — see the precedence note on OnCommand.
func (*Light) Get ¶
func (l *Light) Get() LightState
func (*Light) Set ¶
func (l *Light) Set(s LightState)
type LightState ¶
type LightState struct {
On bool
Brightness float32
ColorMode ColorMode
Red float32
Green float32
Blue float32
Effect string
// TransitionLength is what Home Assistant asked for, in milliseconds. Only set on
// commands; the device decides whether to honour it.
TransitionLength uint32
}
LightState is the full light state. Colour channels and brightness are 0..1.
type MediaCommand ¶
type MediaCommand struct {
HasCommand bool
Command MediaPlayerCommand
HasVolume bool
Volume float32
HasMediaURL bool
MediaURL string
// Announcement marks TTS and alerts, which should duck or interrupt rather than
// replace whatever is playing.
HasAnnouncement bool
Announcement bool
}
MediaCommand is one media_player command. Only the fields Home Assistant set are populated, indicated by the Has* flags.
type MediaFormat ¶
type MediaFormat struct {
// Format is a container or codec name as ffmpeg knows it, such as "wav" or "flac".
Format string
SampleRate uint32
Channels uint32
SampleBytes uint32
// Announcement marks this as the format for announcements rather than ordinary media.
Announcement bool
}
MediaFormat is audio the device can play. Home Assistant converts a source to the first format matching the purpose, with ffmpeg, so advertising something simple avoids needing a decoder.
type MediaPlayer ¶
type MediaPlayer struct {
Base
SupportsPause bool
// SupportedFormats is what Home Assistant should convert to. With none, it sends whatever the
// source happens to be.
SupportedFormats []MediaFormat
// Features is what Home Assistant offers in the UI. Pause is added from SupportsPause, which
// older versions read instead of the flags.
Features MediaPlayerFeature
OnCommand func(MediaCommand)
// contains filtered or unexported fields
}
func (*MediaPlayer) Muted ¶
func (p *MediaPlayer) Muted() bool
func (*MediaPlayer) SetMuted ¶
func (p *MediaPlayer) SetMuted(m bool)
func (*MediaPlayer) SetState ¶
func (p *MediaPlayer) SetState(s MediaPlayerState)
func (*MediaPlayer) SetVolume ¶
func (p *MediaPlayer) SetVolume(v float32)
func (*MediaPlayer) State ¶
func (p *MediaPlayer) State() MediaPlayerState
func (*MediaPlayer) Volume ¶
func (p *MediaPlayer) Volume() float32
type MediaPlayerCommand ¶
type MediaPlayerCommand = api.MediaPlayerCommand
type MediaPlayerFeature ¶
type MediaPlayerFeature uint32
MediaPlayerFeature is what the player tells Home Assistant it can do, sent as feature_flags. Home Assistant computes the entity's supported features from this, so a player that sends none gets no controls in the UI. The bits are Home Assistant's MediaPlayerEntityFeature values.
const ( MediaPlayerFeaturePause MediaPlayerFeature = 1 << iota MediaPlayerFeatureSeek MediaPlayerFeatureVolumeSet MediaPlayerFeatureVolumeMute MediaPlayerFeaturePreviousTrack MediaPlayerFeatureNextTrack MediaPlayerFeatureTurnOn MediaPlayerFeatureTurnOff MediaPlayerFeaturePlayMedia MediaPlayerFeatureVolumeStep MediaPlayerFeatureSelectSource MediaPlayerFeatureStop MediaPlayerFeatureClearPlaylist MediaPlayerFeaturePlay MediaPlayerFeatureShuffleSet MediaPlayerFeatureSelectSound MediaPlayerFeatureBrowseMedia MediaPlayerFeatureRepeatSet MediaPlayerFeatureGrouping MediaPlayerFeatureAnnounce MediaPlayerFeatureEnqueue )
type MediaPlayerState ¶
type MediaPlayerState = api.MediaPlayerState
type MessageInfo ¶
type MessageInfo struct {
ID uint32
Source api.APISourceType
Name protoreflect.FullName
Type protoreflect.MessageType
}
MessageInfo describes one API message as declared in api.proto. ID is the value of the (id) option, which is what travels on the wire ahead of the payload.
func LookupID ¶
func LookupID(id uint32) (MessageInfo, bool)
func Messages ¶
func Messages() []MessageInfo
func (MessageInfo) FromClient ¶
func (m MessageInfo) FromClient() bool
FromClient reports whether Home Assistant is the sender.
func (MessageInfo) FromDevice ¶
func (m MessageInfo) FromDevice() bool
FromDevice reports whether the device is the sender.
type Number ¶
type PSK ¶
type PSK [32]byte
PSK is the 32-byte Noise pre-shared key. Possession of it is the only identity the protocol has, so it must be unique per device. All-zeros is reserved to mark a device unprovisioned — see Unprovisioned.
func GeneratePSK ¶
func Unprovisioned ¶
func Unprovisioned() *PSK
Unprovisioned returns the reserved all-zeros key. The connection is still Noise, but anyone can complete the handshake: passive-sniffing protection, no authentication.
type PipelineEvent ¶
type PipelineEvent struct {
Type VoiceEvent
Data map[string]string
}
PipelineEvent is a stage transition reported by Home Assistant's pipeline, with the key/value pairs that stage carried (transcript text, TTS url, error details).
type ScannerState ¶
type ScannerState = api.BluetoothScannerState
ScannerState is what the radio is doing.
type Select ¶
type Select struct {
Base
Options []string
// OnCommand runs when Home Assistant picks an option. If nil the new value is
// applied directly; if set, the callback owns whether to call Set.
OnCommand func(value string)
// contains filtered or unexported fields
}
Select is a fixed list of options, used for things like the active wake word.
func (*Select) SetOptions ¶ added in v0.0.13
type Sensor ¶
type Sensor struct {
Base
// Unit is what the number is in, as Home Assistant spells it: "kB", "%", "dB".
Unit string
// DeviceClass is what kind of quantity it is, which is what lets Home Assistant convert it.
DeviceClass string
// StateClass says how it accumulates. Measurement is the usual answer for anything that goes up
// and down; the default is none, which keeps it out of long-term statistics.
StateClass SensorStateClass
// Decimals is how many places Home Assistant shows.
Decimals int32
// contains filtered or unexported fields
}
Sensor is a number Home Assistant reads. Unlike a TextSensor it is recorded and graphed, and with a device class Home Assistant will convert it for display — a size reported in kB can be shown in MB without the device knowing.
The protocol carries the state as a float32, so a value is exact to 24 bits: report a size in the unit it will be read in rather than in bytes, or a large one lands on the nearest representable multiple.
type SensorStateClass ¶
type SensorStateClass int32
SensorStateClass is how a sensor's value accumulates over time.
const ( StateClassNone SensorStateClass = iota StateClassMeasurement StateClassTotalIncreasing StateClassTotal )
type Server ¶
type Server struct {
Info Info
// PSK selects the transport, and the three options serve different purposes:
//
// a real key authenticated Noise — production
// Unprovisioned() Noise with the reserved zero key, so Home Assistant can push a
// real one; needs aioesphomeapi 45.6.0 or newer
// nil plaintext — readable on the wire, so useful for debugging,
// but ESPHome is removing it in 2027.2.0
PSK *PSK
// OnSetEncryptionKey handles Home Assistant provisioning a real key over a zero-PSK
// connection. Leave nil to refuse, which is right when keys are installed
// out-of-band.
OnSetEncryptionKey func(PSK) error
// OnSubscribed fires when a client asks for entity state, which is the first moment
// anything sent to it will arrive. Something the device wants to report but could not
// while it was alone waits for this.
//
// It fires once per connection, on that connection's read loop, so it must not block.
OnSubscribed func()
// WriteTimeout bounds one write. Zero leaves writes unbounded, so a client that stops reading
// blocks the write lock until TCP gives up and every other sender waits behind it.
WriteTimeout time.Duration
// Addr defaults to ":6053".
Addr string
Handler Handler
Logger *slog.Logger
// contains filtered or unexported fields
}
func (*Server) Broadcast ¶
Broadcast sends a message to every connection that has subscribed to state updates, which is how entity state is pushed.
func (*Server) FireEvent ¶
FireEvent asks Home Assistant to put an event on its bus. The name is passed whole and must be under the esphome domain, which is the only one Home Assistant accepts here.
Values are strings because the wire carries no other kind. Home Assistant adds the device id itself, so an event says which device it came from without being told.
func (*Server) ListenAndServe ¶
ListenAndServe accepts connections until ctx is cancelled or Close is called.
func (*Server) Log ¶
Log sends one line to every client that subscribed at this level or louder. A write that fails is left to the read loop to notice, since logging is not worth failing anything else over.
func (*Server) LogsSubscribed ¶
LogsSubscribed reports whether any client is taking logs. Lines produced before one is have nowhere to go, so a caller holding a backlog can wait rather than discard it.
func (*Server) Reconnect ¶
func (s *Server) Reconnect()
Reconnect drops every client, so Home Assistant reconnects and reads the device afresh.
Some of what a device reports is only fetched once per connection — the voice satellite's available wake words among it — and there is no message for revising it. When that changes, the connection is the only lever: Home Assistant reconnects on its own, within seconds. A connection in the middle of a message closes once that message is answered.
type State ¶ added in v0.0.17
type State struct {
Object string `json:"id"`
Value json.RawMessage `json:"state"`
}
type Switch ¶
type Switch struct {
Base
DeviceClass string
// Assumed tells Home Assistant the device cannot confirm the state, so it should offer
// separate on and off controls rather than a toggle.
Assumed bool
// OnCommand runs when Home Assistant sets the switch. If nil the new value is applied
// directly; if set, the callback owns whether to call Set.
OnCommand func(value bool)
// contains filtered or unexported fields
}
Switch is a boolean Home Assistant can both read and set, for state the device owns but the user can change from either end — a microphone mute being the obvious one.
type Text ¶ added in v0.0.11
type Text struct {
Base
MinLength, MaxLength uint32
Pattern string
Mode api.TextMode
// OnCommand runs when Home Assistant sets a value. If nil the new value is applied directly; if
// set, the callback owns whether to call Set.
OnCommand func(value string)
// contains filtered or unexported fields
}
Text is a string Home Assistant can set.
type TextSensor ¶
TextSensor is a string Home Assistant reads. With no unit or state class its changes appear in the logbook, unlike a numeric sensor's. Home Assistant truncates a state at 255 characters.
func (*TextSensor) Get ¶
func (t *TextSensor) Get() string
func (*TextSensor) Set ¶
func (t *TextSensor) Set(v string)
type TimerEvent ¶
type Update ¶
type Update struct {
Base
DeviceClass string
// OnCommand runs when Home Assistant asks to install or check for an update.
OnCommand func(UpdateCommand)
// contains filtered or unexported fields
}
Update is a firmware update entity. ESPHome devices expose one even when they never self-update, and Home Assistant's satellite setup wizard expects it.
func (*Update) Get ¶
func (u *Update) Get() UpdateState
func (*Update) Set ¶
func (u *Update) Set(s UpdateState)
type UpdateCommand ¶
type UpdateCommand = api.UpdateCommand
type UpdateState ¶
type UpdateState struct {
CurrentVersion string
LatestVersion string
Title string
ReleaseSummary string
ReleaseURL string
InProgress bool
Progress float32
}
UpdateState is the firmware state reported to Home Assistant. An update is offered when LatestVersion differs from CurrentVersion.
type VoiceEvent ¶
type VoiceEvent = api.VoiceAssistantEvent
type VoiceFeature ¶
type VoiceFeature uint32
VoiceFeature flags go in DeviceInfoResponse.voice_assistant_feature_flags and tell Home Assistant what the satellite can do.
The enum lives in ESPHome's C++ (voice_assistant.h), not api.proto, so these are transcribed from there rather than generated.
const ( FeatureVoiceAssistant VoiceFeature = 1 << 0 FeatureSpeaker VoiceFeature = 1 << 1 FeatureAPIAudio VoiceFeature = 1 << 2 FeatureTimers VoiceFeature = 1 << 3 FeatureAnnounce VoiceFeature = 1 << 4 FeatureStartConversation VoiceFeature = 1 << 5 FeatureMultiChannelAudio VoiceFeature = 1 << 6 )
type VoiceSatellite ¶
type VoiceSatellite struct {
AvailableWakeWords []WakeWord
ActiveWakeWords []string
MaxActiveWakeWords uint32
// OnPipelineEvent reports stage transitions: STT text, TTS urls, errors.
OnPipelineEvent func(PipelineEvent)
// OnTTSAudio receives audio to play. Only used when Home Assistant negotiated
// audio over the API, which it signals in SubscribeVoiceAssistantRequest.
OnTTSAudio func(data []byte, end bool)
// OnStartRequestAccepted fires with Home Assistant's answer to StartTurn. A
// non-zero port means it wants the legacy UDP audio path instead.
OnStartRequestAccepted func(port uint32, err bool)
OnAnnounce func(Announce)
OnTimer func(TimerEvent)
// OnSubscribed fires when Home Assistant starts or stops listening for voice turns. Until it
// has subscribed, a wake word cannot be served at all, so this is what readiness means for a
// satellite — and it is worth showing, since the device otherwise looks broken rather than
// unattached.
OnSubscribed func(subscribed bool)
// OnSetActiveWakeWords fires when Home Assistant changes the selection.
OnSetActiveWakeWords func(ids []string)
// OnExternalWakeWords fires when Home Assistant offers models from its
// custom_wake_words directory. Returning the ones the device has adopted adds them
// to the advertised list; return nil to ignore the offer.
//
// It runs before the configuration reply is sent, so a slow download belongs in a
// goroutine — adopt on the next request instead of blocking this one.
OnExternalWakeWords func([]ExternalWakeWord) []WakeWord
// contains filtered or unexported fields
}
VoiceSatellite implements the device half of the voice_assistant flow. The device initiates every turn, so nothing here is driven by Home Assistant polling — which is what makes a pre-flight arbitration check invisible to the protocol.
Use it as a Handler, usually via Chain alongside Entities.
func (*VoiceSatellite) APIAudio ¶
func (v *VoiceSatellite) APIAudio() bool
APIAudio reports whether audio travels over the API connection rather than the legacy UDP path.
func (*VoiceSatellite) AnnounceFinished ¶
func (v *VoiceSatellite) AnnounceFinished(success bool) error
AnnounceFinished reports the outcome of an Announce back to Home Assistant.
func (*VoiceSatellite) ConnClosed ¶ added in v0.0.15
func (v *VoiceSatellite) ConnClosed(c *Conn)
func (*VoiceSatellite) EndAudio ¶
func (v *VoiceSatellite) EndAudio() error
EndAudio marks the end of captured audio for the turn.
func (*VoiceSatellite) SendAudio ¶
func (v *VoiceSatellite) SendAudio(data []byte) error
SendAudio streams captured audio for the active turn.
func (*VoiceSatellite) StartTurn ¶
func (v *VoiceSatellite) StartTurn(wakeWordPhrase string, settings *api.VoiceAssistantAudioSettings) error
StartTurn tells Home Assistant a wake word fired and a turn is beginning. The device decides when to call this, so any pre-flight work — such as winning an arbitration claim — happens before it and is invisible to Home Assistant.
func (*VoiceSatellite) StopTurn ¶
func (v *VoiceSatellite) StopTurn() error
StopTurn ends the current turn early.
func (*VoiceSatellite) Subscribed ¶
func (v *VoiceSatellite) Subscribed() bool
Subscribed reports whether Home Assistant is listening for voice turns.
type VoiceTimerEvent ¶
type VoiceTimerEvent = api.VoiceAssistantTimerEvent
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
wire
Package wire implements the ESPHome native API transport: frame codecs for the plaintext and Noise-encrypted variants, from the device (responder) side.
|
Package wire implements the ESPHome native API transport: frame codecs for the plaintext and Noise-encrypted variants, from the device (responder) side. |
|
Package mdns advertises a device over mDNS so Home Assistant discovers it.
|
Package mdns advertises a device over mDNS so Home Assistant discovers it. |