diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c56e6282..5d6b195a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,7 @@ concurrency: env: FIRMWARES: esp-web-tools esphome-web voice-assistant bluetooth-proxy media-player + VOICE_ASSISTANT_VERSION: beta jobs: prepare: @@ -43,6 +44,12 @@ jobs: device=${device##*/} device=${device%.yaml} version="latest" + fw=${firmware//-/_} + fw=${fw^^} + fw_version=${fw}_VERSION + if [[ -n "${!fw_version}" ]]; then + version=${!fw_version} + fi matrix="$matrix{\"firmware\":\"$firmware\",\"device\":\"$device\", \"version\":\"$version\"}," done done diff --git a/voice-assistant/esp32-s3-box-3.yaml b/voice-assistant/esp32-s3-box-3.yaml index e7f5f451..bb958673 100644 --- a/voice-assistant/esp32-s3-box-3.yaml +++ b/voice-assistant/esp32-s3-box-3.yaml @@ -24,6 +24,8 @@ substitutions: voice_assist_error_phase_id: "11" voice_assist_muted_phase_id: "12" + micro_wake_word_model: okay_nabu + esphome: name: ${name} friendly_name: ${friendly_name} @@ -152,6 +154,11 @@ speaker: - platform: esp_adf id: box_speaker +micro_wake_word: + model: ${micro_wake_word_model} + on_wake_word_detected: + - voice_assistant.start + voice_assistant: id: va microphone: box_mic @@ -173,6 +180,17 @@ voice_assistant: on_tts_stream_end: - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - script.execute: draw_display + on_end: + - if: + condition: + and: + - switch.is_off: mute + - lambda: return id(wake_word_engine_location).state == "On device"; + then: + - wait_until: + not: + voice_assistant.is_running: + - micro_wake_word.start: on_error: - if: condition: @@ -196,14 +214,35 @@ voice_assistant: then: - wait_until: not: ble.enabled - - voice_assistant.start_continuous: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.start - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; else: - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - lambda: id(init_in_progress) = false; - script.execute: draw_display on_client_disconnected: - - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.stop + - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; - script.execute: draw_display script: @@ -272,26 +311,71 @@ switch: - if: condition: lambda: return !id(init_in_progress); - then: - - lambda: id(va).set_use_wake_word(true); + then: - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - if: condition: not: - voice_assistant.is_running then: - - voice_assistant.start_continuous + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.start - script.execute: draw_display on_turn_on: - if: condition: lambda: return !id(init_in_progress); - then: - - voice_assistant.stop + then: - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop + - micro_wake_word.stop - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - script.execute: draw_display +select: + - platform: template + entity_category: config + name: Wake word engine location + id: wake_word_engine_location + optimistic: True + restore_value: True + options: + - In Home Assistant + - On device + initial_option: On device + on_value: + - wait_until: + lambda: return id(voice_assistant_phase) == ${voice_assist_muted_phase_id} || id(voice_assistant_phase) == ${voice_assist_idle_phase_id}; + - if: + condition: + lambda: return x == "In Home Assistant"; + then: + - micro_wake_word.stop + - delay: 500ms + - if: + condition: + switch.is_off: mute + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous: + - if: + condition: + lambda: return x == "On device"; + then: + - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop + - delay: 500ms + - micro_wake_word.start + globals: - id: init_in_progress type: bool diff --git a/voice-assistant/esp32-s3-box-lite.yaml b/voice-assistant/esp32-s3-box-lite.yaml index 452b86ea..6175aacf 100644 --- a/voice-assistant/esp32-s3-box-lite.yaml +++ b/voice-assistant/esp32-s3-box-lite.yaml @@ -23,6 +23,8 @@ substitutions: voice_assist_error_phase_id: "11" voice_assist_muted_phase_id: "12" + micro_wake_word_model: okay_nabu + esphome: name: ${name} friendly_name: ${friendly_name} @@ -199,6 +201,11 @@ speaker: - platform: esp_adf id: box_speaker +micro_wake_word: + model: ${micro_wake_word_model} + on_wake_word_detected: + - voice_assistant.start + voice_assistant: id: va microphone: box_mic @@ -220,6 +227,17 @@ voice_assistant: on_tts_stream_end: - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - script.execute: draw_display + on_end: + - if: + condition: + and: + - switch.is_off: mute + - lambda: return id(wake_word_engine_location).state == "On device"; + then: + - wait_until: + not: + voice_assistant.is_running: + - micro_wake_word.start: on_error: - if: condition: @@ -243,14 +261,35 @@ voice_assistant: then: - wait_until: not: ble.enabled - - voice_assistant.start_continuous: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.start - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; else: - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - lambda: id(init_in_progress) = false; - script.execute: draw_display on_client_disconnected: - - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.stop + - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; - script.execute: draw_display script: @@ -319,26 +358,71 @@ switch: - if: condition: lambda: return !id(init_in_progress); - then: - - lambda: id(va).set_use_wake_word(true); + then: - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - if: condition: not: - voice_assistant.is_running then: - - voice_assistant.start_continuous + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.start - script.execute: draw_display on_turn_on: - if: condition: lambda: return !id(init_in_progress); - then: - - voice_assistant.stop + then: - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop + - micro_wake_word.stop - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - script.execute: draw_display +select: + - platform: template + entity_category: config + name: Wake word engine location + id: wake_word_engine_location + optimistic: True + restore_value: True + options: + - In Home Assistant + - On device + initial_option: On device + on_value: + - wait_until: + lambda: return id(voice_assistant_phase) == ${voice_assist_muted_phase_id} || id(voice_assistant_phase) == ${voice_assist_idle_phase_id}; + - if: + condition: + lambda: return x == "In Home Assistant"; + then: + - micro_wake_word.stop + - delay: 500ms + - if: + condition: + switch.is_off: mute + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous: + - if: + condition: + lambda: return x == "On device"; + then: + - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop + - delay: 500ms + - micro_wake_word.start + globals: - id: init_in_progress type: bool diff --git a/voice-assistant/esp32-s3-box.yaml b/voice-assistant/esp32-s3-box.yaml index 58117ce3..69df6b3c 100644 --- a/voice-assistant/esp32-s3-box.yaml +++ b/voice-assistant/esp32-s3-box.yaml @@ -24,6 +24,8 @@ substitutions: voice_assist_error_phase_id: '11' voice_assist_muted_phase_id: '12' + micro_wake_word_model: okay_nabu + esphome: name: ${name} friendly_name: ${friendly_name} @@ -145,6 +147,11 @@ speaker: - platform: esp_adf id: box_speaker +micro_wake_word: + model: ${micro_wake_word_model} + on_wake_word_detected: + - voice_assistant.start + voice_assistant: id: va microphone: box_mic @@ -166,6 +173,17 @@ voice_assistant: on_tts_stream_end: - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - script.execute: draw_display + on_end: + - if: + condition: + and: + - switch.is_off: mute + - lambda: return id(wake_word_engine_location).state == "On device"; + then: + - wait_until: + not: + voice_assistant.is_running: + - micro_wake_word.start: on_error: - if: condition: @@ -189,13 +207,34 @@ voice_assistant: then: - wait_until: not: ble.enabled - - voice_assistant.start_continuous: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.start - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; else: - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - - lambda: id(init_in_progress) = false; + - lambda: id(init_in_progress) = false; - script.execute: draw_display on_client_disconnected: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop: + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.stop - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; - script.execute: draw_display @@ -266,25 +305,70 @@ switch: condition: lambda: return !id(init_in_progress); then: - - lambda: id(va).set_use_wake_word(true); - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; - if: condition: not: - voice_assistant.is_running then: - - voice_assistant.start_continuous + - if: + condition: + lambda: return id(wake_word_engine_location).state == "In Home Assistant"; + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous + - if: + condition: + lambda: return id(wake_word_engine_location).state == "On device"; + then: + - micro_wake_word.start - script.execute: draw_display on_turn_on: - if: condition: lambda: return !id(init_in_progress); then: - - voice_assistant.stop - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop + - micro_wake_word.stop - lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id}; - script.execute: draw_display +select: + - platform: template + entity_category: config + name: Wake word engine location + id: wake_word_engine_location + optimistic: True + restore_value: True + options: + - In Home Assistant + - On device + initial_option: On device + on_value: + - wait_until: + lambda: return id(voice_assistant_phase) == ${voice_assist_muted_phase_id} || id(voice_assistant_phase) == ${voice_assist_idle_phase_id}; + - if: + condition: + lambda: return x == "In Home Assistant"; + then: + - micro_wake_word.stop + - delay: 500ms + - if: + condition: + switch.is_off: mute + then: + - lambda: id(va).set_use_wake_word(true); + - voice_assistant.start_continuous: + - if: + condition: + lambda: return x == "On device"; + then: + - lambda: id(va).set_use_wake_word(false); + - voice_assistant.stop + - delay: 500ms + - micro_wake_word.start + globals: - id: init_in_progress type: bool