Updated Sketch for voice assistant.
This commit is contained in:
		| @@ -1,15 +1,13 @@ | ||||
| substitutions: | ||||
|   name: "m5stack-atom-echo" | ||||
|   friendly_name: "M5Stack Atom Echo" | ||||
|   name: m5stack-atom-echo | ||||
|   friendly_name: M5Stack Atom Echo | ||||
|   micro_wake_word_model: okay_nabu  # alexa, hey_jarvis, hey_mycroft are also supported | ||||
|  | ||||
| esphome: | ||||
|   name: ${name} | ||||
|   friendly_name: ${friendly_name} | ||||
|   name_add_mac_suffix: False | ||||
|   project: | ||||
|     name: m5stack.atom-echo-voice-assistant | ||||
|     version: "24.7.24" | ||||
|   min_version: 2024.9.0 | ||||
|   friendly_name: ${friendly_name} | ||||
|   min_version: 2025.2.0 | ||||
|  | ||||
| esp32: | ||||
|   board: m5stack-atom | ||||
| @@ -25,25 +23,12 @@ api: | ||||
|  | ||||
| ota: | ||||
|   - platform: esphome | ||||
|     password: !secret ota | ||||
|     id: ota_esphome | ||||
|   - platform: http_request | ||||
|     id: ota_http_request | ||||
|  | ||||
| update: | ||||
|   - platform: http_request | ||||
|     id: update_http_request | ||||
|     name: Firmware | ||||
|     source: https://firmware.esphome.io/voice-assistant/m5stack-atom-echo/manifest.json | ||||
|  | ||||
| http_request: | ||||
|     password: !secret ota | ||||
|  | ||||
| wifi: | ||||
|   on_connect: | ||||
|     - delay: 5s  # Gives time for improv results to be transmitted | ||||
|     - ble.disable: | ||||
|   on_disconnect: | ||||
|     - ble.enable: | ||||
|   ssid: Voltage-legacy | ||||
|   password: !secret voltage_legacy_psk | ||||
|   use_address: ${name}.home | ||||
| @@ -54,22 +39,11 @@ wifi: | ||||
|     ssid: "Raspiaudio Fallback Hotspot" | ||||
|     password: !secret fallback_psk | ||||
|  | ||||
| improv_serial: | ||||
|  | ||||
| esp32_improv: | ||||
|   authorizer: none | ||||
|  | ||||
| logger: | ||||
|  | ||||
| dashboard_import: | ||||
|   package_import_url: github://esphome/firmware/voice-assistant/m5stack-atom-echo.adopted.yaml@main | ||||
|  | ||||
| captive_portal: | ||||
|  | ||||
| button: | ||||
|   - platform: safe_mode | ||||
|     id: button_safe_mode | ||||
|     name: Safe Mode Boot | ||||
|   - platform: factory_reset | ||||
|     id: factory_reset_btn | ||||
|     name: Factory reset | ||||
| @@ -91,16 +65,52 @@ speaker: | ||||
|     id: echo_speaker | ||||
|     i2s_dout_pin: GPIO22 | ||||
|     dac_type: external | ||||
|     channel: mono | ||||
|     bits_per_sample: 32bit | ||||
|     channel: right | ||||
|     buffer_duration: 60ms | ||||
|  | ||||
| media_player: | ||||
|   - platform: speaker | ||||
|     name: None | ||||
|     id: echo_media_player | ||||
|     announcement_pipeline: | ||||
|       speaker: echo_speaker | ||||
|       format: WAV | ||||
|     codec_support_enabled: false | ||||
|     buffer_size: 6000 | ||||
|     files: | ||||
|       - id: timer_finished_wave_file | ||||
|         file: https://github.com/esphome/wake-word-voice-assistants/raw/main/sounds/timer_finished.wav | ||||
|     on_announcement: | ||||
|       - if: | ||||
|           condition: | ||||
|             - microphone.is_capturing: | ||||
|           then: | ||||
|             - if: | ||||
|                 condition: | ||||
|                   lambda: return id(wake_word_engine_location).state == "On device"; | ||||
|                 then: | ||||
|                   - micro_wake_word.stop: | ||||
|                 else: | ||||
|                   - voice_assistant.stop: | ||||
|             - script.execute: reset_led | ||||
|       - light.turn_on: | ||||
|           id: led | ||||
|           blue: 100% | ||||
|           red: 0% | ||||
|           green: 0% | ||||
|           brightness: 100% | ||||
|           effect: none | ||||
|     on_idle: | ||||
|       - script.execute: start_wake_word | ||||
|  | ||||
| voice_assistant: | ||||
|   id: va | ||||
|   microphone: echo_microphone | ||||
|   speaker: echo_speaker | ||||
|   media_player: echo_media_player | ||||
|   noise_suppression_level: 2 | ||||
|   auto_gain: 31dBFS | ||||
|   volume_multiplier: 2.0 | ||||
|   vad_threshold: 3 | ||||
|   on_listening: | ||||
|     - light.turn_on: | ||||
|         id: led | ||||
| @@ -125,10 +135,7 @@ voice_assistant: | ||||
|         effect: none | ||||
|   on_end: | ||||
|     - delay: 100ms | ||||
|     - wait_until: | ||||
|         not: | ||||
|           speaker.is_playing: | ||||
|     - script.execute: reset_led | ||||
|     - script.execute: start_wake_word | ||||
|   on_error: | ||||
|     - light.turn_on: | ||||
|         id: led | ||||
| @@ -137,28 +144,21 @@ voice_assistant: | ||||
|         blue: 0% | ||||
|         brightness: 100% | ||||
|         effect: none | ||||
|     - delay: 1s | ||||
|     - delay: 2s | ||||
|     - script.execute: reset_led | ||||
|   on_client_connected: | ||||
|     - if: | ||||
|         condition: | ||||
|           switch.is_on: use_wake_word | ||||
|         then: | ||||
|           - voice_assistant.start_continuous: | ||||
|           - script.execute: reset_led | ||||
|     - delay: 2s  # Give the api server time to settle | ||||
|     - script.execute: start_wake_word | ||||
|   on_client_disconnected: | ||||
|     - if: | ||||
|         condition: | ||||
|           switch.is_on: use_wake_word | ||||
|         then: | ||||
|           - voice_assistant.stop: | ||||
|           - light.turn_off: led | ||||
|     - voice_assistant.stop: | ||||
|     - micro_wake_word.stop: | ||||
|   on_timer_finished: | ||||
|     - voice_assistant.stop: | ||||
|     - switch.turn_on: timer_ringing | ||||
|     - micro_wake_word.stop: | ||||
|     - wait_until: | ||||
|         not: | ||||
|           microphone.is_capturing: | ||||
|     - switch.turn_on: timer_ringing | ||||
|     - light.turn_on: | ||||
|         id: led | ||||
|         red: 0% | ||||
| @@ -166,25 +166,15 @@ voice_assistant: | ||||
|         blue: 0% | ||||
|         brightness: 100% | ||||
|         effect: "Fast Pulse" | ||||
|     - while: | ||||
|         condition: | ||||
|           switch.is_on: timer_ringing | ||||
|         then: | ||||
|           - lambda: id(echo_speaker).play(id(timer_finished_wave_file), sizeof(id(timer_finished_wave_file))); | ||||
|           - delay: 1s | ||||
|     - wait_until: | ||||
|         not: | ||||
|           speaker.is_playing: | ||||
|         - switch.is_off: timer_ringing | ||||
|     - light.turn_off: led | ||||
|     - switch.turn_off: timer_ringing | ||||
|     - if: | ||||
|         condition: | ||||
|           switch.is_on: use_wake_word | ||||
|         then: | ||||
|           - voice_assistant.start_continuous: | ||||
|           - script.execute: reset_led | ||||
|  | ||||
| binary_sensor: | ||||
|   # button does the following: | ||||
|   # short click - stop a timer | ||||
|   # if no timer then restart either microwakeword or voice assistant continuous | ||||
|   - platform: gpio | ||||
|     pin: | ||||
|       number: GPIO39 | ||||
| @@ -204,23 +194,7 @@ binary_sensor: | ||||
|               then: | ||||
|                 - switch.turn_off: timer_ringing | ||||
|               else: | ||||
|                 - if: | ||||
|                     condition: | ||||
|                       switch.is_off: use_wake_word | ||||
|                     then: | ||||
|                       - if: | ||||
|                           condition: voice_assistant.is_running | ||||
|                           then: | ||||
|                             - voice_assistant.stop: | ||||
|                             - script.execute: reset_led | ||||
|                           else: | ||||
|                             - voice_assistant.start: | ||||
|                     else: | ||||
|                       - voice_assistant.stop | ||||
|                       - delay: 1s | ||||
|                       - script.execute: reset_led | ||||
|                       - script.wait: reset_led | ||||
|                       - voice_assistant.start_continuous: | ||||
|                 - script.execute: start_wake_word | ||||
|       - timing: | ||||
|           - ON for at least 10s | ||||
|         then: | ||||
| @@ -257,7 +231,7 @@ script: | ||||
|     then: | ||||
|       - if: | ||||
|           condition: | ||||
|             - switch.is_on: use_wake_word | ||||
|             - lambda: return id(wake_word_engine_location).state == "On device"; | ||||
|             - switch.is_on: use_listen_light | ||||
|           then: | ||||
|             - light.turn_on: | ||||
| @@ -268,28 +242,45 @@ script: | ||||
|                 brightness: 60% | ||||
|                 effect: none | ||||
|           else: | ||||
|             - light.turn_off: led | ||||
|  | ||||
| switch: | ||||
|   - platform: template | ||||
|     name: Use wake word | ||||
|     id: use_wake_word | ||||
|     optimistic: true | ||||
|     restore_mode: RESTORE_DEFAULT_ON | ||||
|     entity_category: config | ||||
|     on_turn_on: | ||||
|       - lambda: id(va).set_use_wake_word(true); | ||||
|             - if: | ||||
|                 condition: | ||||
|                   - lambda: return id(wake_word_engine_location).state != "On device"; | ||||
|                   - switch.is_on: use_listen_light | ||||
|                 then: | ||||
|                   - light.turn_on: | ||||
|                       id: led | ||||
|                       red: 0% | ||||
|                       green: 100% | ||||
|                       blue: 100% | ||||
|                       brightness: 60% | ||||
|                       effect: none | ||||
|                 else: | ||||
|                   - light.turn_off: led | ||||
|   - id: start_wake_word | ||||
|     then: | ||||
|       - wait_until: | ||||
|           and: | ||||
|             - media_player.is_idle: | ||||
|             - speaker.is_stopped: | ||||
|       - if: | ||||
|           condition: | ||||
|             not: | ||||
|               - voice_assistant.is_running | ||||
|             lambda: return id(wake_word_engine_location).state == "On device"; | ||||
|           then: | ||||
|             - voice_assistant.start_continuous | ||||
|       - script.execute: reset_led | ||||
|     on_turn_off: | ||||
|       - voice_assistant.stop | ||||
|       - lambda: id(va).set_use_wake_word(false); | ||||
|       - script.execute: reset_led | ||||
|             - voice_assistant.stop | ||||
|             - micro_wake_word.stop: | ||||
|             - delay: 1s | ||||
|             - script.execute: reset_led | ||||
|             - script.wait: reset_led | ||||
|             - micro_wake_word.start: | ||||
|           else: | ||||
|             - if: | ||||
|                 condition: voice_assistant.is_running | ||||
|                 then: | ||||
|                   - voice_assistant.stop: | ||||
|                   - script.execute: reset_led | ||||
|             - voice_assistant.start_continuous: | ||||
|  | ||||
| switch: | ||||
|   - platform: template | ||||
|     name: Use listen light | ||||
|     id: use_listen_light | ||||
| @@ -303,26 +294,67 @@ switch: | ||||
|   - platform: template | ||||
|     id: timer_ringing | ||||
|     optimistic: true | ||||
|     internal: true | ||||
|     restore_mode: ALWAYS_OFF | ||||
|     on_turn_off: | ||||
|       # Turn off the repeat mode and disable the pause between playlist items | ||||
|       - lambda: |- | ||||
|               id(echo_media_player) | ||||
|                 ->make_call() | ||||
|                 .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF) | ||||
|                 .set_announcement(true) | ||||
|                 .perform(); | ||||
|               id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 0); | ||||
|       # Stop playing the alarm | ||||
|       - media_player.stop: | ||||
|           announcement: true | ||||
|     on_turn_on: | ||||
|       # Turn on the repeat mode and pause for 1000 ms between playlist items/repeats | ||||
|       - lambda: |- | ||||
|             id(echo_media_player) | ||||
|               ->make_call() | ||||
|               .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE) | ||||
|               .set_announcement(true) | ||||
|               .perform(); | ||||
|             id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 1000); | ||||
|       - media_player.speaker.play_on_device_media_file: | ||||
|           media_file: timer_finished_wave_file | ||||
|           announcement: true | ||||
|       - delay: 15min | ||||
|       - switch.turn_off: timer_ringing | ||||
|  | ||||
| external_components: | ||||
|   - source: github://pr#5230 | ||||
|     components: | ||||
|       - esp_adf | ||||
|     refresh: 0s | ||||
|   - source: | ||||
|       type: git | ||||
|       url: https://github.com/jesserockz/esphome-components | ||||
|       ref: main | ||||
|     components: [file] | ||||
|     refresh: 0s | ||||
| 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: | ||||
|       - if: | ||||
|           condition: | ||||
|             lambda: return x == "In Home Assistant"; | ||||
|           then: | ||||
|             - micro_wake_word.stop | ||||
|             - delay: 500ms | ||||
|             - 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 | ||||
|  | ||||
| esp_adf: | ||||
|  | ||||
| file: | ||||
|   - id: timer_finished_wave_file | ||||
|     file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav | ||||
| micro_wake_word: | ||||
|   on_wake_word_detected: | ||||
|     - voice_assistant.start: | ||||
|         wake_word: !lambda return wake_word; | ||||
|   vad: | ||||
|   models: | ||||
|     - model: ${micro_wake_word_model} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user