Home Assistant Wakeword with Muse Proto HELP

First the media player question: No it doesn’t work as a media player. That wasn’t a goal of mine, so I didn’t seek it out. Also, the media_player section is notably absent in this yaml. I suspect it may be possible, but I’m not smart enough yet on yaml or esphome to make it work. Maybe a future project.

As for the install, I use the ESPHome add-on in Home Assistant, but you have also to install the USB-to-serial drivers on your machine first.

Assuming your code is actually being put on your device, I suspect your problem is one of two things:

  1. Either you aren’t adding it to the ESPHome integration after install; or
  2. You’re straight copy/pasting someone’s yaml which means it doesn’t have your device-specific api and ota keys. When ESPHome creates a project, it generates two encryption keys: api and ota. My understanding is that the api key is generated to allow the device to securely communicate with Home Assistant via the ESPHome integration. The ota key is (I believe) to allow updating of some kind via wifi after the initial setup, but I don’t really understand that one.

Below are the steps I used to get the code installed and the device working:

  1. This is assuming you have HAOS or Supervisor because we’re going to be using Add-Ons
  2. Install the serial drivers found here https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers. [If you don’t want to trust some Internet rando sending a link, you can google ESP32 serial drivers which will link you to a doc by espressif (the makers of the ESP chips) which will contain the same link, but it never hurts to be careful!]
  3. Go to Add-Ons → Add and install ESPHome Add-on. Once installed click the “Open WebUI” button.
  4. Click “New Device” and name it whatever you want (mine is ha-voice-muse-proto). Skip the “Installation” step. When asked for board, just choose the standard ESP32. The next step gives you your API key. It puts it in the config automatically, but just in case you paste over it…
  5. Click “Edit” on your new device. Copy/Paste your yaml. NOTE: This is where you need to make sure you preserve the api and ota keys. Also make sure the wifi section matches your setup. Click save.
  6. Click “Install” → Windows should prompt you with a popup for a device (COM# depending on your USB setup, but usually something other than COM1). This will take a while.
  7. After a bit it should reboot, the code does a nifty status check with the LED.
  8. On your network, find the IP of the device - I check my router to look for new DHCP leases. After first boot I found the DHCP IP, then assigned a static IP by mapping on my router, but you can do it in the yaml in the wifi section if you want like below. Or if you use secrets.yaml you can do that. NOTE: Your secrets.yaml file must be in the config/esphome/ folder on your HA server.
wifi:
  ssid: MyHomeNetwork
  password: VerySafePassword

  # Set manual IP
  manual_ip:
    static_ip: 192.168.0.123
    gateway: 192.168.0.1
    subnet: 255.255.255.0
  1. Then you have to go into Devices and Services and click Add Integration
  2. Search for ESPHome
  3. It will prompt you for the IP of the ESPhome device. Enter it and keep the port the same.
  4. The last thing you need to do is go back into Devices and Services and select the ESPHome Integration. You should see your device listed there by whatever you named it. Click “Configure” and check the box to “Allow the device to make Home Assistant service calls.”
  5. After that it should be up and running. My code has a slowly pulsing cyan led while listening, pulsing blue while detecting.

I did slightly modify the yaml, so I’ve pasted mine below (with painstaking pinout I created because the documentation all shows top of the board, but the writing is on the bottom). It adds a wifi status check, so on boot when it connects to wifi the LED will briefly turn green. I also toned down the brightness of the LEDs and changed the colors. The only things you’d have to change is the wifi info that I have in my secrets.yaml file and your device-specific keys which are created by ESPHome.

Hope this helps!

############################################
# Home Assistant Wakeword Speaker
# Everything Smart Home - https://www.youtube.com/watch?v=zhlIaBG3Ldo
# Code modified from https://github.com/esphome/firmware/blob/main/voice-assistant/raspiaudio-muse-proto.yaml
# Board model esp-wrover-kit // ESP Muse Proto - raspiaudio.com
# Board pinout diagram - https://forum.raspiaudio.com/t/muse-proto-board/231
# Pinout map (from backside)

# PIN   LABEL     FCN              | LABEL       FCN
# 1     GND       Ground           | GND         Ground
# 2     23        GAIN_AMPLI       | +3v3        VDD3V3      
# 3     22        NEOPIXEL         | +3v3        VDD3V3
# 4     TXD       U0TXD            | RST         RST/EN
# 5     RXD       U0RXD            | VP          SENSOR VP
# 6     21        ENABLE_AMPLI     | VN          SENSOR VN
# 7     19        GPIO19           | 34          SD_DETECT
# 8     18        GPIO18           | 35          I2S_CODEC_ASDOUT
# 9     5         I2S_CODEC_SCLK   | 32          GPIO32    
# 10    4         GPIO4            | 33          BAT_MONITOR
# 11    0         IO0              | 25          I2S_CODEC_LRCK
# 12    2         SD_D0            | 26          I2S_CODEC_DIN
# 13    15        SD_CMD           | 27          AUX_DETECT_IO
# 14    SD1       SDI/SD1          | 14          SD_CLK
# 15    SD0       SDO/SD0          | 12          GPIO12
# 16    CLK       SCK/CLK          | 13          SD_D3
# 17    VBAT      VBA^             | SD2         SHD/SD2
# 18    5V        +5V              | SD3         SWP/SD3
# 19    GND       Ground           | CMD         SCS/CMD
# 20    GND       Ground           | GND         Ground

# GPIO 0 = Button next to speaker jack
# GPIO 22 = onboard LED (NEOPIXEL)

#######################################################

esphome:
  name: ha-voice-muse-proto
  friendly_name: ha-voice-muse-proto
#  name_add_mac_suffix: true
  name_add_mac_suffix: false
  project:
    name: raspiaudio.muse-proto-voice-assistant # Author's project
    version: "1.0"
  min_version: 2023.11.1
  on_boot:
      then:
        - light.turn_on:
            id: led
            red: 100%
            green: 100%
            blue: 100%
            brightness: 20%
            effect: none

esp32:
  board: esp-wrover-kit
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: ######## specific to your device ############

ota:
  password: ######## specific to your device ############

#dashboard_import:
#  package_import_url: github://esphome/firmware/voice-assistant/raspiaudio-muse-proto.yaml@main

wifi:
  ssid: ######## specific to your device ############
  password: ######## specific to your device ############
  on_connect:
    - delay: 5s # Gives time for improv results to be transmitted
    - ble.disable:
  on_disconnect:
    - ble.enable:

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: ######## specific to your device ############
    password: ######## specific to your device ############

captive_portal:

improv_serial:

esp32_improv:
  authorizer: none

globals:
  - id: wifi_connected
    type: bool
    initial_value: "false"
    restore_value: false

interval:
  - interval: 2s
    then:
      - if:
          condition:
            and:
              - lambda: "return !id(wifi_connected);"
              - wifi.connected:
          then:
            - globals.set:
                id: wifi_connected
                value: "true"
            - light.turn_on:
                id: led
                red: 0%
                green: 100%
                blue: 0%
                brightness: 20%
                effect: none
            - delay: 3s
            - light.turn_off: led

button:
  - platform: factory_reset
    id: factory_reset_btn
    name: Factory reset

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

i2s_audio:
  - i2s_lrclk_pin: GPIO25
    i2s_bclk_pin: GPIO5

microphone:
  - platform: i2s_audio
    id: board_microphone
    channel: left
    i2s_din_pin: GPIO35
    adc_type: external
    pdm: false

speaker:
  - platform: i2s_audio
    id: board_speaker
    dac_type: external
    i2s_dout_pin: GPIO26
    mode: mono

output:
  - platform: gpio
    pin:
      number: GPIO21
      inverted: true
    id: mute_pin

esp_adf:

voice_assistant:
  id: va
  microphone: board_microphone
  speaker: board_speaker
  use_wake_word: true
  noise_suppression_level: 2
  auto_gain: 31dBFS
  volume_multiplier: 2.0
  vad_threshold: 3
  on_listening:
    - output.turn_on: mute_pin
    - 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:
    - output.turn_off: mute_pin
    - light.turn_on:
        id: led
        blue: 100%
        red: 0%
        green: 0%
        brightness: 100%
        effect: none
  on_end:
    - delay: 150ms
    - wait_until:
        not:
          speaker.is_playing:
    - output.turn_on: mute_pin
    - script.execute: reset_led
  on_error:
    - light.turn_on:
        id: led
        blue: 0%
        red: 100%
        green: 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

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO0
      inverted: true
      mode:
        input: true
        pullup: true
    name: Action
    disabled_by_default: true
    on_multi_click:
      - timing:
          - ON for at least 250ms
          - OFF for at least 50ms
        then:
          - 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
    rmt_channel: 0
    name: None
    id: led
    disabled_by_default: true
    pin: GPIO22
    chipset: WS2812
    num_leds: 1
    rgb_order: grb
    effects:
      - pulse:
          name: "Slow Pulse"
          transition_length: 500ms
          update_interval: 500ms
          min_brightness: 25%
          max_brightness: 50%
      - pulse:
          name: "Fast Pulse"
          transition_length: 100ms
          update_interval: 100ms
          min_brightness: 25%
          max_brightness: 50%

script:
  - id: reset_led
    then:
      - if:
          condition:
            switch.is_on: use_wake_word
          then:
            - light.turn_on:
                id: led
                red: 0%
                green: 100%
                blue: 100%
                brightness: 15%
                effect: "Slow Pulse"
          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