From 6f40e0939a0ef69d75f0eaf7fa5bfcc13f5c885e Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 24 Jul 2024 19:16:41 +1200 Subject: [PATCH 1/3] Add new adopted config for atom echo VA (#244) --- .github/workflows/build.yml | 1 + .../m5stack-atom-echo.adopted.yaml | 280 ++++++++++++++++++ voice-assistant/m5stack-atom-echo.yaml | 4 +- 3 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 voice-assistant/m5stack-atom-echo.adopted.yaml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6abf4a9..68f9939 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -84,6 +84,7 @@ jobs: run: | sed -i 's/${{ steps.esphome-build.outputs.name }}\//\/${{ matrix.firmware }}\/${{ matrix.device }}\//g' output/${{ matrix.device }}/manifest.json - uses: actions/upload-artifact@v4.3.4 + if: ${{ ! contains(matrix.device, 'adopted') }} with: name: build-${{ matrix.firmware }}-${{ matrix.device }} path: output diff --git a/voice-assistant/m5stack-atom-echo.adopted.yaml b/voice-assistant/m5stack-atom-echo.adopted.yaml new file mode 100644 index 0000000..08831ae --- /dev/null +++ b/voice-assistant/m5stack-atom-echo.adopted.yaml @@ -0,0 +1,280 @@ +--- +esphome: + name: m5stack-atom-echo + friendly_name: M5Stack Atom Echo + min_version: 2024.6.0 + name_add_mac_suffix: true + +esp32: + board: m5stack-atom + framework: + type: esp-idf + +logger: +api: + +ota: + - platform: esphome + id: ota_esphome + +wifi: + ap: + +button: + - platform: safe_mode + id: button_safe_mode + name: Safe Mode Boot + + - platform: factory_reset + id: factory_reset_btn + name: Factory reset + +i2s_audio: + - id: i2s_audio_bus + i2s_lrclk_pin: GPIO33 + i2s_bclk_pin: GPIO19 + +microphone: + - platform: i2s_audio + id: echo_microphone + i2s_din_pin: GPIO23 + adc_type: external + pdm: true + +speaker: + - platform: i2s_audio + id: echo_speaker + i2s_dout_pin: GPIO22 + dac_type: external + mode: mono + +voice_assistant: + id: va + microphone: echo_microphone + speaker: echo_speaker + noise_suppression_level: 2 + auto_gain: 31dBFS + volume_multiplier: 2.0 + vad_threshold: 3 + on_listening: + - light.turn_on: + id: led + blue: 100% + red: 0% + green: 0% + effect: "Slow Pulse" + on_stt_vad_end: + - light.turn_on: + id: led + blue: 100% + red: 0% + green: 0% + effect: "Fast Pulse" + on_tts_start: + - light.turn_on: + id: led + blue: 100% + red: 0% + green: 0% + brightness: 100% + effect: none + on_end: + - delay: 100ms + - wait_until: + not: + speaker.is_playing: + - script.execute: reset_led + on_error: + - light.turn_on: + id: led + red: 100% + green: 0% + blue: 0% + brightness: 100% + effect: none + - delay: 1s + - script.execute: reset_led + on_client_connected: + - if: + condition: + switch.is_on: use_wake_word + then: + - voice_assistant.start_continuous: + - script.execute: reset_led + on_client_disconnected: + - if: + condition: + switch.is_on: use_wake_word + then: + - voice_assistant.stop: + - light.turn_off: led + on_timer_finished: + - voice_assistant.stop: + - switch.turn_on: timer_ringing + - wait_until: + not: + microphone.is_capturing: + - light.turn_on: + id: led + red: 0% + green: 100% + 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: + - 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: + - platform: gpio + pin: + number: GPIO39 + inverted: true + name: Button + disabled_by_default: true + entity_category: diagnostic + id: echo_button + on_multi_click: + - timing: + - ON for at least 50ms + - OFF for at least 50ms + then: + - if: + condition: + switch.is_on: timer_ringing + 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: + - timing: + - ON for at least 10s + then: + - button.press: factory_reset_btn + +light: + - platform: esp32_rmt_led_strip + id: led + name: None + disabled_by_default: true + entity_category: config + pin: GPIO27 + default_transition_length: 0s + chipset: SK6812 + num_leds: 1 + rgb_order: grb + rmt_channel: 0 + effects: + - pulse: + name: "Slow Pulse" + transition_length: 250ms + update_interval: 250ms + min_brightness: 50% + max_brightness: 100% + - pulse: + name: "Fast Pulse" + transition_length: 100ms + update_interval: 100ms + min_brightness: 50% + max_brightness: 100% + +script: + - id: reset_led + then: + - if: + condition: + - switch.is_on: use_wake_word + - switch.is_on: use_listen_light + then: + - light.turn_on: + id: led + red: 100% + green: 89% + blue: 71% + 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: + not: + - voice_assistant.is_running + 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 + - platform: template + name: Use listen light + id: use_listen_light + optimistic: true + restore_mode: RESTORE_DEFAULT_ON + entity_category: config + on_turn_on: + - script.execute: reset_led + on_turn_off: + - script.execute: reset_led + - platform: template + id: timer_ringing + optimistic: true + internal: true + restore_mode: ALWAYS_OFF + on_turn_on: + - delay: 15min + - switch.turn_off: timer_ringing + +external_components: + - source: github://pr#5230 + components: + - esp_adf + refresh: 0s + - source: github://jesserockz/esphome-components + components: [file] + refresh: 0s + +esp_adf: + +file: + - id: timer_finished_wave_file + file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav diff --git a/voice-assistant/m5stack-atom-echo.yaml b/voice-assistant/m5stack-atom-echo.yaml index 0f7eb6c..a9532a9 100644 --- a/voice-assistant/m5stack-atom-echo.yaml +++ b/voice-assistant/m5stack-atom-echo.yaml @@ -6,7 +6,7 @@ esphome: name_add_mac_suffix: true project: name: m5stack.atom-echo-voice-assistant - version: "24.7.4.1" + version: "24.7.24" esp32: board: m5stack-atom @@ -31,7 +31,7 @@ update: http_request: dashboard_import: - package_import_url: github://esphome/firmware/voice-assistant/m5stack-atom-echo.yaml@main + package_import_url: github://esphome/firmware/voice-assistant/m5stack-atom-echo.adopted.yaml@main wifi: on_connect: From 79da7d5da902ad49efd519ccd7253c393a14409b Mon Sep 17 00:00:00 2001 From: JLo Date: Thu, 25 Jul 2024 04:36:09 +0200 Subject: [PATCH 2/3] Simplify S3 Box Firmwares (#229) --- wake-word-voice-assistant/esp32-s3-box-3.yaml | 50 ++++++----------- .../esp32-s3-box-lite.yaml | 50 +++++++---------- wake-word-voice-assistant/esp32-s3-box.yaml | 53 ++++++------------- 3 files changed, 50 insertions(+), 103 deletions(-) diff --git a/wake-word-voice-assistant/esp32-s3-box-3.yaml b/wake-word-voice-assistant/esp32-s3-box-3.yaml index 4c8da01..d3b3c7f 100644 --- a/wake-word-voice-assistant/esp32-s3-box-3.yaml +++ b/wake-word-voice-assistant/esp32-s3-box-3.yaml @@ -125,27 +125,16 @@ esp32_improv: button: - platform: factory_reset id: factory_reset_btn - name: Factory reset + internal: true binary_sensor: - - platform: gpio - pin: - number: GPIO1 - inverted: true - name: "Mute" - id: mute_switch - disabled_by_default: true - entity_category: diagnostic - - platform: gpio pin: number: GPIO0 mode: INPUT_PULLUP inverted: true - name: Top Left Button id: top_left_button - disabled_by_default: true - entity_category: diagnostic + internal: true on_multi_click: - timing: - ON for at least 50ms @@ -165,7 +154,8 @@ output: light: - platform: monochromatic id: led - name: LCD Backlight + name: Screen + icon: "mdi:television" entity_category: config output: backlight_output restore_mode: RESTORE_DEFAULT_ON @@ -478,16 +468,10 @@ script: - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; switch: - - platform: template - name: Display conversation - id: display_conversation - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - entity_category: config - - platform: template name: Mute id: mute + icon: "mdi:microphone-off" optimistic: true restore_mode: RESTORE_DEFAULT_OFF entity_category: config @@ -540,6 +524,7 @@ select: entity_category: config name: Wake word engine location id: wake_word_engine_location + icon: "mdi:account-voice" optimistic: true restore_value: true options: @@ -746,24 +731,21 @@ display: lambda: |- it.fill(id(thinking_color)); it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_thinking), ImageAlign::CENTER); - if (id(display_conversation).state) { - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - } + it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); + it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); + id(draw_timer_timeline).execute(); - id: replying_page lambda: |- it.fill(id(replying_color)); it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_replying), ImageAlign::CENTER); - if (id(display_conversation).state) { - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); - } + it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); + it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); + it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); + it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); id(draw_timer_timeline).execute(); - id: timer_finished_page lambda: |- diff --git a/wake-word-voice-assistant/esp32-s3-box-lite.yaml b/wake-word-voice-assistant/esp32-s3-box-lite.yaml index d5295e7..3ce2af5 100644 --- a/wake-word-voice-assistant/esp32-s3-box-lite.yaml +++ b/wake-word-voice-assistant/esp32-s3-box-lite.yaml @@ -118,18 +118,15 @@ esp32_improv: authorizer: none button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - platform: factory_reset id: factory_reset_btn - name: Factory reset + internal: true sensor: - platform: adc pin: GPIO1 id: front_buttons + internal: true update_interval: 16ms attenuation: 11db on_value: @@ -179,17 +176,17 @@ sensor: binary_sensor: - platform: template id: left - name: "Left" + internal: true on_press: - switch.turn_off: timer_ringing - platform: template id: middle - name: "Middle" + internal: true on_press: - switch.turn_off: timer_ringing - platform: template id: right - name: "Right" + internal: true on_press: - switch.turn_off: timer_ringing @@ -198,9 +195,8 @@ binary_sensor: number: GPIO0 mode: INPUT_PULLUP inverted: true - name: Left Top Button id: left_top_button - disabled_by_default: true + internal: true on_multi_click: - timing: - ON for at least 50ms @@ -221,7 +217,8 @@ output: light: - platform: monochromatic id: led - name: LCD Backlight + name: Screen + icon: "mdi:television" entity_category: config output: backlight_output restore_mode: RESTORE_DEFAULT_ON @@ -533,16 +530,10 @@ script: - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; switch: - - platform: template - name: Display conversation - id: display_conversation - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - entity_category: config - - platform: template name: Mute id: mute + icon: "mdi:microphone-off" optimistic: true restore_mode: RESTORE_DEFAULT_OFF entity_category: config @@ -595,6 +586,7 @@ select: entity_category: config name: Wake word engine location id: wake_word_engine_location + icon: "mdi:account-voice" optimistic: true restore_value: true options: @@ -799,24 +791,20 @@ display: lambda: |- it.fill(id(thinking_color)); it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_thinking), ImageAlign::CENTER); - if (id(display_conversation).state) { - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - } + it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); + it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); id(draw_timer_timeline).execute(); - id: replying_page lambda: |- it.fill(id(replying_color)); it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_replying), ImageAlign::CENTER); - if (id(display_conversation).state) { - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); - } + it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); + it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); + it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); + it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); id(draw_timer_timeline).execute(); - id: timer_finished_page lambda: |- diff --git a/wake-word-voice-assistant/esp32-s3-box.yaml b/wake-word-voice-assistant/esp32-s3-box.yaml index 4a85e86..1e363bf 100644 --- a/wake-word-voice-assistant/esp32-s3-box.yaml +++ b/wake-word-voice-assistant/esp32-s3-box.yaml @@ -117,33 +117,18 @@ esp32_improv: authorizer: none button: - - platform: safe_mode - id: button_safe_mode - name: Safe Mode Boot - - platform: factory_reset id: factory_reset_btn - name: Factory reset + internal: true binary_sensor: - - platform: gpio - pin: - number: GPIO1 - inverted: true - name: "Mute" - id: mute_switch - disabled_by_default: true - entity_category: diagnostic - - platform: gpio pin: number: GPIO0 mode: INPUT_PULLUP inverted: true - name: Top Left Button id: top_left_button - disabled_by_default: true - entity_category: diagnostic + internal: true on_multi_click: - timing: - ON for at least 50ms @@ -163,7 +148,8 @@ output: light: - platform: monochromatic id: led - name: LCD Backlight + name: Screen + icon: "mdi:television" entity_category: config output: backlight_output restore_mode: RESTORE_DEFAULT_ON @@ -474,16 +460,10 @@ script: - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; switch: - - platform: template - name: Display conversation - id: display_conversation - optimistic: true - restore_mode: RESTORE_DEFAULT_ON - entity_category: config - - platform: template name: Mute id: mute + icon: "mdi:microphone-off" optimistic: true restore_mode: RESTORE_DEFAULT_OFF entity_category: config @@ -536,6 +516,7 @@ select: entity_category: config name: Wake word engine location id: wake_word_engine_location + icon: "mdi:account-voice" optimistic: true restore_value: true options: @@ -740,24 +721,20 @@ display: lambda: |- it.fill(id(thinking_color)); it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_thinking), ImageAlign::CENTER); - if (id(display_conversation).state) { - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - } + it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); + it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); id(draw_timer_timeline).execute(); - id: replying_page lambda: |- it.fill(id(replying_color)); it.image((it.get_width() / 2), (it.get_height() / 2), id(casita_replying), ImageAlign::CENTER); - if (id(display_conversation).state) { - it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); - it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); - it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); - it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); - it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); - } + it.filled_rectangle(20 , 20 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 20 , 280 , 30 , Color::BLACK ); + it.filled_rectangle(20 , 190 , 280 , 30 , Color::WHITE ); + it.rectangle(20 , 190 , 280 , 30 , Color::BLACK ); + it.printf(30, 25, id(font_request), Color::BLACK, "%s", id(text_request).state.c_str()); + it.printf(30, 195, id(font_response), Color::BLACK, "%s", id(text_response).state.c_str()); id(draw_timer_timeline).execute(); - id: timer_finished_page lambda: |- From 05f8f62d08de6155c1db42ec1d19baf4399ac025 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:36:32 +1200 Subject: [PATCH 3/3] Bump actions/download-artifact from 4.1.7 to 4.1.8 (#231) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 68f9939..2a2b616 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -103,7 +103,7 @@ jobs: - project: esphome-web name: ESPHome Web steps: - - uses: actions/download-artifact@v4.1.7 + - uses: actions/download-artifact@v4.1.8 with: pattern: build-${{ matrix.project }}-* merge-multiple: true @@ -135,7 +135,7 @@ jobs: - project: media-player name: Media Player steps: - - uses: actions/download-artifact@v4.1.7 + - uses: actions/download-artifact@v4.1.8 with: pattern: build-${{ matrix.project }}-* merge-multiple: true @@ -165,7 +165,7 @@ jobs: - full-manifests steps: - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4.1.7 + - uses: actions/download-artifact@v4.1.8 with: pattern: "!build-*" path: output