From b8c1086b791484aa5d4addc554d47808b0eddc09 Mon Sep 17 00:00:00 2001 From: tetele Date: Wed, 15 Jan 2025 14:50:41 +0000 Subject: [PATCH] Added Nabu VPE components --- esphome/modular-onju.yaml | 27 +++++ esphome/onju-modules/audio-nabu.yaml | 81 +++++++++++++ esphome/onju-modules/media_player.yaml | 109 ++++++++++++++++++ esphome/onju-modules/microphone.yaml | 2 + .../onju-modules/voice_assistant-nabu.yaml | 23 ++++ esphome/onju-modules/voice_assistant.yaml | 62 ++++++++++ 6 files changed, 304 insertions(+) create mode 100644 esphome/onju-modules/audio-nabu.yaml create mode 100644 esphome/onju-modules/media_player.yaml create mode 100644 esphome/onju-modules/microphone.yaml create mode 100644 esphome/onju-modules/voice_assistant-nabu.yaml create mode 100644 esphome/onju-modules/voice_assistant.yaml diff --git a/esphome/modular-onju.yaml b/esphome/modular-onju.yaml index c1dc3c4..29291a5 100644 --- a/esphome/modular-onju.yaml +++ b/esphome/modular-onju.yaml @@ -10,4 +10,31 @@ packages: onju_leds: !include onju-modules/leds.yaml onju_controls: !include onju-modules/controls.yaml # audio_gnumpi: !include onju-modules/audio-gnumpi.yaml + audio_nabu: !include onju-modules/audio-nabu.yaml # onju_va_mww: !include onju-modules/micro_wake_word.yaml + va_nabu: !include onju-modules/voice_assistant-nabu.yaml + +# TEMP https://discord.com/channels/429907082951524364/1324733194980950106 +esp32: + framework: + version: 4.4.8 + platform_version: 5.4.0 + +binary_sensor: + - id: !extend action + on_click: + then: + - logger.log: + tag: "action_click" + format: "Voice assistant is running: %s" + args: ['id(va).is_running() ? "yes" : "no"'] + - if: + condition: media_player.is_playing + then: + - media_player.stop + - if: + condition: voice_assistant.is_running + then: + - voice_assistant.stop: + else: + - voice_assistant.start: diff --git a/esphome/onju-modules/audio-nabu.yaml b/esphome/onju-modules/audio-nabu.yaml new file mode 100644 index 0000000..5305463 --- /dev/null +++ b/esphome/onju-modules/audio-nabu.yaml @@ -0,0 +1,81 @@ +packages: + onju_microphone: !include microphone.yaml + onju_media_player: !include media_player.yaml + +external_components: + - source: + type: git + url: https://github.com/esphome/home-assistant-voice-pe + ref: dev + components: + - media_player + - microphone + - nabu + - nabu_microphone +i2s_audio: + - id: i2s_output + i2s_lrclk_pin: + number: GPIO13 + allow_other_uses: true + i2s_bclk_pin: + number: GPIO18 + allow_other_uses: true + + - id: i2s_input + i2s_lrclk_pin: + number: GPIO13 + allow_other_uses: true + i2s_bclk_pin: + number: GPIO18 + allow_other_uses: true + +speaker: + - platform: i2s_audio + sample_rate: 16000 + i2s_mode: primary + i2s_dout_pin: GPIO12 + bits_per_sample: 32bit + i2s_audio_id: i2s_output + dac_type: external + channel: stereo + timeout: never + buffer_duration: 100ms + +microphone: + - id: !remove onju_microphone + - platform: nabu_microphone + i2s_din_pin: GPIO17 + adc_type: external + pdm: false + sample_rate: 16000 + bits_per_sample: 32bit + i2s_mode: primary + i2s_audio_id: i2s_input + channel_0: + id: onju_microphone + amplify_shift: 2 + channel_1: + id: comm_mic + amplify_shift: 2 + +media_player: + - id: !extend onju_out + platform: nabu + speaker: + sample_rate: 16000 + volume_increment: 0.05 + volume_min: 0.4 + volume_max: 0.85 + files: + - id: wake_word_triggered_sound + file: ${wakeup_sound_url} + +switch: + # TODO + - platform: gpio + id: dac_mute + name: DAC mute + restore_mode: ALWAYS_OFF + pin: + number: GPIO21 + inverted: True diff --git a/esphome/onju-modules/media_player.yaml b/esphome/onju-modules/media_player.yaml new file mode 100644 index 0000000..9f1fbd5 --- /dev/null +++ b/esphome/onju-modules/media_player.yaml @@ -0,0 +1,109 @@ +substitutions: + wakeup_sound_url: "https://github.com/tetele/onju-voice-satellite/raw/main/res/wakeup.mp3" # New Notification #7 by UNIVERSFIELD https://freesound.org/people/UNIVERSFIELD/sounds/736267/ + error_sound_url: "https://github.com/tetele/onju-voice-satellite/raw/main/res/error.mp3" # Error #8 by UNIVERSFIELD https://freesound.org/people/UNIVERSFIELD/sounds/734442/ + timer_finished_sound_url: "https://github.com/tetele/onju-voice-satellite/raw/main/res/timer_finished.mp3" # New Notification #6 by UNIVERSFIELD https://freesound.org/people/UNIVERSFIELD/sounds/734445/ + +media_player: + - id: onju_out + name: None + on_state: + then: + - lambda: |- + static float old_volume = -1; + float new_volume = id(onju_out).volume; + if(abs(new_volume-old_volume) > 0.0001) { + if(old_volume != -1) { + id(show_volume) = true; + id(control_led)->execute(); + } + } + old_volume = new_volume; + +globals: + - id: show_volume + type: bool + restore_value: no + initial_value: "false" + +light: + - id: !extend top_led + effects: + - addressable_lambda: + name: show_volume + update_interval: 50ms + lambda: |- + int int_volume = int(id(onju_out).volume * 100.0f * it.size()); + int full_leds = int_volume / 100; + int last_brightness = int_volume % 100; + int i = 0; + for(; i < full_leds; i++) { + it[i] = Color::WHITE; + } + if(i < 4) { + it[i++] = Color(64, 64, 64).fade_to_white(last_brightness*256/100); + } + for(; i < it.size(); i++) { + it[i] = Color(64, 64, 64); + } + +script: + - id: set_volume + mode: restart + parameters: + volume: float + then: + - media_player.volume_set: + id: onju_out + volume: !lambda return clamp(id(onju_out).volume+volume, 0.0f, 1.0f); + - lambda: | + id(show_volume) = true; + - script.execute: control_led + + - id: !extend control_led_volume_touched + then: + - if: + condition: + lambda: "return id(show_volume);" + then: + - light.turn_on: + id: top_led + effect: show_volume + - delay: 1s + - lambda: | + id(show_volume) = false; + - script.execute: control_led + else: + - light.turn_off: top_led + +binary_sensor: + - id: !extend volume_down + on_press: + then: + - script.execute: + id: set_volume + volume: -0.05 + - delay: 750ms + - while: + condition: + binary_sensor.is_on: volume_down + then: + - script.execute: + id: set_volume + volume: -0.05 + - delay: 150ms + + - id: !extend volume_up + on_press: + then: + - script.execute: + id: set_volume + volume: 0.05 + - delay: 750ms + - while: + condition: + binary_sensor.is_on: volume_up + then: + - script.execute: + id: set_volume + volume: 0.05 + - delay: 150ms diff --git a/esphome/onju-modules/microphone.yaml b/esphome/onju-modules/microphone.yaml new file mode 100644 index 0000000..491c4ff --- /dev/null +++ b/esphome/onju-modules/microphone.yaml @@ -0,0 +1,2 @@ +microphone: + - id: onju_microphone diff --git a/esphome/onju-modules/voice_assistant-nabu.yaml b/esphome/onju-modules/voice_assistant-nabu.yaml new file mode 100644 index 0000000..2918a71 --- /dev/null +++ b/esphome/onju-modules/voice_assistant-nabu.yaml @@ -0,0 +1,23 @@ +packages: + onju_voice_assistant: !include voice_assistant.yaml + +external_components: + - source: + type: git + url: https://github.com/tetele/home-assistant-voice-pe + ref: fix-mww-guarding + components: + - voice_assistant + # refresh: 0s + +voice_assistant: + microphone: onju_microphone + media_player: onju_out + use_wake_word: false + noise_suppression_level: 0 + auto_gain: 0 dbfs + volume_multiplier: 1 + on_end: + then: + - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; + - script.execute: control_led diff --git a/esphome/onju-modules/voice_assistant.yaml b/esphome/onju-modules/voice_assistant.yaml new file mode 100644 index 0000000..9617b44 --- /dev/null +++ b/esphome/onju-modules/voice_assistant.yaml @@ -0,0 +1,62 @@ +globals: + - id: !extend voice_assistant_phase + initial_value: ${voice_assist_not_ready_phase_id} # used to make the leds not blink when the va component is not loaded + +api: + services: + - service: start_va + then: + - voice_assistant.start + - service: stop_va + then: + - voice_assistant.stop + +voice_assistant: + id: va + microphone: onju_microphone + use_wake_word: false + # TODO + on_listening: + - lambda: id(voice_assistant_phase) = ${voice_assist_waiting_for_command_phase_id}; + - script.execute: control_led + on_stt_vad_start: + - lambda: id(voice_assistant_phase) = ${voice_assist_listening_for_command_phase_id}; + - script.execute: control_led + on_stt_vad_end: + - lambda: id(voice_assistant_phase) = ${voice_assist_thinking_phase_id}; + - script.execute: control_led + on_tts_start: + - lambda: id(voice_assistant_phase) = ${voice_assist_replying_phase_id}; + - script.execute: control_led + on_client_connected: + - lambda: id(init_in_progress) = false; + - lambda: id(voice_assistant_phase) = ${voice_assist_idle_phase_id}; + - script.execute: control_led + on_client_disconnected: + - voice_assistant.stop: + - lambda: id(voice_assistant_phase) = ${voice_assist_not_ready_phase_id}; + - script.execute: control_led + on_error: + - if: + condition: + and: + - lambda: return !id(init_in_progress); + - lambda: return code != "duplicate_wake_up_detected"; + then: + - lambda: id(voice_assistant_phase) = ${voice_assist_error_phase_id}; + - script.execute: control_led + +script: + - id: turn_on_wake_word + then: [] + - id: turn_off_wake_word + then: [] + + +# TODO +binary_sensor: + - id: !extend mute_switch + on_press: + - script.execute: turn_off_wake_word + on_release: + - script.execute: turn_on_wake_word