From 7a0d7c5ca141ea40ffeb638cceb627196f901fc8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 5 Jan 2026 09:24:33 -1000 Subject: [PATCH 1/2] [voice_assistant] Reduce heap allocation with stack-based timer formatting --- esphome/components/voice_assistant/voice_assistant.cpp | 3 ++- esphome/components/voice_assistant/voice_assistant.h | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index de683113bb..05c356ae4c 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -866,11 +866,12 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse .is_active = msg.is_active, }; this->timers_[timer.id] = timer; + char timer_buf[Timer::TO_STR_BUFFER_SIZE]; ESP_LOGD(TAG, "Timer Event\n" " Type: %" PRId32 "\n" " %s", - msg.event_type, timer.to_string().c_str()); + msg.event_type, timer.to_str(timer_buf)); switch (msg.event_type) { case api::enums::VOICE_ASSISTANT_TIMER_STARTED: diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 8d3d3497ec..7b0c9072ba 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -23,6 +23,7 @@ #endif #include "esphome/components/socket/socket.h" +#include #include #include @@ -76,6 +77,15 @@ struct Timer { this->id.c_str(), this->name.c_str(), this->total_seconds, this->seconds_left, YESNO(this->is_active)); } + /// Buffer size for to_str() - sufficient for typical timer names + static constexpr size_t TO_STR_BUFFER_SIZE = 128; + /// Format to buffer, returns pointer to buffer (may truncate long names) + const char *to_str(std::span buffer) const { + snprintf(buffer.data(), buffer.size(), + "Timer(id=%s, name=%s, total_seconds=%" PRIu32 ", seconds_left=%" PRIu32 ", is_active=%s)", + this->id.c_str(), this->name.c_str(), this->total_seconds, this->seconds_left, YESNO(this->is_active)); + return buffer.data(); + } }; struct WakeWord { From cc8bd2d29d4ed84fcb52c2efa9df0dda06a34907 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 5 Jan 2026 09:26:41 -1000 Subject: [PATCH 2/2] dry --- esphome/components/voice_assistant/voice_assistant.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 7b0c9072ba..b1b3df7bbd 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -72,11 +72,6 @@ struct Timer { uint32_t seconds_left; bool is_active; - std::string to_string() const { - return str_sprintf("Timer(id=%s, name=%s, total_seconds=%" PRIu32 ", seconds_left=%" PRIu32 ", is_active=%s)", - this->id.c_str(), this->name.c_str(), this->total_seconds, this->seconds_left, - YESNO(this->is_active)); - } /// Buffer size for to_str() - sufficient for typical timer names static constexpr size_t TO_STR_BUFFER_SIZE = 128; /// Format to buffer, returns pointer to buffer (may truncate long names) @@ -86,6 +81,10 @@ struct Timer { this->id.c_str(), this->name.c_str(), this->total_seconds, this->seconds_left, YESNO(this->is_active)); return buffer.data(); } + std::string to_string() const { + char buffer[TO_STR_BUFFER_SIZE]; + return this->to_str(buffer); + } }; struct WakeWord {