mirror of
https://github.com/esphome/esphome.git
synced 2026-05-28 13:37:24 +08:00
[voice_assistant] Replace timer unordered_map with vector to eliminate per-tick heap allocation (#13857)
This commit is contained in:
@@ -371,7 +371,12 @@ async def to_code(config):
|
|||||||
if on_timer_tick := config.get(CONF_ON_TIMER_TICK):
|
if on_timer_tick := config.get(CONF_ON_TIMER_TICK):
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
var.get_timer_tick_trigger(),
|
var.get_timer_tick_trigger(),
|
||||||
[(cg.std_vector.template(Timer), "timers")],
|
[
|
||||||
|
(
|
||||||
|
cg.std_vector.template(Timer).operator("const").operator("ref"),
|
||||||
|
"timers",
|
||||||
|
)
|
||||||
|
],
|
||||||
on_timer_tick,
|
on_timer_tick,
|
||||||
)
|
)
|
||||||
has_timers = True
|
has_timers = True
|
||||||
|
|||||||
@@ -859,35 +859,43 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse &msg) {
|
void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse &msg) {
|
||||||
Timer timer = {
|
// Find existing timer or add a new one
|
||||||
.id = msg.timer_id,
|
auto it = this->timers_.begin();
|
||||||
.name = msg.name,
|
for (; it != this->timers_.end(); ++it) {
|
||||||
.total_seconds = msg.total_seconds,
|
if (it->id == msg.timer_id)
|
||||||
.seconds_left = msg.seconds_left,
|
break;
|
||||||
.is_active = msg.is_active,
|
}
|
||||||
};
|
if (it == this->timers_.end()) {
|
||||||
this->timers_[timer.id] = timer;
|
this->timers_.push_back({});
|
||||||
|
it = this->timers_.end() - 1;
|
||||||
|
}
|
||||||
|
it->id = msg.timer_id;
|
||||||
|
it->name = msg.name;
|
||||||
|
it->total_seconds = msg.total_seconds;
|
||||||
|
it->seconds_left = msg.seconds_left;
|
||||||
|
it->is_active = msg.is_active;
|
||||||
|
|
||||||
char timer_buf[Timer::TO_STR_BUFFER_SIZE];
|
char timer_buf[Timer::TO_STR_BUFFER_SIZE];
|
||||||
ESP_LOGD(TAG,
|
ESP_LOGD(TAG,
|
||||||
"Timer Event\n"
|
"Timer Event\n"
|
||||||
" Type: %" PRId32 "\n"
|
" Type: %" PRId32 "\n"
|
||||||
" %s",
|
" %s",
|
||||||
msg.event_type, timer.to_str(timer_buf));
|
msg.event_type, it->to_str(timer_buf));
|
||||||
|
|
||||||
switch (msg.event_type) {
|
switch (msg.event_type) {
|
||||||
case api::enums::VOICE_ASSISTANT_TIMER_STARTED:
|
case api::enums::VOICE_ASSISTANT_TIMER_STARTED:
|
||||||
this->timer_started_trigger_.trigger(timer);
|
this->timer_started_trigger_.trigger(*it);
|
||||||
break;
|
break;
|
||||||
case api::enums::VOICE_ASSISTANT_TIMER_UPDATED:
|
case api::enums::VOICE_ASSISTANT_TIMER_UPDATED:
|
||||||
this->timer_updated_trigger_.trigger(timer);
|
this->timer_updated_trigger_.trigger(*it);
|
||||||
break;
|
break;
|
||||||
case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED:
|
case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED:
|
||||||
this->timer_cancelled_trigger_.trigger(timer);
|
this->timer_cancelled_trigger_.trigger(*it);
|
||||||
this->timers_.erase(timer.id);
|
this->timers_.erase(it);
|
||||||
break;
|
break;
|
||||||
case api::enums::VOICE_ASSISTANT_TIMER_FINISHED:
|
case api::enums::VOICE_ASSISTANT_TIMER_FINISHED:
|
||||||
this->timer_finished_trigger_.trigger(timer);
|
this->timer_finished_trigger_.trigger(*it);
|
||||||
this->timers_.erase(timer.id);
|
this->timers_.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,16 +909,12 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VoiceAssistant::timer_tick_() {
|
void VoiceAssistant::timer_tick_() {
|
||||||
std::vector<Timer> res;
|
for (auto &timer : this->timers_) {
|
||||||
res.reserve(this->timers_.size());
|
|
||||||
for (auto &pair : this->timers_) {
|
|
||||||
auto &timer = pair.second;
|
|
||||||
if (timer.is_active && timer.seconds_left > 0) {
|
if (timer.is_active && timer.seconds_left > 0) {
|
||||||
timer.seconds_left--;
|
timer.seconds_left--;
|
||||||
}
|
}
|
||||||
res.push_back(timer);
|
|
||||||
}
|
}
|
||||||
this->timer_tick_trigger_.trigger(res);
|
this->timer_tick_trigger_.trigger(this->timers_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) {
|
void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) {
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "esphome/components/socket/socket.h"
|
#include "esphome/components/socket/socket.h"
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
@@ -226,9 +225,9 @@ class VoiceAssistant : public Component {
|
|||||||
Trigger<Timer> *get_timer_updated_trigger() { return &this->timer_updated_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_cancelled_trigger() { return &this->timer_cancelled_trigger_; }
|
||||||
Trigger<Timer> *get_timer_finished_trigger() { return &this->timer_finished_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_; }
|
Trigger<const std::vector<Timer> &> *get_timer_tick_trigger() { return &this->timer_tick_trigger_; }
|
||||||
void set_has_timers(bool has_timers) { this->has_timers_ = has_timers; }
|
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_; }
|
const std::vector<Timer> &get_timers() const { return this->timers_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool allocate_buffers_();
|
bool allocate_buffers_();
|
||||||
@@ -267,13 +266,13 @@ class VoiceAssistant : public Component {
|
|||||||
|
|
||||||
api::APIConnection *api_client_{nullptr};
|
api::APIConnection *api_client_{nullptr};
|
||||||
|
|
||||||
std::unordered_map<std::string, Timer> timers_;
|
std::vector<Timer> timers_;
|
||||||
void timer_tick_();
|
void timer_tick_();
|
||||||
Trigger<Timer> timer_started_trigger_;
|
Trigger<Timer> timer_started_trigger_;
|
||||||
Trigger<Timer> timer_finished_trigger_;
|
Trigger<Timer> timer_finished_trigger_;
|
||||||
Trigger<Timer> timer_updated_trigger_;
|
Trigger<Timer> timer_updated_trigger_;
|
||||||
Trigger<Timer> timer_cancelled_trigger_;
|
Trigger<Timer> timer_cancelled_trigger_;
|
||||||
Trigger<std::vector<Timer>> timer_tick_trigger_;
|
Trigger<const std::vector<Timer> &> timer_tick_trigger_;
|
||||||
bool has_timers_{false};
|
bool has_timers_{false};
|
||||||
bool timer_tick_running_{false};
|
bool timer_tick_running_{false};
|
||||||
|
|
||||||
|
|||||||
@@ -68,3 +68,24 @@ voice_assistant:
|
|||||||
- logger.log:
|
- logger.log:
|
||||||
format: "Voice assistant error - code %s, message: %s"
|
format: "Voice assistant error - code %s, message: %s"
|
||||||
args: [code.c_str(), message.c_str()]
|
args: [code.c_str(), message.c_str()]
|
||||||
|
on_timer_started:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer started: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_updated:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer updated: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_cancelled:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer cancelled: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_finished:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer finished: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_tick:
|
||||||
|
- lambda: |-
|
||||||
|
for (auto &timer : timers) {
|
||||||
|
ESP_LOGD("timer", "Timer %s: %" PRIu32 "s left", timer.name.c_str(), timer.seconds_left);
|
||||||
|
}
|
||||||
|
|||||||
@@ -58,3 +58,24 @@ voice_assistant:
|
|||||||
- logger.log:
|
- logger.log:
|
||||||
format: "Voice assistant error - code %s, message: %s"
|
format: "Voice assistant error - code %s, message: %s"
|
||||||
args: [code.c_str(), message.c_str()]
|
args: [code.c_str(), message.c_str()]
|
||||||
|
on_timer_started:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer started: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_updated:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer updated: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_cancelled:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer cancelled: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_finished:
|
||||||
|
- logger.log:
|
||||||
|
format: "Timer finished: %s"
|
||||||
|
args: [timer.id.c_str()]
|
||||||
|
on_timer_tick:
|
||||||
|
- lambda: |-
|
||||||
|
for (auto &timer : timers) {
|
||||||
|
ESP_LOGD("timer", "Timer %s: %" PRIu32 "s left", timer.name.c_str(), timer.seconds_left);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user