[voice_assistant] Download wake word models advertised by Home Assistant

Home Assistant sends the list of external wake words it knows about with
every configuration request. This picks up the ones micro_wake_word can
run, downloads them on demand, and hands them to micro_wake_word so they
can be activated like a compiled-in model.

Set the new http_request option to turn this on. It requires
micro_wake_word to be configured, and pulls in the sha256 and json
components used to verify a download and read its manifest.

How it works:

- The advertised wake words are cached on each configuration request, so
  entries Home Assistant stops sending drop out and their models are
  unloaded.
- When Home Assistant activates a wake word whose model is not loaded
  yet, the model is queued and fetched by a background task. The wake
  word is reported as active straight away so the UI reflects the request
  while the download runs.
- Downloads are checked against the size and hash from the manifest, and
  the model has to use the same feature step size as the frontend.
- A model that fails to load is stored as disabled so it is not retried
  on every boot.
- Loaded models are restored after a reboot.

The configuration response now comes entirely from voice_assistant, which
merges the compiled-in models with the cached external wake words, so the
API no longer needs to append them itself.
This commit is contained in:
Kevin Ahrendt
2026-08-10 08:11:47 -04:00
parent 25cb440005
commit 046d030d36
6 changed files with 627 additions and 14 deletions
@@ -0,0 +1,49 @@
substitutions:
i2s_din_pin: GPIO34
i2s_dout_pin: GPIO32
packages:
i2s_audio: !include ../../test_build_components/common/i2s_audio/esp32-idf.yaml
wifi:
ssid: MySSID
password: password1
api:
# Runtime wake word model downloading pulls in sha256 + json via AUTO_LOAD and defines
# USE_VOICE_ASSISTANT_RUNTIME_MODEL, compiling the whole download/validation code path.
http_request:
id: model_http_request
verify_ssl: false
micro_wake_word:
id: mww_id
microphone: va_mic_id_external
# Empty models list: exercises the optional-models path. Wake words arrive at runtime from Home Assistant.
models: []
microphone:
- platform: i2s_audio
id: va_mic_id_external
i2s_audio_id: i2s_audio_bus
i2s_din_pin: ${i2s_din_pin}
adc_type: external
pdm: false
speaker:
- platform: i2s_audio
id: va_speaker_id
i2s_audio_id: i2s_audio_bus
dac_type: external
i2s_dout_pin: ${i2s_dout_pin}
voice_assistant:
microphone:
microphone: va_mic_id_external
gain_factor: 4
channels: 0
speaker: va_speaker_id
micro_wake_word: mww_id
http_request_id: model_http_request
conversation_timeout: 60s