"ReSpeaker Lite" - new Seeed Studio Voice Assistant Development Kit hardware combine ESP32 with XMOS XU316 DSP chip for advanced audio processing as a ESPHome-based Home Assistant Assist Satellite voice devkit

Just updated my main branch GitHub - formatBCE/Respeaker-Lite-ESPHome-integration

What’s changed:

  • added sensor for installed DFU firmware version
  • added software switch for microphone mute functionality
  • Respeaker now is reset with ESP (was glitching before)
  • added functionality from PE to stop the TTS with saying wake word.
1 Like

Hmm I didnt so I tried updating it to what you have shown but then it gave me further error so I changed

media_player:
  - platform: nabu
    id: nabu_media_player
    name: Media Player
    internal: false
    sample_rate: 16000
    i2s_dout_pin: GPIO43
    bits_per_sample: 32bit
    i2s_mode: secondary
    i2s_audio_id: i2s_output
    volume_increment: 0.05
    volume_min: 0.4
    volume_max: 0.85

to this

speaker:
  - platform: i2s_audio
    sample_rate: 16000
    i2s_dout_pin: GPIO43
    bits_per_sample: 32bit
    i2s_mode: secondary
    i2s_audio_id: i2s_output
    dac_type: external
    channel: left

media_player:
  - platform: nabu
    id: nabu_media_player
    name: Media Player
    internal: false
    audio_dac:
    speaker:
    sample_rate: 16000
    volume_increment: 0.05
    volume_min: 0.4
    volume_max: 0.85

then it complained again about audio_dac so I added the following but not sure if its right

audio_dac:
  - platform: aic3204

then it complained again

INFO ESPHome 2024.10.1
INFO Reading configuration /config/esphome/respeaker.yaml...
INFO Updating https://github.com/esphome/voice-kit@dev
INFO Updating https://github.com/esphome/esphome.git@pull/7605/head
Failed config

audio_dac.aic3204: [source /config/esphome/respeaker.yaml:97]
  
  Component audio_dac.aic3204 requires component i2c.
  platform: aic3204

I think it needs this but wasnt sure of the GPIO’s being right…

i2c:
  sda: GPIO5
  scl: GPIO6
  frequency: 400kHz

Update: Pins are good as per ReSpeaker Lite with XIAO ESP32S3 | The Pi Hut

In my repo you can find perfectly working config.

formatBCE

I think I had to go https when I set up Google Home and Alexa manually using duckdns. It was a few years ago!

ginandbacon:

I stripped it out and typed [MyURL] myself. It’s duckdns one and works both for external remote access and internally with NAT Loopback at the router.

I can access HA using the internal IP once I get through Chrome’s warning that it could be dangerous! EDIT Sorry, it has to be https://; using http:// does not get me access at all. I think I had to set up an http:// proxy to get my Ecowitt weather station working a while ago. Is that something I could use to overcome this issue? Ah, it looks like that was a special Ad-On just for the Ecowitt.

I could try to get ReSpeaker to use my internal HA IP if i knew how!

Here’s my redacted config. I should be as per the repo apart form my credential bits. Just noticed that I commented out the dns1 bit in the manual_ip block - could that be it?

substitutions:
  voice_assist_idle_phase_id: "1"
  voice_assist_listening_phase_id: "2"
  voice_assist_thinking_phase_id: "3"
  voice_assist_replying_phase_id: "4"
  voice_assist_not_ready_phase_id: "10"
  voice_assist_error_phase_id: "11"
  voice_assist_muted_phase_id: "12"
esphome:
  name: respeaker-satellite
  friendly_name: respeaker-satellite
  min_version: 2024.9.0
  platformio_options:
    board_build.flash_mode: dio
  on_boot:
    priority: 600
    then:
      - script.execute: adjust_led
      - delay: 30s
      - if:
          condition:
            lambda: return id(init_in_progress);
          then:
            - lambda: id(init_in_progress) = false;
            - script.execute: adjust_led
esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  flash_size: 8MB
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
      CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB: "y"
      CONFIG_ESP32_S3_BOX_BOARD: "y"
      CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY: "y"
      
      CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y"

      # Settings based on https://github.com/espressif/esp-adf/issues/297#issuecomment-783811702
      CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM: "16"
      CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM: "512"
      CONFIG_ESP32_WIFI_STATIC_TX_BUFFER: "y"
      CONFIG_ESP32_WIFI_TX_BUFFER_TYPE: "0"
      CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM: "8"
      CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM: "32"
      CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED: "y"
      CONFIG_ESP32_WIFI_TX_BA_WIN: "16"
      CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED: "y"
      CONFIG_ESP32_WIFI_RX_BA_WIN: "32"
      CONFIG_LWIP_MAX_ACTIVE_TCP: "16"
      CONFIG_LWIP_MAX_LISTENING_TCP: "16"
      CONFIG_TCP_MAXRTX: "12"
      CONFIG_TCP_SYNMAXRTX: "6"
      CONFIG_TCP_MSS: "1436"
      CONFIG_TCP_MSL: "60000"
      CONFIG_TCP_SND_BUF_DEFAULT: "65535"
      CONFIG_TCP_WND_DEFAULT: "65535"  # Adjusted from linked settings to avoid compilation error
      CONFIG_TCP_RECVMBOX_SIZE: "512"
      CONFIG_TCP_QUEUE_OOSEQ: "y"
      CONFIG_TCP_OVERSIZE_MSS: "y"
      CONFIG_LWIP_WND_SCALE: "y"
      CONFIG_TCP_RCV_SCALE: "3"
      CONFIG_LWIP_TCPIP_RECVMBOX_SIZE: "512"

      CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y"
      CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y"

psram:
  mode: octal  # quad for N8R2 and octal for N16R8
  speed: 80MHz

external_components:
  - source:
      type: git
      #url: https://github.com/esphome/voice-kit
      #ref: dev
      url: https://github.com/formatBCE/home-assistant-voice-pe
      ref: format_bce
    components:
      - aic3204
      - audio_dac
      - media_player
      - micro_wake_word
      - microphone
      - nabu
      - nabu_microphone
      - voice_assistant
      - voice_kit
    refresh: 0s
  - source: github://pr#7605
    components: [ audio, i2s_audio, speaker]
    refresh: 0s

api:
  encryption:
    key: "REDACTED"
  on_client_connected:
    - script.execute: adjust_led
  on_client_disconnected:
    - script.execute: adjust_led

#ota:
#  - platform: esphome
#    id: ota_esphome
#    password: !secret ota_password

logger:

wifi:
  ap:
    ssid: "Respeaker-Satellite-1"
    password: "SDCi3ZeMJi3d"
  on_connect:
    - script.execute: adjust_led
  on_disconnect:
    - script.execute: adjust_led
  ssid: "REDACTED"
  password: !secret wifi_password
  manual_ip:
    static_ip: REDACTED
    gateway: REDACTED
    subnet: REDACTED
#    dns1: !secret dns1
  

captive_portal:

switch:
  - platform: template
    id: timer_ringing
    optimistic: true
    internal: true
    restore_mode: ALWAYS_OFF
    on_turn_on:
      # Duck audio
      - nabu.set_ducking:
          decibel_reduction: 20
          duration: 0.0s
      # Ring timer
      - script.execute: ring_timer
      # Refresh LED
      - script.execute: adjust_led
      # If 15 minutes have passed and the timer is still ringing, stop it.
      - delay: 15min
      - switch.turn_off: timer_ringing
    on_turn_off:
      # Stop any current annoucement (ie: stop the timer ring mid playback)
      - if:
          condition:
            lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
          then:
            lambda: |-
              id(nabu_media_player)
                ->make_call()
                .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                .set_announcement(true)
                .perform();
      # Set back ducking ratio to zero
      - nabu.set_ducking:
          decibel_reduction: 0
          duration: 1.0s
      # Refresh the LED ring
      - script.execute: adjust_led

button:
#  - platform: safe_mode
#    id: button_safe_mode
#    name: Safe Mode Boot
  - platform: factory_reset
    id: factory_reset_btn
    name: Factory reset
  - platform: restart
    name: Restart
    id: but_rest
  

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO4 # D3
      inverted: true
    id: mute
    name: "Mute"
  - platform: gpio
    pin: 
      number: GPIO3 # D2
      inverted: true
    id: user_button
    name: "User button"
    on_multi_click:
      - timing:
          - ON for at most 1s
          - OFF for at least 0.25s
        then:
          - if:
              condition:
                lambda: return !id(init_in_progress);
              then:
                - if:
                    condition:
                      switch.is_on: timer_ringing
                    then:
                      - switch.turn_off: timer_ringing
                    else:
                      - if:
                          condition:
                            lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
                          then:
                            - lambda: |
                                id(nabu_media_player)
                                  ->make_call()
                                  .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                                  .set_announcement(true)
                                  .perform();
                          else:
                            - if:
                                condition:
                                  voice_assistant.is_running:
                                then:
                                  - voice_assistant.stop:
                                else:
                                  - if:
                                      condition:
                                        media_player.is_playing:
                                      then:
                                        - media_player.pause:
                                      else:
                                        - if:
                                            condition:
                                              and:
                                                # - switch.is_off: master_mute_switch
                                                - not:
                                                    voice_assistant.is_running
                                            then:
                                              - voice_assistant.start:

light:
  - platform: esp32_rmt_led_strip
    id: led_ww
    rgb_order: GRB
    pin: GPIO1
    num_leds: 1
    rmt_channel: 0
    chipset: ws2812
    name: none
    disabled_by_default: true
    entity_category: config
    default_transition_length: 0s

    effects:
      - pulse:
      - pulse:
          name: "Fast Pulse"
          transition_length: 100ms
          update_interval: 100ms
          min_brightness: 50%
          max_brightness: 100%
      - pulse:
          name: "Slow Pulse"
          transition_length: 250ms
          update_interval: 250ms
          min_brightness: 50%
          max_brightness: 100%


 # Audio and Voice Assistant Config  

i2s_audio:
  - id: i2s_output
    i2s_lrclk_pin: 
      number: GPIO7
      allow_other_uses: true
    i2s_bclk_pin:  
      number: GPIO8
      allow_other_uses: true
    i2s_mclk_pin:  
      number: GPIO9
      allow_other_uses: true

  - id: i2s_input
    i2s_lrclk_pin:  
      number: GPIO7
      allow_other_uses: true
    i2s_bclk_pin:  
      number: GPIO8
      allow_other_uses: true
    i2s_mclk_pin:  
      number: GPIO9
      allow_other_uses: true

microphone:
  - platform: nabu_microphone
    i2s_din_pin: GPIO44
    adc_type: external
    pdm: false
    sample_rate: 16000
    bits_per_sample: 32bit
    i2s_mode: secondary
    i2s_audio_id: i2s_input
    channel_0:
      id: nabu_mic_mww
    channel_1:
      id: nabu_mic_va

speaker:
  - platform: i2s_audio
    sample_rate: 16000
    i2s_mode: secondary
    i2s_dout_pin: GPIO43
    bits_per_sample: 32bit
    i2s_audio_id: i2s_output
    dac_type: external
    channel: left

media_player:
  - platform: nabu
    id: nabu_media_player
    name: Media Player
    internal: false
    speaker:
    sample_rate: 16000
    volume_increment: 0.05
    volume_min: 0.4
    volume_max: 0.85
    on_announcement:
      - nabu.set_ducking:
          decibel_reduction: 20
          duration: 0.0s
    on_state:
      if:
        condition:
          and:
            - switch.is_off: timer_ringing
            - not:
                voice_assistant.is_running:
            - not:
                lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
        then:
          - nabu.set_ducking:
              decibel_reduction: 0
              duration: 1.0s

micro_wake_word:
  models:
    - model: https://github.com/kahrendt/microWakeWord/releases/download/okay_nabu/okay_nabu.json
  vad:
  microphone: nabu_mic_mww
  on_wake_word_detected:
    # If a timer is ringing: Stop it, do not start the voice assistant (We can stop timer from voice!)
    - if:
        condition:
          switch.is_on: timer_ringing
        then:
          - switch.turn_off: timer_ringing
        # Start voice assistant, stop current announcement.
        else:
          - if:
              condition:
                lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
              then:
                lambda: |-
                  id(nabu_media_player)
                    ->make_call()
                    .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                    .set_announcement(true)
                    .perform();
          - voice_assistant.start:
              wake_word: !lambda return wake_word;

voice_assistant:
  id: va
  microphone: nabu_mic_va
  media_player: nabu_media_player
  noise_suppression_level: 0
  auto_gain: 0dBFS
  volume_multiplier: 1
  on_client_connected:
    - lambda: id(init_in_progress) = false;
    - micro_wake_word.start:
    - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
    - script.execute: adjust_led
  on_client_disconnected:
    - voice_assistant.stop:
    - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id};
    - script.execute: adjust_led
  on_error:
    - if:
        condition:
          lambda: return !id(init_in_progress);
        then:
          - lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id};
          - script.execute: adjust_led
          - delay: 1s
          - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
          - script.execute: adjust_led
  on_start:
    - nabu.set_ducking:
        decibel_reduction: 20   # Number of dB quieter; higher implies more quiet, 0 implies full volume
        duration: 0.0s          # The duration of the transition (default is 0)
  on_listening:
    - lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id};
    - script.execute: adjust_led
  on_stt_vad_end:
    - lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id};
    - script.execute: adjust_led
  on_tts_start:
    - lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id};
    - script.execute: adjust_led
  on_end:
    - wait_until:
        not:
          voice_assistant.is_running:
    - nabu.set_ducking:
        decibel_reduction: 0   # 0 dB means no reduction
        duration: 1.0s
    - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
    - script.execute: adjust_led
  on_timer_finished:
    - switch.turn_on: timer_ringing

script:
  - id: ring_timer
    then:
      - while:
          condition:
            switch.is_on: timer_ringing
          then:
            - media_player.play_media: http://{ha_ip}:8123/local/sounds/timer_finished.flac
            - delay: 1s
            - wait_until:
                not:
                  media_player.is_playing:
  - id: adjust_led
    then:
      - if:
          condition:
            lambda: return !id(init_in_progress);
          then:
            - if: 
                condition:
                  switch.is_on: timer_ringing
                then:
                  - light.turn_on:
                      id: led_ww           
                      red: 0%
                      green: 100%
                      blue: 0%
                      brightness: 60%
                      effect: fast pulse 
                else:
                  - if:
                      condition:
                        wifi.connected:
                      then:
                        - if:
                            condition:
                              api.connected:
                            then:
                              - lambda: |
                                  switch(id(voice_assistant_phase)) {
                                    case ${voice_assist_listening_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 0.2, 1.0)
                                        .set_effect("Slow Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_thinking_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 0.2, 1.0)
                                        .set_effect("Fast Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_replying_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(0.2, 1.0, 1.0)
                                        .set_effect("Slow Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_error_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 1.0, 0.2)
                                        .set_effect("Fast Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_muted_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.3)
                                        .set_rgb(1.0, 0.0, 0.0)
                                        .perform();
                                      break;
                                    case ${voice_assist_not_ready_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.3)
                                        .set_rgb(1.0, 1.0, 0.2)
                                        .perform();
                                        break;
                                    default:
                                      id(led_ww).turn_off()
                                        .perform();
                                  }
                            else:
                              - light.turn_on:
                                  id: led_ww           
                                  red: 100%
                                  green: 0%
                                  blue: 0%
                                  brightness: 40%
                                  effect: fast pulse 
                      else:
                        - light.turn_on:
                            id: led_ww           
                            red: 100%
                            green: 0%
                            blue: 0%
                            brightness: 40%
                            effect: slow pulse
          else:
            - light.turn_on:
                id: led_ww           
                red: 100%
                green: 100%
                blue: 0%
                brightness: 30%
                effect: slow pulse

globals:
  - id: init_in_progress
    type: bool
    restore_value: false
    initial_value: "true"
  - id: voice_assistant_phase
    type: int
    restore_value: false
    initial_value: ${voice_assist_not_ready_phase_id}

Ran into strange issue, get a constant message about the state of the mute button not being detected. When I looked to see if there was new firmware, I noticed I was on 1.0.7. When I upgrade, it goes fine, but still lists as the same version. Anyone else have this issue? Outside the warning in the logs it works fine…

Running Ubuntu and added udev rule per Seed’s wiki and obviously upgraded

me@ubuntu:~$ sudo dfu-util -e -a 1 -D ffva_i2s_v1.0.8.bin
[sudo] password for me: 
dfu-util 0.11

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Warning: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release
Opening DFU capable USB device...
Device ID 2886:0019
Device DFU version 0101
Claiming USB DFU Interface...
Setting Alternate Interface #1 ...
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 0101
Device returned transfer size 4096
Copying data from PC to DFU device
Download	[=========================] 100%       270336 bytes
Download done.
DFU state(7) = dfuMANIFEST, status(0) = No error condition is present
DFU state(2) = dfuIDLE, status(0) = No error condition is present
Done!
me@ubuntu:~$ sudo dfu-util -l
dfu-util 0.11

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Found DFU: [2886:0019] ver=0107, devnum=4, cfg=1, intf=0, path="3-1", alt=2, name="DFU DATAPARTITION", serial="0000000001"
Found DFU: [2886:0019] ver=0107, devnum=4, cfg=1, intf=0, path="3-1", alt=1, name="DFU UPGRADE", serial="0000000001"
Found DFU: [2886:0019] ver=0107, devnum=4, cfg=1, intf=0, path="3-1", alt=0, name="DFU FACTORY", serial="0000000001"

I think your config is fine. I think the main issue is it needs to connect via http on port 8123 over LAN and right now you can’t get to it internally. https wouldn’t work even with a valid SSL cert because it would still probably try to go out to the internet and back on port 8123, which isn’t open and shouldn’t be. Even then you would have https on 8123 which probably would be an issue. Need to get internal LAN access back.

Are you still using the proxy for external access? Just did a brief search here but found this , seems like installing a proxy disables http internal access, even once removed without clearing cache or other stuff.

Reconnect Respeaker to the PC, and run util.

Also, in my repo you can find 1.0.9. :slight_smile:

Tried both, firmware update runs fine but version is 0107 after updating to either. According to Seeed’s wiki it should update. From wiki below… Really, really odd… I know it updated to 1.0.7 because it fixed my led issue. Nothing has changed. Going to try it on a friends Mac later but it’s an ARM version so who knows if dfu-util will even install.

EDIT: Everything works fine, just have this logged all the time. Just cleaned the build files too and installed again.

[17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W][respeaker_lite:069]: Read mic mute state failed [17:55:23][W]

Something wrong with the util?
Do you see version in Home Assistant?

Do you mean this one?

Currently have this flashed but its stopped working now

substitutions:
  voice_assist_idle_phase_id: "1"
  voice_assist_listening_phase_id: "2"
  voice_assist_thinking_phase_id: "3"
  voice_assist_replying_phase_id: "4"
  voice_assist_not_ready_phase_id: "10"
  voice_assist_error_phase_id: "11"
  voice_assist_muted_phase_id: "12"
esphome:
  name: respeakerv3
  friendly_name: respeakerv3
  min_version: 2024.9.0
  platformio_options:
    board_build.flash_mode: dio
  on_boot:
    priority: 600
    then:
      - script.execute: adjust_led
      - delay: 30s
      - if:
          condition:
            lambda: return id(init_in_progress);
          then:
            - lambda: id(init_in_progress) = false;
            - script.execute: adjust_led
esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  flash_size: 8MB
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
      CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB: "y"
      CONFIG_ESP32_S3_BOX_BOARD: "y"
      CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY: "y"
      
      CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y"

      # Settings based on https://github.com/espressif/esp-adf/issues/297#issuecomment-783811702
      CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM: "16"
      CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM: "512"
      CONFIG_ESP32_WIFI_STATIC_TX_BUFFER: "y"
      CONFIG_ESP32_WIFI_TX_BUFFER_TYPE: "0"
      CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM: "8"
      CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM: "32"
      CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED: "y"
      CONFIG_ESP32_WIFI_TX_BA_WIN: "16"
      CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED: "y"
      CONFIG_ESP32_WIFI_RX_BA_WIN: "32"
      CONFIG_LWIP_MAX_ACTIVE_TCP: "16"
      CONFIG_LWIP_MAX_LISTENING_TCP: "16"
      CONFIG_TCP_MAXRTX: "12"
      CONFIG_TCP_SYNMAXRTX: "6"
      CONFIG_TCP_MSS: "1436"
      CONFIG_TCP_MSL: "60000"
      CONFIG_TCP_SND_BUF_DEFAULT: "65535"
      CONFIG_TCP_WND_DEFAULT: "65535"  # Adjusted from linked settings to avoid compilation error
      CONFIG_TCP_RECVMBOX_SIZE: "512"
      CONFIG_TCP_QUEUE_OOSEQ: "y"
      CONFIG_TCP_OVERSIZE_MSS: "y"
      CONFIG_LWIP_WND_SCALE: "y"
      CONFIG_TCP_RCV_SCALE: "3"
      CONFIG_LWIP_TCPIP_RECVMBOX_SIZE: "512"

      CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y"
      CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y"

psram:
  mode: octal  # quad for N8R2 and octal for N16R8
  speed: 80MHz

external_components:
  - source:
      type: git
      url: https://github.com/esphome/voice-kit
      ref: dev
    components:
      - aic3204
      - audio_dac
      - media_player
      - micro_wake_word
      - microphone
      - nabu
      - nabu_microphone
      - voice_assistant
      - voice_kit
    refresh: 0s
  - source: github://pr#7605
    components: [ audio, i2s_audio, speaker]
    refresh: 0s

audio_dac:
  - platform: aic3204

api:
  encryption:
    key: "removed"  
  on_client_connected:
    - script.execute: adjust_led
  on_client_disconnected:
    - script.execute: adjust_led

ota:
  - platform: esphome
    id: ota_esphome
    password: "removed"

i2c:
  sda: GPIO5
  scl: GPIO6
  frequency: 400kHz

logger:

wifi:
  ssid: !secret wifi_ssid 
  password: !secret wifi_password
  on_connect:
    - script.execute: adjust_led
  on_disconnect:
    - script.execute: adjust_led
  #ssid: !secret wifi_ssid
  #password: !secret wifi_password
  #manual_ip:
  #  static_ip: !secret respeaker_satellite_1_ip
  #  gateway: !secret gateway
  #  subnet: !secret subnet
  #  dns1: !secret dns1
  
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Voice-Assistant Fallback Hotspot"
    password: "removed"

captive_portal:

switch:
  - platform: template
    id: timer_ringing
    optimistic: true
    internal: true
    restore_mode: ALWAYS_OFF
    on_turn_on:
      # Duck audio
      - nabu.set_ducking:
          decibel_reduction: 20
          duration: 0.0s
      # Ring timer
      - script.execute: ring_timer
      # Refresh LED
      - script.execute: adjust_led
      # If 15 minutes have passed and the timer is still ringing, stop it.
      - delay: 15min
      - switch.turn_off: timer_ringing
    on_turn_off:
      # Stop any current annoucement (ie: stop the timer ring mid playback)
      - if:
          condition:
            lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
          then:
            lambda: |-
              id(nabu_media_player)
                ->make_call()
                .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                .set_announcement(true)
                .perform();
      # Set back ducking ratio to zero
      - nabu.set_ducking:
          decibel_reduction: 0
          duration: 1.0s
      # Refresh the LED ring
      - script.execute: adjust_led

button:
  - platform: safe_mode
    id: button_safe_mode
    name: Safe Mode Boot
  - platform: factory_reset
    id: factory_reset_btn
    name: Factory reset
  - platform: restart
    name: Restart
    id: but_rest
  

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO4 # D3
      inverted: true
    id: mute
    name: "Mute"
  - platform: gpio
    pin: 
      number: GPIO3 # D2
      inverted: true
    id: user_button
    name: "User button"
    on_multi_click:
      - timing:
          - ON for at most 1s
          - OFF for at least 0.25s
        then:
          - if:
              condition:
                lambda: return !id(init_in_progress);
              then:
                - if:
                    condition:
                      switch.is_on: timer_ringing
                    then:
                      - switch.turn_off: timer_ringing
                    else:
                      - if:
                          condition:
                            lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
                          then:
                            - lambda: |
                                id(nabu_media_player)
                                  ->make_call()
                                  .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                                  .set_announcement(true)
                                  .perform();
                          else:
                            - if:
                                condition:
                                  voice_assistant.is_running:
                                then:
                                  - voice_assistant.stop:
                                else:
                                  - if:
                                      condition:
                                        media_player.is_playing:
                                      then:
                                        - media_player.pause:
                                      else:
                                        - if:
                                            condition:
                                              and:
                                                # - switch.is_off: master_mute_switch
                                                - not:
                                                    voice_assistant.is_running
                                            then:
                                              - voice_assistant.start:

light:
  - platform: esp32_rmt_led_strip
    id: led_ww
    rgb_order: GRB
    pin: GPIO1
    num_leds: 1
    rmt_channel: 0
    chipset: ws2812
    name: none
    disabled_by_default: true
    entity_category: config
    default_transition_length: 0s

    effects:
      - pulse:
      - pulse:
          name: "Fast Pulse"
          transition_length: 100ms
          update_interval: 100ms
          min_brightness: 50%
          max_brightness: 100%
      - pulse:
          name: "Slow Pulse"
          transition_length: 250ms
          update_interval: 250ms
          min_brightness: 50%
          max_brightness: 100%


 # Audio and Voice Assistant Config  

i2s_audio:
  - id: i2s_output
    i2s_lrclk_pin: 
      number: GPIO7
      allow_other_uses: true
    i2s_bclk_pin:  
      number: GPIO8
      allow_other_uses: true
    i2s_mclk_pin:  
      number: GPIO9
      allow_other_uses: true

  - id: i2s_input
    i2s_lrclk_pin:  
      number: GPIO7
      allow_other_uses: true
    i2s_bclk_pin:  
      number: GPIO8
      allow_other_uses: true
    i2s_mclk_pin:  
      number: GPIO9
      allow_other_uses: true

microphone:
  - platform: nabu_microphone
    i2s_din_pin: GPIO44
    adc_type: external
    pdm: false
    sample_rate: 16000
    bits_per_sample: 32bit
    i2s_mode: secondary
    i2s_audio_id: i2s_input
    channel_0:
      id: nabu_mic_mww
    channel_1:
      id: nabu_mic_va

speaker:
  - platform: i2s_audio
    sample_rate: 16000
    i2s_dout_pin: GPIO43
    bits_per_sample: 32bit
    i2s_mode: secondary
    i2s_audio_id: i2s_output
    dac_type: external
    channel: left

media_player:
  - platform: nabu
    id: nabu_media_player
    name: Media Player
    internal: false
    audio_dac:
    speaker:
    sample_rate: 16000
    volume_increment: 0.05
    volume_min: 0.4
    volume_max: 0.85
    on_announcement:
      - nabu.set_ducking:
          decibel_reduction: 20
          duration: 0.0s
    on_state:
      if:
        condition:
          and:
            - switch.is_off: timer_ringing
            - not:
                voice_assistant.is_running:
            - not:
                lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
        then:
          - nabu.set_ducking:
              decibel_reduction: 0
              duration: 1.0s

micro_wake_word:
  models:
    - model: https://github.com/kahrendt/microWakeWord/releases/download/okay_nabu/okay_nabu.json
  vad:
  microphone: nabu_mic_mww
  on_wake_word_detected:
    # If a timer is ringing: Stop it, do not start the voice assistant (We can stop timer from voice!)
    - if:
        condition:
          switch.is_on: timer_ringing
        then:
          - switch.turn_off: timer_ringing
        # Start voice assistant, stop current announcement.
        else:
          - if:
              condition:
                lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
              then:
                lambda: |-
                  id(nabu_media_player)
                    ->make_call()
                    .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                    .set_announcement(true)
                    .perform();
          - voice_assistant.start:
              wake_word: !lambda return wake_word;

voice_assistant:
  id: va
  microphone: nabu_mic_va
  media_player: nabu_media_player
  noise_suppression_level: 0
  auto_gain: 0dBFS
  volume_multiplier: 1
  on_client_connected:
    - lambda: id(init_in_progress) = false;
    - micro_wake_word.start:
    - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
    - script.execute: adjust_led
  on_client_disconnected:
    - voice_assistant.stop:
    - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id};
    - script.execute: adjust_led
  on_error:
    - if:
        condition:
          lambda: return !id(init_in_progress);
        then:
          - lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id};
          - script.execute: adjust_led
          - delay: 1s
          - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
          - script.execute: adjust_led
  on_start:
    - nabu.set_ducking:
        decibel_reduction: 20   # Number of dB quieter; higher implies more quiet, 0 implies full volume
        duration: 0.0s          # The duration of the transition (default is 0)
  on_listening:
    - lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id};
    - script.execute: adjust_led
  on_stt_vad_end:
    - lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id};
    - script.execute: adjust_led
  on_tts_start:
    - lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id};
    - script.execute: adjust_led
  on_end:
    - wait_until:
        not:
          voice_assistant.is_running:
    - nabu.set_ducking:
        decibel_reduction: 0   # 0 dB means no reduction
        duration: 1.0s
    - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
    - script.execute: adjust_led
  on_timer_finished:
    - switch.turn_on: timer_ringing

script:
  - id: ring_timer
    then:
      - while:
          condition:
            switch.is_on: timer_ringing
          then:
            - media_player.play_media: http://192.168.0.110:8123/local/sounds/timer-ding.mp3
            - delay: 1s
            - wait_until:
                not:
                  media_player.is_playing:
  - id: adjust_led
    then:
      - if:
          condition:
            lambda: return !id(init_in_progress);
          then:
            - if: 
                condition:
                  switch.is_on: timer_ringing
                then:
                  - light.turn_on:
                      id: led_ww           
                      red: 0%
                      green: 100%
                      blue: 0%
                      brightness: 60%
                      effect: fast pulse 
                else:
                  - if:
                      condition:
                        wifi.connected:
                      then:
                        - if:
                            condition:
                              api.connected:
                            then:
                              - lambda: |
                                  switch(id(voice_assistant_phase)) {
                                    case ${voice_assist_listening_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 0.2, 1.0)
                                        .set_effect("Slow Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_thinking_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 0.2, 1.0)
                                        .set_effect("Fast Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_replying_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(0.2, 1.0, 1.0)
                                        .set_effect("Slow Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_error_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 1.0, 0.2)
                                        .set_effect("Fast Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_muted_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.3)
                                        .set_rgb(1.0, 0.0, 0.0)
                                        .perform();
                                      break;
                                    case ${voice_assist_not_ready_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.3)
                                        .set_rgb(1.0, 1.0, 0.2)
                                        .perform();
                                        break;
                                    default:
                                      id(led_ww).turn_off()
                                        .perform();
                                  }
                            else:
                              - light.turn_on:
                                  id: led_ww           
                                  red: 100%
                                  green: 0%
                                  blue: 0%
                                  brightness: 40%
                                  effect: fast pulse 
                      else:
                        - light.turn_on:
                            id: led_ww           
                            red: 100%
                            green: 0%
                            blue: 0%
                            brightness: 40%
                            effect: slow pulse
          else:
            - light.turn_on:
                id: led_ww           
                red: 100%
                green: 100%
                blue: 0%
                brightness: 30%
                effect: slow pulse

globals:
  - id: init_in_progress
    type: bool
    restore_value: false
    initial_value: "true"
  - id: voice_assistant_phase
    type: int
    restore_value: false
    initial_value: ${voice_assist_not_ready_phase_id}

Yup, the switch shows up, it just can’t detect the state. I did re-enable the binary sensor because I have an automation based on it. Trying to move it to the new assist_satellite domain…

That’s weird, probably something wrong with dfu util?

I mean this one GitHub - formatBCE/Respeaker-Lite-ESPHome-integration

The one you’re referring to is Home Assistant PE config and isn’t suitable for Respeaker Lite.

right got confused.

Also the respeaker_lite_i2s_dfu_firmware_v1.0.9.bin this is a new board firmware or esp firmware and I assume need to flash it?

This is the XMOS board hardware. There’s readme :slight_smile:

Ok downloaded the Respeaker-Lite-ESPHome-integration/respeaker_lite_i2s_dfu_firmware_v1.0.9.bin at fa4afe62b3b4df92ff0f9bfa7098f88443b78e80 · formatBCE/Respeaker-Lite-ESPHome-integration · GitHub

flashed and check got this


D:\dfu-util\win64>dfu-util -e -a 1 -D respeaker_lite_i2s_dfu_firmware_v1.0.9.bin
dfu-util 0.11

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Warning: Invalid DFU suffix signature
A valid DFU suffix will be required in a future dfu-util release
Opening DFU capable USB device...
Device ID 2886:0019
Run-Time device DFU version 0101
Claiming USB DFU Interface...
Setting Alternate Interface #1 ...
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 0101
Device returned transfer size 4096
Copying data from PC to DFU device
Download        [=========================] 100%       315975 bytes
Download done.
DFU state(7) = dfuMANIFEST, status(0) = No error condition is present
DFU state(2) = dfuIDLE, status(0) = No error condition is present
Done!

D:\dfu-util\win64>dfu-util -l
dfu-util 0.11

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Found DFU: [2886:0019] ver=0205, devnum=16, cfg=1, intf=3, path="1-1", alt=2, name="DFU DATAPARTITION", serial="0000000001"
Found DFU: [2886:0019] ver=0205, devnum=16, cfg=1, intf=3, path="1-1", alt=1, name="DFU UPGRADE", serial="0000000001"
Found DFU: [2886:0019] ver=0205, devnum=16, cfg=1, intf=3, path="1-1", alt=0, name="DFU FACTORY", serial="0000000001"

remove connect again and check

D:\dfu-util\win64>dfu-util -l
dfu-util 0.11

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Found DFU: [2886:0019] ver=0105, devnum=64, cfg=1, intf=0, path="1-1", alt=2, name="DFU DATAPARTITION", serial="0000000001"
Found DFU: [2886:0019] ver=0105, devnum=64, cfg=1, intf=0, path="1-1", alt=1, name="DFU UPGRADE", serial="0000000001"
Found DFU: [2886:0019] ver=0105, devnum=64, cfg=1, intf=0, path="1-1", alt=0, name="DFU FACTORY", serial="0000000001"

Oh I am not having any luck with getting it working. Just randomly flashing red then yellow. I have used your repo with some changes to passwords etc

substitutions:
  voice_assist_idle_phase_id: "1"
  voice_assist_listening_phase_id: "2"
  voice_assist_thinking_phase_id: "3"
  voice_assist_replying_phase_id: "4"
  voice_assist_not_ready_phase_id: "10"
  voice_assist_error_phase_id: "11"
  voice_assist_muted_phase_id: "12"
esphome:
  name: respeaker-satellite
  friendly_name: respeaker-satellite
  min_version: 2024.9.0
  platformio_options:
    board_build.flash_mode: dio
  on_boot:
    priority: 600
    then:
      - script.execute: adjust_led
      - delay: 30s
      - if:
          condition:
            lambda: return id(init_in_progress);
          then:
            - lambda: id(init_in_progress) = false;
            - script.execute: adjust_led
esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  flash_size: 8MB
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
      CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB: "y"
      CONFIG_ESP32_S3_BOX_BOARD: "y"
      CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY: "y"
      
      CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y"

      # Settings based on https://github.com/espressif/esp-adf/issues/297#issuecomment-783811702
      CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM: "16"
      CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM: "512"
      CONFIG_ESP32_WIFI_STATIC_TX_BUFFER: "y"
      CONFIG_ESP32_WIFI_TX_BUFFER_TYPE: "0"
      CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM: "8"
      CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM: "32"
      CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED: "y"
      CONFIG_ESP32_WIFI_TX_BA_WIN: "16"
      CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED: "y"
      CONFIG_ESP32_WIFI_RX_BA_WIN: "32"
      CONFIG_LWIP_MAX_ACTIVE_TCP: "16"
      CONFIG_LWIP_MAX_LISTENING_TCP: "16"
      CONFIG_TCP_MAXRTX: "12"
      CONFIG_TCP_SYNMAXRTX: "6"
      CONFIG_TCP_MSS: "1436"
      CONFIG_TCP_MSL: "60000"
      CONFIG_TCP_SND_BUF_DEFAULT: "65535"
      CONFIG_TCP_WND_DEFAULT: "65535"  # Adjusted from linked settings to avoid compilation error
      CONFIG_TCP_RECVMBOX_SIZE: "512"
      CONFIG_TCP_QUEUE_OOSEQ: "y"
      CONFIG_TCP_OVERSIZE_MSS: "y"
      CONFIG_LWIP_WND_SCALE: "y"
      CONFIG_TCP_RCV_SCALE: "3"
      CONFIG_LWIP_TCPIP_RECVMBOX_SIZE: "512"

      CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y"
      CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y"

psram:
  mode: octal  # quad for N8R2 and octal for N16R8
  speed: 80MHz

external_components:
  - source:
      type: git
      url: https://github.com/esphome/voice-kit
      ref: dev
      #url: https://github.com/formatBCE/home-assistant-voice-pe
      #ref: format_bce
    components:
      - aic3204
      - audio_dac
      - media_player
      - micro_wake_word
      - microphone
      - nabu
      - nabu_microphone
      - voice_assistant
    refresh: 0s
  - source: github://pr#7605
    components: [ audio, i2s_audio, speaker]
    refresh: 0s
  - source:
      type: git
      url: https://github.com/formatBCE/Respeaker-Lite-ESPHome-integration
      ref: dev
    components: [ respeaker_lite ]
    refresh: 0s

api:
  encryption:
    key: "removed"  
  on_client_connected:
    - script.execute: adjust_led
  on_client_disconnected:
    - script.execute: adjust_led

ota:
  - platform: esphome
    id: ota_esphome
    password: "removed"

logger:

wifi:
  ssid: !secret wifi_ssid 
  password: !secret wifi_password
  on_connect:
    - script.execute: adjust_led
  on_disconnect:
    - script.execute: adjust_led
  #ssid: !secret wifi_ssid
  #password: !secret wifi_password
  #manual_ip:
  #  static_ip: !secret respeaker_satellite_1_ip
  #  gateway: !secret gateway
  #  subnet: !secret subnet
  #  dns1: !secret dns1
  
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Voice-Assistant Fallback Hotspot"
    password: "removed"
  

captive_portal:

i2c:
  - id: bus_a
    sda: GPIO5
    scl: GPIO6
    scan: true

respeaker_lite:
  id: respeaker
  i2c_id: bus_a
  reset_pin: GPIO2
  mute_state:
    internal: true
    id: mute_state
  firmware_version:
    icon: mdi:application-cog
    name: XMOS firmware version
    internal: false
    id: firmware_version

switch:
  - platform: gpio
    internal: true
    pin: 
      number: GPIO4 # D3
      inverted: true
    id: mute_toggle
    on_turn_on:
      - delay: 300ms
      - switch.turn_off: mute_toggle
  - platform: template
    id: mic_mute_switch
    name: Mic mute
    icon: mdi:microphone-off
    lambda: |-
      if (id(mute_state).state) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
      - switch.turn_on: mute_toggle
    turn_off_action:
      - switch.turn_on: mute_toggle
  - platform: template
    id: timer_ringing
    optimistic: true
    internal: true
    restore_mode: ALWAYS_OFF
    on_turn_on:
      # Duck audio
      - nabu.set_ducking:
          decibel_reduction: 20
          duration: 0.0s
      # Ring timer
      - script.execute: ring_timer
      # Refresh LED
      - script.execute: adjust_led
      # If 15 minutes have passed and the timer is still ringing, stop it.
      - delay: 15min
      - switch.turn_off: timer_ringing
    on_turn_off:
      # Stop any current annoucement (ie: stop the timer ring mid playback)
      - if:
          condition:
            lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
          then:
            lambda: |-
              id(nabu_media_player)
                ->make_call()
                .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                .set_announcement(true)
                .perform();
      # Set back ducking ratio to zero
      - nabu.set_ducking:
          decibel_reduction: 0
          duration: 1.0s
      # Refresh the LED ring
      - script.execute: adjust_led

button:
  - platform: safe_mode
    id: button_safe_mode
    name: Safe Mode Boot
  - platform: factory_reset
    id: factory_reset_btn
    name: Factory reset
  - platform: restart
    name: Restart
    id: but_rest
  

binary_sensor:
  - platform: gpio
    pin: 
      number: GPIO3 # D2
      inverted: true
    id: user_button
    name: "User button"
    on_multi_click:
      - timing:
          - ON for at most 1s
          - OFF for at least 0.25s
        then:
          - if:
              condition:
                lambda: return !id(init_in_progress);
              then:
                - if:
                    condition:
                      switch.is_on: timer_ringing
                    then:
                      - switch.turn_off: timer_ringing
                    else:
                      - if:
                          condition:
                            lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
                          then:
                            - lambda: |
                                id(nabu_media_player)
                                  ->make_call()
                                  .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                                  .set_announcement(true)
                                  .perform();
                          else:
                            - if:
                                condition:
                                  voice_assistant.is_running:
                                then:
                                  - voice_assistant.stop:
                                else:
                                  - if:
                                      condition:
                                        media_player.is_playing:
                                      then:
                                        - media_player.pause:
                                      else:
                                        - if:
                                            condition:
                                              and:
                                                # - switch.is_off: master_mute_switch
                                                - not:
                                                    voice_assistant.is_running
                                            then:
                                              - voice_assistant.start:

light:
  - platform: esp32_rmt_led_strip
    id: led_ww
    rgb_order: GRB
    pin: GPIO1
    num_leds: 1
    rmt_channel: 0
    chipset: ws2812
    name: none
    disabled_by_default: true
    entity_category: config
    default_transition_length: 0s

    effects:
      - pulse:
      - pulse:
          name: "Fast Pulse"
          transition_length: 100ms
          update_interval: 100ms
          min_brightness: 50%
          max_brightness: 100%
      - pulse:
          name: "Slow Pulse"
          transition_length: 250ms
          update_interval: 250ms
          min_brightness: 50%
          max_brightness: 100%

 # Audio and Voice Assistant Config  

i2s_audio:
  - id: i2s_output
    i2s_lrclk_pin: 
      number: GPIO7
      allow_other_uses: true
    i2s_bclk_pin:  
      number: GPIO8
      allow_other_uses: true
    i2s_mclk_pin:  
      number: GPIO9
      allow_other_uses: true

  - id: i2s_input
    i2s_lrclk_pin:  
      number: GPIO7
      allow_other_uses: true
    i2s_bclk_pin:  
      number: GPIO8
      allow_other_uses: true
    i2s_mclk_pin:  
      number: GPIO9
      allow_other_uses: true

microphone:
  - platform: nabu_microphone
    i2s_din_pin: GPIO44
    adc_type: external
    pdm: false
    sample_rate: 16000
    bits_per_sample: 32bit
    i2s_mode: secondary
    i2s_audio_id: i2s_input
    channel_0:
      id: nabu_mic_mww
    channel_1:
      id: nabu_mic_va

speaker:
  - platform: i2s_audio
    sample_rate: 16000
    i2s_mode: secondary
    i2s_dout_pin: GPIO43
    bits_per_sample: 32bit
    i2s_audio_id: i2s_output
    dac_type: external
    channel: left

media_player:
  - platform: nabu
    id: nabu_media_player
    name: Media Player
    internal: false
    speaker:
    sample_rate: 16000
    volume_increment: 0.05
    volume_min: 0.0
    volume_max: 1.0
    on_announcement:
      - nabu.set_ducking:
          decibel_reduction: 20
          duration: 0.0s
    on_state:
      if:
        condition:
          and:
            - switch.is_off: timer_ringing
            - not:
                voice_assistant.is_running:
            - not:
                lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
        then:
          - nabu.set_ducking:
              decibel_reduction: 0
              duration: 1.0s

micro_wake_word:
  models:
    - model: okay_nabu
    - model: https://github.com/kahrendt/microWakeWord/releases/download/stop/stop.json
      id: stop
      internal: true
  vad:
  microphone: nabu_mic_mww
  on_wake_word_detected:
    # If a timer is ringing: Stop it, do not start the voice assistant (We can stop timer from voice!)
    - if:
        condition:
          switch.is_on: timer_ringing
        then:
          - switch.turn_off: timer_ringing
        # Start voice assistant, stop current announcement.
        else:
          - if:
              condition:
                lambda: return id(nabu_media_player)->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING;
              then:
                lambda: |-
                  id(nabu_media_player)
                    ->make_call()
                    .set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP)
                    .set_announcement(true)
                    .perform();
          - voice_assistant.start:
              wake_word: !lambda return wake_word;

voice_assistant:
  id: va
  microphone: nabu_mic_va
  media_player: nabu_media_player
  noise_suppression_level: 0
  auto_gain: 0dBFS
  volume_multiplier: 1
  on_client_connected:
    - lambda: id(init_in_progress) = false;
    - micro_wake_word.start:
    - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
    - script.execute: adjust_led
  on_client_disconnected:
    - voice_assistant.stop:
    - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id};
    - script.execute: adjust_led
  on_error:
    - if:
        condition:
          lambda: return !id(init_in_progress);
        then:
          - lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id};
          - script.execute: adjust_led
          - delay: 1s
          - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
          - script.execute: adjust_led
  on_start:
    - nabu.set_ducking:
        decibel_reduction: 20   # Number of dB quieter; higher implies more quiet, 0 implies full volume
        duration: 0.0s          # The duration of the transition (default is 0)
  on_listening:
    - lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id};
    - script.execute: adjust_led
  on_stt_vad_end:
    - lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id};
    - script.execute: adjust_led
  on_tts_start:
    - lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id};
    - script.execute: adjust_led
    - script.execute: activate_stop_word_if_tts_step_is_long
  on_end:
    - wait_until:
        not:
          voice_assistant.is_running:
    - nabu.set_ducking:
        decibel_reduction: 0   # 0 dB means no reduction
        duration: 1.0s
    - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
    - script.execute: adjust_led
    - script.stop: activate_stop_word_if_tts_step_is_long
  on_timer_finished:
    - switch.turn_on: timer_ringing

script:
  - id: ring_timer
    then:
      - while:
          condition:
            switch.is_on: timer_ringing
          then:
            - media_player.play_media: http://192.168.0.110:8123/local/sounds/timer-ding.mp3
            - delay: 1s
            - wait_until:
                not:
                  media_player.is_playing:
  # Script used activate the stop word if the TTS step is long.
  # Why is this wrapped on a script?
  #   Becasue we want to stop the sequence if the TTS step is faster than that.
  #   This allows us to prevent having the deactivation of the stop word before its own activation.
  - id: activate_stop_word_if_tts_step_is_long
    then:
      - delay: 1s
      # Enable stop wake word
      - lambda: id(stop).enable();
  - id: adjust_led
    then:
      - if:
          condition:
            lambda: return !id(init_in_progress);
          then:
            - if: 
                condition:
                  switch.is_on: timer_ringing
                then:
                  - light.turn_on:
                      id: led_ww           
                      red: 0%
                      green: 100%
                      blue: 0%
                      brightness: 60%
                      effect: fast pulse 
                else:
                  - if:
                      condition:
                        wifi.connected:
                      then:
                        - if:
                            condition:
                              api.connected:
                            then:
                              - lambda: |
                                  switch(id(voice_assistant_phase)) {
                                    case ${voice_assist_listening_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 0.2, 1.0)
                                        .set_effect("Slow Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_thinking_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 0.2, 1.0)
                                        .set_effect("Fast Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_replying_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(0.2, 1.0, 1.0)
                                        .set_effect("Slow Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_error_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.6)
                                        .set_rgb(1.0, 1.0, 0.2)
                                        .set_effect("Fast Pulse")
                                        .perform();
                                      break;
                                    case ${voice_assist_muted_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.3)
                                        .set_rgb(1.0, 0.0, 0.0)
                                        .perform();
                                      break;
                                    case ${voice_assist_not_ready_phase_id}:
                                      id(led_ww).turn_on()
                                        .set_brightness(0.3)
                                        .set_rgb(1.0, 1.0, 0.2)
                                        .perform();
                                        break;
                                    default:
                                      id(led_ww).turn_off()
                                        .perform();
                                  }
                            else:
                              - light.turn_on:
                                  id: led_ww           
                                  red: 100%
                                  green: 0%
                                  blue: 0%
                                  brightness: 40%
                                  effect: fast pulse 
                      else:
                        - light.turn_on:
                            id: led_ww           
                            red: 100%
                            green: 0%
                            blue: 0%
                            brightness: 40%
                            effect: slow pulse
          else:
            - light.turn_on:
                id: led_ww           
                red: 100%
                green: 100%
                blue: 0%
                brightness: 30%
                effect: slow pulse

globals:
  - id: init_in_progress
    type: bool
    restore_value: false
    initial_value: "true"
  - id: voice_assistant_phase
    type: int
    restore_value: false
    initial_value: ${voice_assist_not_ready_phase_id}

I’m pretty sure dfu util makes something wrong on Windows. You’re not the one reporting this. See, -l should report version 0109, not 0105, if you correctly downloaded the file.

yeah something not right. I managed to flash dfu-util -e -a 1 -D respeaker_lite_i2s_dfu_firmware_v1.0.8.bin

1.0.8 should work fine, if written correctly.
Make sure you clean build files in ESPHome before installing.

I think something weird is going on…

INFO ESPHome 2024.10.1
INFO Reading configuration /config/esphome/respeaker.yaml...
INFO Updating https://github.com/esphome/voice-kit@dev
INFO Updating https://github.com/esphome/esphome.git@pull/7605/head
INFO Updating https://github.com/formatBCE/Respeaker-Lite-ESPHome-integration@dev
WARNING GPIO3 is a strapping PIN and should only be used for I/O with care.
Attaching external pullup/down resistors to strapping pins can cause unexpected failures.
See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins
INFO Starting log output from respeaker-satellite.local using esphome API
WARNING Can't connect to ESPHome API for respeaker-satellite.local: Error resolving IP address: [Errno -5] No address associated with hostname (APIConnectionError)
INFO Trying to connect to respeaker-satellite.local in the background
INFO Successfully connected to respeaker-satellite @ 192.168.0.60 in 0.100s
INFO Successful handshake with respeaker-satellite @ 192.168.0.60 in 0.192s
[17:09:45][I][app:100]: ESPHome version 2024.10.1 compiled on Oct 23 2024, 15:28:36
[17:09:45][C][wifi:600]: WiFi:
[17:09:45][C][wifi:428]:   Local MAC: 64:E8:33:50:C0:7C
[17:09:45][C][wifi:433]:   SSID: [redacted]
[17:09:45][C][wifi:436]:   IP Address: 192.168.0.60
[17:09:45][C][wifi:440]:   BSSID: [redacted]
[17:09:45][C][wifi:441]:   Hostname: 'respeaker-satellite'
[17:09:45][C][wifi:443]:   Signal strength: -34 dB ▂▄▆█
[17:09:45][C][wifi:447]:   Channel: 3
[17:09:45][C][wifi:448]:   Subnet: 255.255.255.0
[17:09:45][C][wifi:449]:   Gateway: 192.168.0.1
[17:09:45][C][wifi:450]:   DNS1: 192.168.0.1
[17:09:45][C][wifi:451]:   DNS2: 0.0.0.0
[17:09:45][C][logger:185]: Logger:
[17:09:45][C][logger:186]:   Level: DEBUG
[17:09:45][C][logger:188]:   Log Baud Rate: 115200
[17:09:45][C][logger:189]:   Hardware UART: USB_SERIAL_JTAG
[17:09:45][C][i2c.idf:075]: I2C Bus:
[17:09:45][C][i2c.idf:076]:   SDA Pin: GPIO5
[17:09:45][C][i2c.idf:077]:   SCL Pin: GPIO6
[17:09:45][C][i2c.idf:078]:   Frequency: 50000 Hz
[17:09:45][C][i2c.idf:084]:   Recovery: bus successfully recovered
[17:09:45][I][i2c.idf:094]: Results from i2c bus scan:
[17:09:45][I][i2c.idf:100]: Found i2c device at address 0x18
[17:09:45][C][switch.gpio:068]: GPIO Switch 'mute_toggle'
[17:09:45][C][switch.gpio:091]:   Restore Mode: always OFF
[17:09:45][C][switch.gpio:031]:   Pin: GPIO4
[17:09:45][C][esp32_rmt_led_strip:187]: ESP32 RMT LED Strip:
[17:09:45][C][esp32_rmt_led_strip:188]:   Pin: 1
[17:09:45][C][esp32_rmt_led_strip:189]:   Channel: 0
[17:09:45][C][esp32_rmt_led_strip:214]:   RGB Order: GRB
[17:09:45][C][esp32_rmt_led_strip:215]:   Max refresh rate: 0
[17:09:45][C][esp32_rmt_led_strip:216]:   Number of LEDs: 1
[17:09:45][C][gpio.binary_sensor:015]: GPIO Binary Sensor 'User button'
[17:09:45][C][gpio.binary_sensor:016]:   Pin: GPIO3
[17:09:46][C][light:103]: Light 'respeaker-satellite'
[17:09:46][C][light:105]:   Default Transition Length: 0.0s
[17:09:46][C][light:106]:   Gamma Correct: 2.80
[17:09:46][C][template.switch:068]: Template Switch 'Mic mute'
[17:09:46][C][template.switch:070]:   Icon: 'mdi:microphone-off'
[17:09:46][C][template.switch:091]:   Restore Mode: always OFF
[17:09:46][C][template.switch:057]:   Optimistic: NO
[17:09:46][C][template.switch:068]: Template Switch 'timer_ringing'
[17:09:46][C][template.switch:091]:   Restore Mode: always OFF
[17:09:46][C][template.switch:057]:   Optimistic: YES
[17:09:46][C][psram:020]: PSRAM:
[17:09:46][C][psram:021]:   Available: YES
[17:09:46][C][psram:024]:   Size: 8191 KB
[17:09:46][C][safe_mode.button:024]: Safe Mode Button 'Safe Mode Boot'
[17:09:46][C][safe_mode.button:024]:   Icon: 'mdi:restart-alert'
[17:09:46][C][factory_reset.button:011]: Factory Reset Button 'Factory reset'
[17:09:46][C][factory_reset.button:011]:   Icon: 'mdi:restart-alert'
[17:09:46][C][restart.button:017]: Restart Button 'Restart'
[17:09:46][C][restart.button:017]:   Icon: 'mdi:restart'
[17:09:46][C][captive_portal:089]: Captive Portal:
[17:09:46][C][mdns:116]: mDNS:
[17:09:46][C][mdns:117]:   Hostname: respeaker-satellite
[17:09:46][C][esphome.ota:073]: Over-The-Air updates:
[17:09:46][C][esphome.ota:074]:   Address: respeaker-satellite.local:3232
[17:09:46][C][esphome.ota:075]:   Version: 2
[17:09:46][C][esphome.ota:078]:   Password configured
[17:09:46][C][safe_mode:018]: Safe Mode:
[17:09:46][C][safe_mode:020]:   Boot considered successful after 60 seconds
[17:09:46][C][safe_mode:021]:   Invoke after 10 boot attempts
[17:09:46][C][safe_mode:023]:   Remain in safe mode for 300 seconds
[17:09:46][C][api:140]: API Server:
[17:09:46][C][api:141]:   Address: respeaker-satellite.local:6053
[17:09:46][C][api:143]:   Using noise encryption: YES
[17:09:46][C][micro_wake_word:072]: microWakeWord:
[17:09:46][C][micro_wake_word:073]:   models:
[17:09:46][C][micro_wake_word:015]:     - Wake Word: Okay Nabu
[17:09:46][C][micro_wake_word:016]:       Probability cutoff: 0.97
[17:09:46][C][micro_wake_word:017]:       Sliding window size: 5
[17:09:46][C][micro_wake_word:015]:     - Wake Word: Stop
[17:09:46][C][micro_wake_word:016]:       Probability cutoff: 0.50
[17:09:46][C][micro_wake_word:017]:       Sliding window size: 5
[17:09:46][C][micro_wake_word:021]:     - VAD Model
[17:09:46][C][micro_wake_word:022]:       Probability cutoff: 0.50
[17:09:46][C][micro_wake_word:023]:       Sliding window size: 5
[17:09:46][D][micro_wake_word:379]: Starting wake word detection
[17:09:46][D][light:036]: 'respeaker-satellite' Setting:
[17:09:46][D][light:047]:   State: OFF
[17:09:46][D][light:109]:   Effect: 'None'
[17:09:46][D][esp-idf:000][microphone_task]: I (75732) I2S: DMA Malloc info, datalen=blocksize=1280, dma_buf_count=4

[17:09:47][D][i2s_audio.microphone:377]: Starting I2S Audio Microphne
[17:09:47][D][i2s_audio.microphone:381]: Started I2S Audio Microphone
[17:09:47][D][micro_wake_word:418]: State changed from IDLE to DETECTING_WAKE_WORD
[17:14:47][D][micro_wake_word:357]: Detected 'Okay Nabu' with sliding average probability is 0.99 and max probability is 1.00
[17:14:47][D][voice_assistant:516]: State changed from IDLE to START_MICROPHONE
[17:14:47][D][voice_assistant:522]: Desired state set to START_PIPELINE
[17:14:47][D][voice_assistant:225]: Starting Microphone
[17:14:47][D][ring_buffer:034]: Created ring buffer with size 16384
[17:14:47][D][voice_assistant:516]: State changed from START_MICROPHONE to STARTING_MICROPHONE
[17:14:47][D][voice_assistant:516]: State changed from STARTING_MICROPHONE to START_PIPELINE
[17:14:47][D][voice_assistant:280]: Requesting start...
[17:14:47][D][voice_assistant:516]: State changed from START_PIPELINE to STARTING_PIPELINE
[17:14:47][W][respeaker_lite:063]: Request mic mute state failed
[17:14:47][W][respeaker_lite:063]: Request mic mute state failed
[17:14:47][W][respeaker_lite:063]: Request mic mute state failed
[17:14:47][W][respeaker_lite:063]: Request mic mute state failed
WARNING respeaker-satellite @ 192.168.0.60: Connection error occurred: [Errno 104] Connection reset by peer
INFO Processing unexpected disconnect from ESPHome API for respeaker-satellite @ 192.168.0.60
WARNING Disconnected from API
INFO Successfully connected to respeaker-satellite @ 192.168.0.60 in 0.495s
INFO Successful handshake with respeaker-satellite @ 192.168.0.60 in 0.222s