1
0
mirror of https://github.com/esphome/esphome.git synced 2026-02-08 08:41:59 +00:00

[voice_assistant] Avoid heap allocation for triggers

This commit is contained in:
J. Nick Koston
2026-02-02 03:31:14 +01:00
parent 1ff2f3b6a3
commit 4beed62df1
2 changed files with 75 additions and 75 deletions

View File

@@ -197,7 +197,7 @@ void VoiceAssistant::loop() {
switch (this->state_) {
case State::IDLE: {
if (this->continuous_ && this->desired_state_ == State::IDLE) {
this->idle_trigger_->trigger();
this->idle_trigger_.trigger();
this->set_state_(State::START_MICROPHONE, State::START_PIPELINE);
} else {
this->deallocate_buffers_();
@@ -254,7 +254,7 @@ void VoiceAssistant::loop() {
if (this->api_client_ == nullptr ||
!this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE)) {
ESP_LOGW(TAG, "Could not request start");
this->error_trigger_->trigger("not-connected", "Could not request start");
this->error_trigger_.trigger("not-connected", "Could not request start");
this->continuous_ = false;
this->set_state_(State::IDLE, State::IDLE);
break;
@@ -384,7 +384,7 @@ void VoiceAssistant::loop() {
this->wait_for_stream_end_ = false;
this->stream_ended_ = false;
this->tts_stream_end_trigger_->trigger();
this->tts_stream_end_trigger_.trigger();
}
#endif
if (this->continue_conversation_) {
@@ -425,7 +425,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
return;
}
this->api_client_ = nullptr;
this->client_disconnected_trigger_->trigger();
this->client_disconnected_trigger_.trigger();
return;
}
@@ -440,7 +440,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
}
this->api_client_ = client;
this->client_connected_trigger_->trigger();
this->client_connected_trigger_.trigger();
}
static const LogString *voice_assistant_state_to_string(State state) {
@@ -491,7 +491,7 @@ void VoiceAssistant::set_state_(State state, State desired_state) {
void VoiceAssistant::failed_to_start() {
ESP_LOGE(TAG, "Failed to start server. See Home Assistant logs for more details.");
this->error_trigger_->trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details.");
this->error_trigger_.trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details.");
this->set_state_(State::STOP_MICROPHONE, State::IDLE);
}
@@ -637,18 +637,18 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
}
#endif
this->defer([this]() { this->start_trigger_->trigger(); });
this->defer([this]() { this->start_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_WAKE_WORD_START:
break;
case api::enums::VOICE_ASSISTANT_WAKE_WORD_END: {
ESP_LOGD(TAG, "Wake word detected");
this->defer([this]() { this->wake_word_detected_trigger_->trigger(); });
this->defer([this]() { this->wake_word_detected_trigger_.trigger(); });
break;
}
case api::enums::VOICE_ASSISTANT_STT_START:
ESP_LOGD(TAG, "STT started");
this->defer([this]() { this->listening_trigger_->trigger(); });
this->defer([this]() { this->listening_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_STT_END: {
std::string text;
@@ -665,12 +665,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
text += "...";
}
ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str());
this->defer([this, text]() { this->stt_end_trigger_->trigger(text); });
this->defer([this, text]() { this->stt_end_trigger_.trigger(text); });
break;
}
case api::enums::VOICE_ASSISTANT_INTENT_START:
ESP_LOGD(TAG, "Intent started");
this->defer([this]() { this->intent_start_trigger_->trigger(); });
this->defer([this]() { this->intent_start_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_INTENT_PROGRESS: {
ESP_LOGD(TAG, "Intent progress");
@@ -693,7 +693,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
}
#endif
this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_->trigger(tts_url_for_trigger); });
this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_.trigger(tts_url_for_trigger); });
break;
}
case api::enums::VOICE_ASSISTANT_INTENT_END: {
@@ -704,7 +704,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
this->continue_conversation_ = (arg.value == "1");
}
}
this->defer([this]() { this->intent_end_trigger_->trigger(); });
this->defer([this]() { this->intent_end_trigger_.trigger(); });
break;
}
case api::enums::VOICE_ASSISTANT_TTS_START: {
@@ -724,7 +724,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
ESP_LOGD(TAG, "Response: \"%s\"", text.c_str());
this->defer([this, text]() {
this->tts_start_trigger_->trigger(text);
this->tts_start_trigger_.trigger(text);
#ifdef USE_SPEAKER
if (this->speaker_ != nullptr) {
this->speaker_->start();
@@ -756,7 +756,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
this->started_streaming_tts_ = false; // Helps indicate reaching the TTS_END stage
#endif
this->tts_end_trigger_->trigger(url);
this->tts_end_trigger_.trigger(url);
});
State new_state = this->local_output_ ? State::STREAMING_RESPONSE : State::IDLE;
if (new_state != this->state_) {
@@ -776,7 +776,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
// No TTS start event ("nevermind")
this->set_state_(State::IDLE, State::IDLE);
}
this->defer([this]() { this->end_trigger_->trigger(); });
this->defer([this]() { this->end_trigger_.trigger(); });
break;
}
case api::enums::VOICE_ASSISTANT_ERROR: {
@@ -796,7 +796,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
// Wake word is not set up or not ready on Home Assistant so stop and do not retry until user starts again.
this->defer([this, code, message]() {
this->request_stop();
this->error_trigger_->trigger(code, message);
this->error_trigger_.trigger(code, message);
});
return;
}
@@ -805,7 +805,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
this->signal_stop_();
this->set_state_(State::STOP_MICROPHONE, State::IDLE);
}
this->defer([this, code, message]() { this->error_trigger_->trigger(code, message); });
this->defer([this, code, message]() { this->error_trigger_.trigger(code, message); });
break;
}
case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: {
@@ -813,7 +813,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
if (this->speaker_ != nullptr) {
this->wait_for_stream_end_ = true;
ESP_LOGD(TAG, "TTS stream start");
this->defer([this] { this->tts_stream_start_trigger_->trigger(); });
this->defer([this] { this->tts_stream_start_trigger_.trigger(); });
}
#endif
break;
@@ -829,12 +829,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
case api::enums::VOICE_ASSISTANT_STT_VAD_START:
ESP_LOGD(TAG, "Starting STT by VAD");
this->defer([this]() { this->stt_vad_start_trigger_->trigger(); });
this->defer([this]() { this->stt_vad_start_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_STT_VAD_END:
ESP_LOGD(TAG, "STT by VAD end");
this->set_state_(State::STOP_MICROPHONE, State::AWAITING_RESPONSE);
this->defer([this]() { this->stt_vad_end_trigger_->trigger(); });
this->defer([this]() { this->stt_vad_end_trigger_.trigger(); });
break;
default:
ESP_LOGD(TAG, "Unhandled event type: %" PRId32, msg.event_type);
@@ -876,17 +876,17 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse
switch (msg.event_type) {
case api::enums::VOICE_ASSISTANT_TIMER_STARTED:
this->timer_started_trigger_->trigger(timer);
this->timer_started_trigger_.trigger(timer);
break;
case api::enums::VOICE_ASSISTANT_TIMER_UPDATED:
this->timer_updated_trigger_->trigger(timer);
this->timer_updated_trigger_.trigger(timer);
break;
case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED:
this->timer_cancelled_trigger_->trigger(timer);
this->timer_cancelled_trigger_.trigger(timer);
this->timers_.erase(timer.id);
break;
case api::enums::VOICE_ASSISTANT_TIMER_FINISHED:
this->timer_finished_trigger_->trigger(timer);
this->timer_finished_trigger_.trigger(timer);
this->timers_.erase(timer.id);
break;
}
@@ -910,13 +910,13 @@ void VoiceAssistant::timer_tick_() {
}
res.push_back(timer);
}
this->timer_tick_trigger_->trigger(res);
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->tts_start_trigger_.trigger(msg.text);
this->media_player_response_state_ = MediaPlayerResponseState::URL_SENT;
@@ -939,8 +939,8 @@ void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg)
this->set_state_(State::STREAMING_RESPONSE, State::STREAMING_RESPONSE);
}
this->tts_end_trigger_->trigger(msg.media_id);
this->end_trigger_->trigger();
this->tts_end_trigger_.trigger(msg.media_id);
this->end_trigger_.trigger();
}
#endif
}

View File

@@ -195,38 +195,38 @@ class VoiceAssistant : public Component {
void set_conversation_timeout(uint32_t conversation_timeout) { this->conversation_timeout_ = conversation_timeout; }
void reset_conversation_id();
Trigger<> *get_intent_end_trigger() const { return this->intent_end_trigger_; }
Trigger<> *get_intent_start_trigger() const { return this->intent_start_trigger_; }
Trigger<std::string> *get_intent_progress_trigger() const { return this->intent_progress_trigger_; }
Trigger<> *get_listening_trigger() const { return this->listening_trigger_; }
Trigger<> *get_end_trigger() const { return this->end_trigger_; }
Trigger<> *get_start_trigger() const { return this->start_trigger_; }
Trigger<> *get_stt_vad_end_trigger() const { return this->stt_vad_end_trigger_; }
Trigger<> *get_stt_vad_start_trigger() const { return this->stt_vad_start_trigger_; }
Trigger<> *get_intent_end_trigger() { return &this->intent_end_trigger_; }
Trigger<> *get_intent_start_trigger() { return &this->intent_start_trigger_; }
Trigger<std::string> *get_intent_progress_trigger() { return &this->intent_progress_trigger_; }
Trigger<> *get_listening_trigger() { return &this->listening_trigger_; }
Trigger<> *get_end_trigger() { return &this->end_trigger_; }
Trigger<> *get_start_trigger() { return &this->start_trigger_; }
Trigger<> *get_stt_vad_end_trigger() { return &this->stt_vad_end_trigger_; }
Trigger<> *get_stt_vad_start_trigger() { return &this->stt_vad_start_trigger_; }
#ifdef USE_SPEAKER
Trigger<> *get_tts_stream_start_trigger() const { return this->tts_stream_start_trigger_; }
Trigger<> *get_tts_stream_end_trigger() const { return this->tts_stream_end_trigger_; }
Trigger<> *get_tts_stream_start_trigger() { return &this->tts_stream_start_trigger_; }
Trigger<> *get_tts_stream_end_trigger() { return &this->tts_stream_end_trigger_; }
#endif
Trigger<> *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; }
Trigger<std::string> *get_stt_end_trigger() const { return this->stt_end_trigger_; }
Trigger<std::string> *get_tts_end_trigger() const { return this->tts_end_trigger_; }
Trigger<std::string> *get_tts_start_trigger() const { return this->tts_start_trigger_; }
Trigger<std::string, std::string> *get_error_trigger() const { return this->error_trigger_; }
Trigger<> *get_idle_trigger() const { return this->idle_trigger_; }
Trigger<> *get_wake_word_detected_trigger() { return &this->wake_word_detected_trigger_; }
Trigger<std::string> *get_stt_end_trigger() { return &this->stt_end_trigger_; }
Trigger<std::string> *get_tts_end_trigger() { return &this->tts_end_trigger_; }
Trigger<std::string> *get_tts_start_trigger() { return &this->tts_start_trigger_; }
Trigger<std::string, std::string> *get_error_trigger() { return &this->error_trigger_; }
Trigger<> *get_idle_trigger() { return &this->idle_trigger_; }
Trigger<> *get_client_connected_trigger() const { return this->client_connected_trigger_; }
Trigger<> *get_client_disconnected_trigger() const { return this->client_disconnected_trigger_; }
Trigger<> *get_client_connected_trigger() { return &this->client_connected_trigger_; }
Trigger<> *get_client_disconnected_trigger() { return &this->client_disconnected_trigger_; }
void client_subscription(api::APIConnection *client, bool subscribe);
api::APIConnection *get_api_connection() const { return this->api_client_; }
void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; }
Trigger<Timer> *get_timer_started_trigger() const { return this->timer_started_trigger_; }
Trigger<Timer> *get_timer_updated_trigger() const { return this->timer_updated_trigger_; }
Trigger<Timer> *get_timer_cancelled_trigger() const { return this->timer_cancelled_trigger_; }
Trigger<Timer> *get_timer_finished_trigger() const { return this->timer_finished_trigger_; }
Trigger<std::vector<Timer>> *get_timer_tick_trigger() const { return this->timer_tick_trigger_; }
Trigger<Timer> *get_timer_started_trigger() { return &this->timer_started_trigger_; }
Trigger<Timer> *get_timer_updated_trigger() { return &this->timer_updated_trigger_; }
Trigger<Timer> *get_timer_cancelled_trigger() { return &this->timer_cancelled_trigger_; }
Trigger<Timer> *get_timer_finished_trigger() { return &this->timer_finished_trigger_; }
Trigger<std::vector<Timer>> *get_timer_tick_trigger() { return &this->timer_tick_trigger_; }
void set_has_timers(bool has_timers) { this->has_timers_ = has_timers; }
const std::unordered_map<std::string, Timer> &get_timers() const { return this->timers_; }
@@ -243,37 +243,37 @@ class VoiceAssistant : public Component {
std::unique_ptr<socket::Socket> socket_ = nullptr;
struct sockaddr_storage dest_addr_;
Trigger<> *intent_end_trigger_ = new Trigger<>();
Trigger<> *intent_start_trigger_ = new Trigger<>();
Trigger<> *listening_trigger_ = new Trigger<>();
Trigger<> *end_trigger_ = new Trigger<>();
Trigger<> *start_trigger_ = new Trigger<>();
Trigger<> *stt_vad_start_trigger_ = new Trigger<>();
Trigger<> *stt_vad_end_trigger_ = new Trigger<>();
Trigger<> intent_end_trigger_;
Trigger<> intent_start_trigger_;
Trigger<> listening_trigger_;
Trigger<> end_trigger_;
Trigger<> start_trigger_;
Trigger<> stt_vad_start_trigger_;
Trigger<> stt_vad_end_trigger_;
#ifdef USE_SPEAKER
Trigger<> *tts_stream_start_trigger_ = new Trigger<>();
Trigger<> *tts_stream_end_trigger_ = new Trigger<>();
Trigger<> tts_stream_start_trigger_;
Trigger<> tts_stream_end_trigger_;
#endif
Trigger<std::string> *intent_progress_trigger_ = new Trigger<std::string>();
Trigger<> *wake_word_detected_trigger_ = new Trigger<>();
Trigger<std::string> *stt_end_trigger_ = new Trigger<std::string>();
Trigger<std::string> *tts_end_trigger_ = new Trigger<std::string>();
Trigger<std::string> *tts_start_trigger_ = new Trigger<std::string>();
Trigger<std::string, std::string> *error_trigger_ = new Trigger<std::string, std::string>();
Trigger<> *idle_trigger_ = new Trigger<>();
Trigger<std::string> intent_progress_trigger_;
Trigger<> wake_word_detected_trigger_;
Trigger<std::string> stt_end_trigger_;
Trigger<std::string> tts_end_trigger_;
Trigger<std::string> tts_start_trigger_;
Trigger<std::string, std::string> error_trigger_;
Trigger<> idle_trigger_;
Trigger<> *client_connected_trigger_ = new Trigger<>();
Trigger<> *client_disconnected_trigger_ = new Trigger<>();
Trigger<> client_connected_trigger_;
Trigger<> client_disconnected_trigger_;
api::APIConnection *api_client_{nullptr};
std::unordered_map<std::string, Timer> timers_;
void timer_tick_();
Trigger<Timer> *timer_started_trigger_ = new Trigger<Timer>();
Trigger<Timer> *timer_finished_trigger_ = new Trigger<Timer>();
Trigger<Timer> *timer_updated_trigger_ = new Trigger<Timer>();
Trigger<Timer> *timer_cancelled_trigger_ = new Trigger<Timer>();
Trigger<std::vector<Timer>> *timer_tick_trigger_ = new Trigger<std::vector<Timer>>();
Trigger<Timer> timer_started_trigger_;
Trigger<Timer> timer_finished_trigger_;
Trigger<Timer> timer_updated_trigger_;
Trigger<Timer> timer_cancelled_trigger_;
Trigger<std::vector<Timer>> timer_tick_trigger_;
bool has_timers_{false};
bool timer_tick_running_{false};