From ab23ad99832bbfb58f2e22d5be7a82e51b6da535 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Mon, 9 Sep 2024 14:19:42 -0500 Subject: [PATCH] Add announce (#64) * Add announce * Add finished message * Add triggers (defer did not work) * Remove url from VoiceAssistantAnnounceFinished * Add success flag to VoiceAssistantAnnounceFinished --- .../voice_assistant/voice_assistant.cpp | 22 ++++++++++++++++++- .../voice_assistant/voice_assistant.h | 8 +++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index f3f95b2..8038133 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -435,6 +435,10 @@ void VoiceAssistant::loop() { this->set_timeout("playing", 50, [this]() { this->cancel_timeout("speaker-timeout"); this->set_state_(State::IDLE, State::IDLE); + + api::VoiceAssistantAnnounceFinished msg; + msg.success = true; + this->api_client_->send_voice_assistant_announce_finished(msg); }); } break; @@ -767,7 +771,11 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } case api::enums::VOICE_ASSISTANT_RUN_END: { ESP_LOGD(TAG, "Assist Pipeline ended"); - if (this->state_ == State::STREAMING_MICROPHONE) { + if (this->state_ == State::STARTING_PIPELINE) { + // Pipeline ended before starting microphone + this->set_state_(State::IDLE, State::IDLE); + } + else if (this->state_ == State::STREAMING_MICROPHONE) { this->ring_buffer_->reset(); #ifdef USE_ESP_ADF if (this->use_wake_word_) { @@ -910,6 +918,18 @@ void VoiceAssistant::timer_tick_() { this->timer_tick_trigger_->trigger(res); } +void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) { +#ifdef USE_MEDIA_PLAYER + if (this->media_player_ != nullptr) { + this->tts_start_trigger_->trigger(msg.text); + this->media_player_->make_call().set_media_url(msg.media_id).set_announcement(true).perform(); + this->set_state_(State::STREAMING_RESPONSE, State::STREAMING_RESPONSE); + this->tts_end_trigger_->trigger(msg.media_id); + this->end_trigger_->trigger(); + } +#endif +} + VoiceAssistant *global_voice_assistant = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace voice_assistant diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 16d9eaa..33831b8 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -43,6 +43,7 @@ enum VoiceAssistantFeature : uint32_t { FEATURE_SPEAKER = 1 << 1, FEATURE_API_AUDIO = 1 << 2, FEATURE_TIMERS = 1 << 3, + FEATURE_ANNOUNCE = 1 << 4, }; enum class State { @@ -134,6 +135,12 @@ class VoiceAssistant : public Component { flags |= VoiceAssistantFeature::FEATURE_TIMERS; } +#ifdef USE_MEDIA_PLAYER + if (this->media_player_ != nullptr) { + flags |= VoiceAssistantFeature::FEATURE_ANNOUNCE; + } +#endif + return flags; } @@ -147,6 +154,7 @@ class VoiceAssistant : public Component { void on_event(const api::VoiceAssistantEventResponse &msg); void on_audio(const api::VoiceAssistantAudio &msg); void on_timer_event(const api::VoiceAssistantTimerEventResponse &msg); + void on_announce(const api::VoiceAssistantAnnounceRequest &msg); bool is_running() const { return this->state_ != State::IDLE; } void set_continuous(bool continuous) { this->continuous_ = continuous; }