Projet voice control

Bonjour,
@Krull56, je viens de regarder un peu ton yaml ESPHome :
Il faudra déjà que je vérifie que mon câblage est compatible.
Sinon, c’est quoi micro_wake_word, dans mes code actuels j’ai use_wake_word !
Avec micro_wake_word il faut un Addon, une intégration en plus ?

Bonne journée
Bob

Hello

Non, les micro_wake_word sont autonomes sur la carte ( c’est l’avantage car ta carte n’envoie pas en continu un flux vers ton pipeline pour analyser si le wake word est prononcé).
Quand le MWW est reconnu par la carte, là elle envoi l’audio à ton HA pour qu’il puisse analyser la commande.

Pour le câblage, tu as l’habitude , tu as juste à changer les GPIO dans le code pour que ça colle :wink:

@+

1 « J'aime »

Merci @Krull56, j’essaie ça ce soir :wink:
Bob

Bonsoir @Krull56
Alors voila, je suis passé à ESPHome 2024.7.0 et avec ton code (mon API, OTA etc) le PI à fait ce qu’il a pu:

======================== [SUCCESS] Took 1478.72 seconds ========================
INFO Successfully compiled program.
INFO Connecting to 192.168.1.15
INFO Uploading /data/build/esp32-psram16-r8-voice-3/.pioenvs/esp32-psram16-r8-voice-3/firmware.bin (1269920 bytes)
Uploading: [============================================================] 100% Done...

Il a bien chauffé :slight_smile:
Je précise que mon code précédent fonctionnait pour les commandes vocales mais qu’il n’y avais pas de retour de son « speaker ».

J’ai gardé ce code dans un premier temps :

micro_wake_word:
  vad:
  models:
    - model: okay_nabu
    - model: hey_jarvis
    - model: alexa

Il réponds juste à OK Bruno, comme avant mais toujours pas de son pour moi.
Les entités de l’ESP.


Mon Assistant:

J’ai remplacé Ampli et HP par un qui fonctionne et pas mieux.
Je mets le code utilisé:

esphome:
  name: esp32-psram16-r8-voice-3
  friendly_name: Esp32 Psram16-r8 Voice 3
  platformio_options:
    board_build.flash_mode: dio

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf
    version: 4.4.6
    sdkconfig_options:
      CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
      CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
      CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
      CONFIG_AUDIO_BOARD_CUSTOM: "y"

   
psram:
  mode: octal
  speed: 80MHz

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "+ez3sbE9GwM6JTDj/orddddddzcK2H2dW3z2Iq3JVQ8="

  on_client_connected:
        then:
          - delay: 50ms
          - light.turn_off: my_light
          - micro_wake_word.start:
  on_client_disconnected:
        then:
          - voice_assistant.stop: 


ota:
  - platform: esphome
    password: "36c193329a9d7282cdddddd4724316a7"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.1.15
    gateway: 192.168.1.254
    subnet: 255.255.255.0 

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp32-Psram16-R8-Voice-3"
    password: "IHdddddd4Y1s"

captive_portal:
    

    
button:
  - platform: restart
    id: reboot
    name: "Reboot V3"

switch:
  - platform: template
    id: mute
    name: mute
    optimistic: true
    on_turn_on: 
      - micro_wake_word.stop:
      - voice_assistant.stop:
      - light.turn_on:
          id: my_light           
          red: 100%
          green: 0%
          blue: 0%
          brightness: 60%
          effect: fast pulse 
      - delay: 2s
      - light.turn_off:
          id: my_light
      - light.turn_on:
          id: my_light           
          red: 100%
          green: 0%
          blue: 0%
          brightness: 30%
    on_turn_off:
      - micro_wake_word.start:
      - light.turn_on:
          id: my_light           
          red: 0%
          green: 100%
          blue: 0%
          brightness: 60%
          effect: fast pulse 
      - delay: 2s
      - light.turn_off:
          id: my_light 

light:
  - platform: esp32_rmt_led_strip
    id: my_light
    rgb_order: GRB
    pin: GPIO8
    num_leds: 2
    rmt_channel: 0
    chipset: ws2812
    name: "on board light"
    effects:
      - pulse:
      - pulse:
          name: "Fast_Pulse"
          transition_length: 0.5s
          update_interval: 0.5s
          min_brightness: 0%
          max_brightness: 100%

i2s_audio:
  - id: i2s_in
    i2s_lrclk_pin: GPIO5  #ws
    i2s_bclk_pin: GPIO6   #sck
  - id: i2s_out
    i2s_lrclk_pin: GPIO46
    i2s_bclk_pin: GPIO9



microphone:
  - platform: i2s_audio
    id: va_mic
    adc_type: external
    i2s_din_pin: GPIO4 #SD
    channel: left
    pdm: false
    i2s_audio_id: i2s_in
    bits_per_sample: 32bit

speaker:
    platform: i2s_audio
    id: va_speaker
    i2s_audio_id: i2s_out
    dac_type: external
    i2s_dout_pin: GPIO10  
    mode: mono

micro_wake_word:
  vad:
  models:
    - model: okay_nabu
    - model: hey_jarvis
    - model: alexa
  on_wake_word_detected:
    then:
      - voice_assistant.start:
          wake_word: !lambda return wake_word;
      - light.turn_on:
          id: my_light           
          red: 0%
          green: 0%
          blue: 100%
          brightness: 100%
          effect: Fast_Pulse

voice_assistant:
  id: va
  microphone: va_mic
  speaker: va_speaker
  noise_suppression_level: 2
  auto_gain: 31dBFS
  volume_multiplier: 4

  on_stt_end:
       then: 
         - light.turn_off: my_light
  on_error:
          - micro_wake_word.start:  
  on_end:
        then:
          - light.turn_off: my_light
          - wait_until:
              not:
                voice_assistant.is_running:
          - micro_wake_word.start:

@Krull56 et tous, si vous avez une idée :wink:
Merci
Bonne soirée
Bob

Je tente de reflasher pour voir :wink:
Pas mieux, sur celui qui fonctionne et que je ne mettrais pas à jour, il est en 2024.4.2, je vois un lien vers le MP3 créé, là c’est du wav !

[23:17:47][D][voice_assistant:655]: Speech recognised as: "éteindre la lumière marine"
[23:17:47][D][voice_assistant:627]: Event Type: 5
[23:17:47][D][voice_assistant:660]: Intent started
[23:17:48][D][voice_assistant:627]: Event Type: 6
[23:17:48][D][voice_assistant:627]: Event Type: 7
[23:17:48][D][voice_assistant:683]: Response: "Éteint"
[23:17:48][D][voice_assistant:627]: Event Type: 98
[23:17:48][D][voice_assistant:768]: TTS stream start
[23:17:48][D][voice_assistant:627]: Event Type: 8
[23:17:48][D][voice_assistant:703]: Response URL: "http://192.168.1.32:8123/api/tts_proxy/bd80c857a9f4a7d75384c8df252b26f9f7fde3a3_fr-fr_ddc3b84ef4_tts.piper.wav"
[23:17:48][D][voice_assistant:504]: State changed from AWAITING_RESPONSE to STREAMING_RESPONSE
[23:17:48][D][voice_assistant:510]: Desired state set to STREAMING_RESPONSE
[23:17:48][D][i2s_audio.speaker:203]: Starting I2S Audio Speaker

Et le fichier est bien créé dans \192.168.1.32\config\tts

C’est con, le N16R8 répond plus rapidement que le T8V1.7 mais il est muet :rofl:
Bob
Bob

C’est vraiment incompréhensible :thinking:

As-tu retiré ton esp de l’intégration ESPHOME, debranché tonesp et rebranché pour que HA le détecte de nouveau ( et ne pas oublier de cocher « Autorisez l’appareil à passer des appels de service Home Assistant ») ?

Je testerai demain @Krull56 de le retirer de l’intégration ESPHOME, il est pourtant autorisé:


Merci
Je constate aussi que certain ESP32 bien que débranchés restent Online un bon moment !
Il est débranché depuis plus de 5 minutes mais il reste en vie :slight_smile:
image

Bob

Bonjour @Krull56

Je viens de faire la manipulation, ça n’a rien changé.
Bonne journée.
bob

Pause du midi, on y retourne :wink:
J’ai vérifié mes branchements et annoté le code des lignes GPIO:

i2s_audio:
  - id: i2s_in
    i2s_lrclk_pin: GPIO5  #ws micro
    i2s_bclk_pin: GPIO6   #sck micro
  - id: i2s_out
    i2s_lrclk_pin: GPIO46 #lrc ampli
    i2s_bclk_pin: GPIO9 #rclk ampli

microphone:
  - platform: i2s_audio
    id: va_mic
    adc_type: external
    i2s_din_pin: GPIO4 #sd micro
    channel: left
    pdm: false
    i2s_audio_id: i2s_in
    bits_per_sample: 32bit

speaker:
    platform: i2s_audio
    id: va_speaker
    i2s_audio_id: i2s_out
    dac_type: external
    i2s_dout_pin: GPIO10 #din ampli
    mode: mono

ça me semble ok non ?

A la vérification du code avant de flasher j’ai ceci pour les models:

micro_wake_word:
  vad:
    model:
      url: https://github.com/esphome/micro-wake-word-models/raw/main/models/v2/vad.json
      type: http
  models:
  - model:
      url: https://github.com/esphome/micro-wake-word-models/raw/main/models/v2/okay_nabu.json
      type: http
  - model:
      url: https://github.com/esphome/micro-wake-word-models/raw/main/models/v2/hey_jarvis.json
      type: http
  - model:
      url: https://github.com/esphome/micro-wake-word-models/raw/main/models/v2/alexa.json
      type: http
  on_wake_word_detected:

https mais type http :thinking:

Bon appétit :wink:
Bob

Bonjour,
Passage à ESPHome 2024.7.3, toujours pas de son avec speaker sur S3 N16R8, donc j’ai tenté d’envoyer le message sur un autre media_player mais sans succès:

  #Pour envoyer réponse sur media_player
  on_tts_end:
    then:
      - logger.log: "Passage dans on_tts_end "
      - homeassistant.service:
          service: media_player.play_media
          data:
            entity_id:  media_player.esp32_voice_control_1_mediasat1
            media_content_id: !lambda 'return x;'
            media_content_type: music
            announce: "true"

J’ai aussi testé avec ça qui fonctionne dans une automatisation:

        data:
          media_content_id: >-
            media-source://media_source/local/stomps-and-claps-percussion-and-rhythm-141190.mp3
          media_content_type: audio/mpeg

Cette commande ne donne rien dans mes logs, même placée ailleurs sur une condition dans laquelle je suis certain de passer.

- logger.log: "Passage dans on_tts_end "

Les logs de l’ESP:

[13:36:58][D][voice_assistant:627]: Event Type: 4
[13:36:58][D][voice_assistant:655]: Speech recognised as: "allumer la lumière marine"
[13:36:58][D][voice_assistant:627]: Event Type: 5
[13:36:58][D][voice_assistant:660]: Intent started
[13:36:59][D][voice_assistant:627]: Event Type: 6
[13:36:59][D][voice_assistant:627]: Event Type: 7
[13:36:59][D][voice_assistant:683]: Response: "Allumé"
[13:36:59][D][voice_assistant:627]: Event Type: 98
[13:36:59][D][voice_assistant:768]: TTS stream start
[13:36:59][D][voice_assistant:627]: Event Type: 8
[13:36:59][D][voice_assistant:703]: Response URL: "http://192.168.1.32:8123/api/tts_proxy/a54a861193bf0fc5d5dc1b9f543d744a47d3ba31_fr-fr_ddc3b84ef4_tts.piper.wav"
[13:36:59][D][voice_assistant:504]: State changed from AWAITING_RESPONSE to STREAMING_RESPONSE
[13:36:59][D][voice_assistant:510]: Desired state set to STREAMING_RESPONSE
[13:36:59][D][i2s_audio.speaker:203]: Starting I2S Audio Speaker
[13:36:59][D][light:036]: 'My Light' Setting:
[13:36:59][D][light:051]:   Brightness: 60%
[13:36:59][D][light:059]:   Red: 0%, Green: 0%, Blue: 100%
[13:36:59][D][light:085]:   Transition length: 1.0s
[13:36:59][D][voice_assistant:627]: Event Type: 2
[13:36:59][D][voice_assistant:717]: Assist Pipeline ended
[13:36:59][D][i2s_audio.speaker:206]: Started I2S Audio Speaker
[13:36:59][D][i2s_audio.speaker:210]: Stopping I2S Audio Speaker
[13:36:59][D][i2s_audio.speaker:222]: Stopped I2S Audio Speaker
[13:36:59][D][i2s_audio.speaker:203]: Starting I2S Audio Speaker
[13:36:59][D][i2s_audio.speaker:206]: Started I2S Audio Speaker
[13:37:00][D][voice_assistant:627]: Event Type: 99
[13:37:00][D][voice_assistant:776]: TTS stream end
[13:37:00][D][voice_assistant:375]: End of audio stream received
[13:37:00][D][voice_assistant:504]: State changed from STREAMING_RESPONSE to RESPONSE_FINISHED
[13:37:00][D][voice_assistant:510]: Desired state set to RESPONSE_FINISHED
[13:37:01][D][i2s_audio.speaker:210]: Stopping I2S Audio Speaker
[13:37:01][D][i2s_audio.speaker:222]: Stopped I2S Audio Speaker
[13:37:01][D][voice_assistant:407]: Speaker has finished outputting all audio
[13:37:01][D][voice_assistant:504]: State changed from RESPONSE_FINISHED to IDLE
[13:37:01][D][voice_assistant:510]: Desired state set to IDLE
[13:37:01][D][voice_assistant:504]: State changed from IDLE to START_MICROPHONE
[13:37:01][D][voice_assistant:510]: Desired state set to START_PIPELINE
[13:37:01][D][voice_assistant:221]: Starting Microphone
[13:37:01][D][voice_assistant:504]: State changed from START_MICROPHONE to STARTING_MICROPHONE
[13:37:01][D][voice_assistant:504]: State changed from STARTING_MICROPHONE to START_PIPELINE
[13:37:01][D][voice_assistant:275]: Requesting start...
[13:37:01][D][voice_assistant:504]: State changed from START_PIPELINE to STARTING_PIPELINE
[13:37:01][D][voice_assistant:525]: Client started, streaming microphone
[13:37:01][D][voice_assistant:504]: State changed from STARTING_PIPELINE to STREAMING_MICROPHONE
[13:37:01][D][voice_assistant:510]: Desired state set to STREAMING_MICROPHONE
[13:37:01][D][voice_assistant:627]: Event Type: 1
[13:37:01][D][voice_assistant:630]: Assist Pipeline running
[13:37:01][D][voice_assistant:627]: Event Type: 9
[13:37:03][D][switch:016]: 'LedIO13' Turning OFF.
[13:37:03][D][switch:055]: 'LedIO13': Sending state OFF
[13:37:03][D][light:036]: 'My Light' Setting:
[13:37:03][D][light:047]:   State: OFF
[13:37:03][D][light:085]:   Transition length: 1.0s
[13:37:03][D][light:091]:   Effect: 'None'

Peut-être faut-il déclarer ‹ media_player.esp32_voice_control_1_mediasat1 › comme on le fait pour les entitées HA dans un YAML ESPHome ?
Une idée @Krull56, @WarC0zes… je vous nomme parce que je ne peux créer un nouveau message mais peut-être devrais-je créer un nouveau sujet :wink:
Bob

Hello tout le monde,

Ayant terminer mon dashboard, je souhaite me remettre sur Assist. Je m’étais arrêter avec Vosk, Piper, Whisper et openWakeWord, mais ça a peut-être bougé entre temps. C’est le cas ou pas du tout ?

Hello

Pas de changements côté pipeline si ce n’est de nouvelles commandes de dispo, sinon les micro -wakeword intégrables directement sur esp32.
Un gros travail en cours actuellement pour préparer esphome à la sortie du device dédié qui sera vendu par Nabu Casa d’ici quelques mois.

@+

1 « J'aime »

Super, on va attendre ça bien sagement alors :slight_smile:

Merci

Hello,

du nouveau concernant le projet de nabu casa concernant un assistant vocal local ?
Sinon petite question je trouve que la reconnaissance vocal n’est pas très fiable sur mon esp avec un microphone INMP441 serait-il possible de modifier des paramètres dans le code afin d’améliorer la reconnaissance ?

esphome:
  name: esphome-web-697778
  friendly_name: esphome-web-697778
  on_boot:
    - priority: -100
      then:
        - wait_until: api.connected
        - delay: 5s
        - voice_assistant.start_continuous:

esp32:
  board: esp32dev
  framework:
    type: arduino
   
# Enable logging
logger:


# Enable Home Assistant API
api:
  encryption:
    key: ""
    
# Allow Over-The-Air updates
ota:
- platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Test Fallback Hotspot"
    password: ""

captive_portal:

light:
  - platform: binary
    name: "Light"
    output: light_output

output:
  - id: light_output
    platform: gpio
    pin: GPIO22

i2s_audio:
  - id: i2s_in
    i2s_lrclk_pin: GPIO25
    i2s_bclk_pin: GPIO32

microphone:
  - platform: i2s_audio
    adc_type: external
    pdm: false
    id: mic_i2s
    bits_per_sample: 16bit
    i2s_audio_id: i2s_in
    i2s_din_pin: GPIO33

media_player:
  - platform: i2s_audio
    id: media_sat1
    name: "media_sat1"
    i2s_dout_pin: GPIO26
    dac_type: external
    mode: mono

voice_assistant:
  id: va
  microphone: mic_i2s
  use_wake_word: true
  noise_suppression_level: 2
  auto_gain: 3dBFS
  volume_multiplier: 4.0 

  on_wake_word_detected:
    then:
      - output.turn_on: light_output
  
  on_end:
    - delay: 2s
    - output.turn_off: light_output

switch:
  - platform: template
    name: media_on
    id: media_on
    optimistic: True
    on_turn_on:
      - switch.turn_off: use_wake_word
      - delay: 1s
      - voice_assistant.stop
    on_turn_off: 
      - switch.turn_on: use_wake_word
      - delay: 1s
      - voice_assistant.start_continuous

  - platform: template
    name: Listen
    id: Listen
    optimistic: true
    on_turn_on:
     - switch.turn_off: use_wake_word
     - delay: 1s
     - voice_assistant.start_continuous
    on_turn_off:
     - switch.turn_on: use_wake_word

  - 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
    on_turn_off:
      - voice_assistant.stop
      - lambda: id(va).set_use_wake_word(false);

Hello

Tu utilise bien Vosk pour ton pipeline plutôt que faster Whisper ?
A noter que pour l’instant ça ne fonctionne bien que dans un environnement plutôt silencieux, mais ca va bientôt changer :wink:

2 « J'aime »

Ouais j’utilise bien vosk mais la transcription vocal vers texte est mauvaise comme à l’époque avec des vieux micro où on comprenais 1 mot sur 2.
Je me demandais s’il était pas possible de brancher un autre microphone sur l’esp pour avoir une meilleure captation du son.

info du core 2024.10

  • There is a new entity in town, the assist satellite entity. It is a building block for remote sattelites devices that use Assist. This is in preparation for our upcoming sattelite hardware. Stay tuned!

ca avance, mais faut encore patienter.

Dans les kit tout pret, sans soudure, j’ai trouvé celui-là :

Il est pensé pour pouvoir être encastré dans le plafond, ce qui change des assistants posé sur un meuble.

1 « J'aime »

Bonjour,
pour ceux qui utilisent un ATOM Echo, j’ai galéré à faire la MAJ de ESPHOME que je n’avais pas fait depuis aout 2024.

À force de chercher sur le GitHub de ESPHOME, j’ai trouvé la solution.
Il faut modifier le fichier YAML de la source dans packages :

packages:
  m5stack.atom-echo-voice-assistant: github://esphome/firmware/voice-assistant/m5stack-atom-echo.adopted.yaml@main

Il faudra peut-être reflasher par USB, car la table de partition à changer.

Les nouveautés ( pas tester avant aujourd’hui ) fonctionnent bien. Savoir l’heure, la date , créer un minuteur avec une sonnera quand il est fini :wink:

1 « J'aime »

Projet très intéressant, je ne sais pas si je vais résister bien longtemps à remplacer Alexa à la maison :sweat_smile:
Certain on réussi à mettre la voix de Jarvis ou autre plus originales ?
Le graal serait de pouvoir utiliser ce voice control HA sur des enceintes connectées existantes comme sonos and co voir son téléphone ou pc avec micro.

Hello

Voici un premier retour après quelques tests effectués sur le respeaker-lite voice kit.

ReSpeaker Lite Voice Assistant Kit, Full Kit of 2 Mic Array, pre-soldered XIAO ESP32S3, Mono Enclosed Speaker, and Enclosure (seeedstudio.com)

j’ai pris la totale, respeaker avec ESP32-S3 soudé , HP et petite boiboite :grin:

A peine reçu, déjà monté !

le mic array ne dispose que de 2 micros ( pas assez pour faire du beamforming) , mais le XMOS est probablement celui qui sera utilisé par le futur kit de Nabu Casa , ou une variante très proche. Cela permet de tester dès aujourd’hui quelques évolutions encore en dev dont le fameux support du media player avec le framework esp-idf ( @vincen si tu passes par là :wink: ) : GitHub - esphome/home-assistant-voice-pe: Home Assistant Voice PE

Un gars du forum anglophone a déjà adapté provisoirement le yaml pour ce respeaker-lite, j’ai donc fait le fainéant sur ce coup.

Pas de chance pour moi, la led est HS (suis pas le seul dans ce cas) , mais pour le reste…CA FONCTIONNE !!! :stuck_out_tongue_winking_eye:

Plutôt très réactif à 4-5 m, le speaker de 5 watts balance pas mal (il y a aussi une sortie jack de dispo si on veut du GROS son @Bob )
Et cerise sur le gateau, enfin, après tant d’attente, le media player fonctionne ( testé avec music assistant)

Voili, voilà, en se basant sur ces résultats, on peut estimer que le voice kit de NAbu sera certainement le Graal tant attendu, on y croit :crossed_fingers:
Et le Satellite one de Brad ( FuturProofHome) promet aussi …
Vivement noël :christmas_tree:

Et pour @vincen, le yaml ( à adapter bien sur puisque tu utilise un ESP32 externe), avec media player et timer

@+

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
    components:
      - aic3204
      - audio_dac
      - media_player
      - micro_wake_word
      - microphone
      - nabu
      - nabu_microphone
      - voice_assistant
      - voice_kit
    refresh: 0s

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

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

logger:

wifi:
  ap:
    ssid: "Respeaker-Satellite-1"
    password: "SDCi3ZeMJi3d"
  on_connect:
    - script.execute: adjust_led
  on_disconnect:
    - script.execute: adjust_led
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  

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
    id: mute
    name: "Mute"
  - platform: gpio
    pin: 
      number: GPIO3 # D2
    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: False
    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
      

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
    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.15.254: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: 0%
                      blue: 100%
                      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}
2 « J'aime »