Thanks to Smart Home Junkie’s video (invidious link), I had my Atom Echos as voice recognition boxes with all audio output redirected to a media player of my choice (because the audio on the Echo is super quiet).

Whenever ESPHome updated, I updated my Echos to get the recent ESPHome updates, and then reinstalled the custom yaml for audio redirection.

However, with ESPHome’s recent 2024.6.4 update, trying to install the yaml triggers errors that don’t seem to make sense. For example, here’s a section of the yaml:

microphone:
  - platform: i2s_audio
    id: echo_microphone_kitchen
    i2s_din_pin: GPIO23
    adc_type: external
    pdm: true

speaker:
  - platform: i2s_audio
    id: echo_speaker_kitchen
    i2s_dout_pin: GPIO21
    dac_type: external
    mode: mono

voice_assistant:
  id: va
  microphone: echo_microphone_kitchen
  speaker: echo_speaker_kitchen
  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_tts_end:
    - homeassistant.service:
        service: media_player.play_media
        data:
          entity_id: media_player.${media_player}
          media_content_id: !lambda 'return x;'
          media_content_type: music
          announce: "false"
  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

external_components:
  - source: github://pr#5230
    components:
      - esp_adf
    refresh: 0s

esp_adf:

On lines 3 and 10 I define unique IDs for the device’s microphone and speaker.

But ESPHome won’t compile, telling me:

  • on line 46: Too many candidates found for ‘id’ type ‘speaker::Speaker’ Some are ‘echo_speaker’, ‘echo_speaker_kitchen’.
  • on line 57: Too many candidates found for ‘id’ type ‘speaker::Speaker’ Some are ‘echo_speaker’, ‘echo_speaker_kitchen’.
  • on line 77: Too many candidates found for ‘id’ type ‘microphone::Microphone’ Some are ‘echo_microphone’, ‘echo_microphone_kitchen’.
  • on line 90: Too many candidates found for ‘id’ type ‘speaker::Speaker’ Some are ‘echo_speaker’, ‘echo_speaker_kitchen’.

There are no other occurrences of the word “speaker” or “microphone” in the conf yaml (and I’m not including other yaml files).

I’m assuming most of this config is default, and the only things I care about are forcing pin 21 for the speaker (line 11) and redirecting audio to my media player (lines 45-52).

  • Mike Wooskey@lemmy.thewooskeys.comOP
    link
    fedilink
    English
    arrow-up
    1
    ·
    3 days ago

    FYI, here’s the config yaml I’m copy-pasting for all my Echos. The only thing that changes are in the “substitutions” section:

    substitutions:
      name: m5stack-echo-kitchen
      friendly_name: M5Stack Atom Echo - Kitchen
      media_player: kitchen_speaker
      encryption_key: !secret kitchen_encryption_key
      speaker_i2s_dout_pin: "GPIO21"
    
    esphome:
      name: ${name}
      name_add_mac_suffix: false
      friendly_name: ${friendly_name}
      project:
        name: m5stack.atom-echo-voice-assistant
        version: "1.0"
      min_version: 2024.6.0
    
    esp32:
      board: m5stack-atom
      framework:
        type: esp-idf
    
    api:
      encryption:
        key: ${encryption_key}
    
    ota:
      - platform: esphome
        id: ota_esphome
    
    dashboard_import:
      package_import_url: github://esphome/firmware/voice-assistant/m5stack-atom-echo.yaml@main
    
    wifi:
      ssid: !secret wifi_ssid
      password: !secret wifi_password
      on_connect:
        - delay: 5s  # Gives time for improv results to be transmitted
        - ble.disable:
      on_disconnect:
        - ble.enable:
      ap:
    
    improv_serial:
    
    esp32_improv:
      authorizer: none
    
    button:
      - 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: ${speaker_i2s_dout_pin}
        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
      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_tts_end:
        - homeassistant.service:
            service: media_player.play_media
            data:
              entity_id: media_player.${media_player}
              media_content_id: !lambda 'return x;'
              media_content_type: music
              announce: "false"
      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:
        refresh: 0s
      - source: github://jesserockz/esphome-components
        components: [file]
        refresh: 0s
    
    file:
      - id: timer_finished_wave_file
        file: https://github.com/esphome/firmware/raw/main/voice-assistant/sounds/timer_finished.wav
    
    logger: