320 lines
8.8 KiB
YAML
320 lines
8.8 KiB
YAML
substitutions:
|
|
device_name: "voiceassist1"
|
|
friendly_name: "ESP32 voice Assist 2"
|
|
comment: "esp32-s3, mic, dac, RGB"
|
|
api_password: !secret voiceassist1_api
|
|
ota_password: !secret ota_password
|
|
wifi_ssid: !secret wifi_ssid
|
|
wifi_password: !secret wifi_password
|
|
gateway: !secret ip_gateway
|
|
subnet: !secret ip_subnet
|
|
ip: !secret voiceassist1_ip
|
|
pin_lrclk: GPIO18
|
|
pin_bclk: GPIO6
|
|
pin_i2sdin: GPIO16
|
|
pin_i2sdout: GPIO17
|
|
#pin_button: GPIO14
|
|
pin_led1: GPIO48
|
|
num_leds: "1"
|
|
chipset: ws2812
|
|
|
|
micro_wake_word_model: okay_nabu
|
|
|
|
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"
|
|
|
|
packages:
|
|
board: !include boards/esp32-s3-voice.yaml
|
|
spkmic: !include interfaces/SpkMicVoice.yaml
|
|
leds: !include templates/light_rgbw_rmt.yaml
|
|
connection: !include common/wifi.yaml
|
|
logger: !include templates/logger.yaml
|
|
|
|
|
|
esphome:
|
|
name: ${device_name}
|
|
friendly_name: ${friendly_name}
|
|
name_add_mac_suffix: true
|
|
platformio_options:
|
|
board_build.flash_mode: dio
|
|
min_version: 2023.11.5
|
|
project:
|
|
name: esphome.voice-assistant
|
|
version: "2.0"
|
|
on_boot:
|
|
priority: 600
|
|
then:
|
|
- delay: 30s
|
|
- if:
|
|
condition:
|
|
lambda: return id(init_in_progress);
|
|
then:
|
|
- lambda: id(init_in_progress) = false;
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 0%
|
|
green: 50%
|
|
blue: 50%
|
|
effect: pulse
|
|
|
|
dashboard_import:
|
|
package_import_url: github://esphome/firmware/wake-word-voice-assistant/esp32-s3-box.yaml@main
|
|
|
|
button:
|
|
- platform: factory_reset
|
|
id: factory_reset_btn
|
|
name: Factory reset
|
|
|
|
esp32_improv:
|
|
authorizer: none
|
|
|
|
binary_sensor:
|
|
- platform: gpio
|
|
pin:
|
|
number: GPIO1
|
|
inverted: true
|
|
name: "Mute"
|
|
disabled_by_default: true
|
|
entity_category: diagnostic
|
|
|
|
micro_wake_word:
|
|
model: ${micro_wake_word_model}
|
|
on_wake_word_detected:
|
|
- voice_assistant.start
|
|
|
|
voice_assistant:
|
|
id: va
|
|
microphone: mic
|
|
use_wake_word: true
|
|
noise_suppression_level: 2
|
|
auto_gain: 31dBFS
|
|
volume_multiplier: 2.0
|
|
speaker: big_speaker
|
|
on_client_connected:
|
|
- if:
|
|
condition:
|
|
switch.is_off: mute
|
|
then:
|
|
- wait_until:
|
|
not: ble.enabled
|
|
- if:
|
|
condition:
|
|
lambda: return id(wake_word_engine_location).state == "In Home Assistant";
|
|
then:
|
|
- lambda: id(va).set_use_wake_word(true);
|
|
- voice_assistant.start_continuous:
|
|
- if:
|
|
condition:
|
|
lambda: return id(wake_word_engine_location).state == "On device";
|
|
then:
|
|
- micro_wake_word.start
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
|
|
else:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id};
|
|
- lambda: id(init_in_progress) = false;
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 0%
|
|
green: 100%
|
|
blue: 0%
|
|
effect: none
|
|
on_listening:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_listening_phase_id};
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 0%
|
|
green: 100%
|
|
blue: 0%
|
|
effect: pulse
|
|
on_stt_vad_end:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id};
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 0%
|
|
green: 100%
|
|
blue: 100%
|
|
effect: Pulse
|
|
on_tts_stream_start:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id};
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 0%
|
|
green: 100%
|
|
blue: 100%
|
|
effect: none
|
|
on_tts_stream_end:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 0%
|
|
green: 0%
|
|
blue: 100%
|
|
effect: Pulse
|
|
on_error:
|
|
- if:
|
|
condition:
|
|
lambda: return !id(init_in_progress);
|
|
then:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id};
|
|
- delay: 1s
|
|
- if:
|
|
condition:
|
|
switch.is_off: mute
|
|
then:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
|
|
else:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id};
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 100%
|
|
green: 0%
|
|
blue: 0%
|
|
effect: Pulse
|
|
- delay: 4s
|
|
- light.turn_off:
|
|
id: led_lights
|
|
on_client_disconnected:
|
|
- if:
|
|
condition:
|
|
lambda: return id(wake_word_engine_location).state == "In Home Assistant";
|
|
then:
|
|
- lambda: id(va).set_use_wake_word(false);
|
|
- voice_assistant.stop:
|
|
- if:
|
|
condition:
|
|
lambda: return id(wake_word_engine_location).state == "On device";
|
|
then:
|
|
- micro_wake_word.stop
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id};
|
|
- light.turn_on:
|
|
id: led_lights
|
|
brightness: 30%
|
|
red: 100%
|
|
green: 0%
|
|
blue: 0%
|
|
effect: none
|
|
on_end:
|
|
- if:
|
|
condition:
|
|
and:
|
|
- switch.is_off: mute
|
|
- lambda: return id(wake_word_engine_location).state == "On device";
|
|
then:
|
|
- wait_until:
|
|
not:
|
|
voice_assistant.is_running:
|
|
- micro_wake_word.start:
|
|
|
|
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(assist).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(assist).set_use_wake_word(false);
|
|
|
|
- platform: template
|
|
name: Mute
|
|
id: mute
|
|
optimistic: true
|
|
restore_mode: RESTORE_DEFAULT_OFF
|
|
entity_category: config
|
|
on_turn_off:
|
|
- if:
|
|
condition:
|
|
lambda: return !id(init_in_progress);
|
|
then:
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id};
|
|
- if:
|
|
condition:
|
|
not:
|
|
- voice_assistant.is_running
|
|
then:
|
|
- if:
|
|
condition:
|
|
lambda: return id(wake_word_engine_location).state == "In Home Assistant";
|
|
then:
|
|
- lambda: id(va).set_use_wake_word(true);
|
|
- voice_assistant.start_continuous
|
|
- if:
|
|
condition:
|
|
lambda: return id(wake_word_engine_location).state == "On device";
|
|
then:
|
|
- micro_wake_word.start
|
|
on_turn_on:
|
|
- if:
|
|
condition:
|
|
lambda: return !id(init_in_progress);
|
|
then:
|
|
- lambda: id(va).set_use_wake_word(false);
|
|
- voice_assistant.stop
|
|
- micro_wake_word.stop
|
|
- lambda: id(voice_assistant_phase) = ${voice_assist_muted_phase_id};
|
|
|
|
select:
|
|
- platform: template
|
|
entity_category: config
|
|
name: Wake word engine location
|
|
id: wake_word_engine_location
|
|
optimistic: true
|
|
restore_value: true
|
|
options:
|
|
- In Home Assistant
|
|
- On device
|
|
initial_option: On device
|
|
on_value:
|
|
- wait_until:
|
|
lambda: return id(voice_assistant_phase) == ${voice_assist_muted_phase_id} || id(voice_assistant_phase) == ${voice_assist_idle_phase_id};
|
|
- if:
|
|
condition:
|
|
lambda: return x == "In Home Assistant";
|
|
then:
|
|
- micro_wake_word.stop
|
|
- delay: 500ms
|
|
- if:
|
|
condition:
|
|
switch.is_off: mute
|
|
then:
|
|
- lambda: id(va).set_use_wake_word(true);
|
|
- voice_assistant.start_continuous:
|
|
- if:
|
|
condition:
|
|
lambda: return x == "On device";
|
|
then:
|
|
- lambda: id(va).set_use_wake_word(false);
|
|
- voice_assistant.stop
|
|
- delay: 500ms
|
|
- micro_wake_word.start
|
|
|
|
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} |