From a1c4d5626857d8eecb656b8d588de99759090356 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 18:37:13 -1000 Subject: [PATCH] [alarm_control_panel] Reduce heap allocations in arm/disarm methods (#13358) --- .../alarm_control_panel.cpp | 55 ++++++------------- .../alarm_control_panel/alarm_control_panel.h | 30 ++++++++-- .../alarm_control_panel_call.cpp | 6 +- .../alarm_control_panel_call.h | 3 +- .../alarm_control_panel/automation.h | 30 +--------- 5 files changed, 49 insertions(+), 75 deletions(-) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index 248b5065ad..ab0a780cef 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -67,52 +67,29 @@ void AlarmControlPanel::add_on_ready_callback(std::function &&callback) this->ready_callback_.add(std::move(callback)); } -void AlarmControlPanel::arm_away(optional code) { +void AlarmControlPanel::arm_with_code_(AlarmControlPanelCall &(AlarmControlPanelCall::*arm_method)(), + const char *code) { auto call = this->make_call(); - call.arm_away(); - if (code.has_value()) - call.set_code(code.value()); + (call.*arm_method)(); + if (code != nullptr) + call.set_code(code); call.perform(); } -void AlarmControlPanel::arm_home(optional code) { - auto call = this->make_call(); - call.arm_home(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); +void AlarmControlPanel::arm_away(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::arm_away, code); } + +void AlarmControlPanel::arm_home(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::arm_home, code); } + +void AlarmControlPanel::arm_night(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::arm_night, code); } + +void AlarmControlPanel::arm_vacation(const char *code) { + this->arm_with_code_(&AlarmControlPanelCall::arm_vacation, code); } -void AlarmControlPanel::arm_night(optional code) { - auto call = this->make_call(); - call.arm_night(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); +void AlarmControlPanel::arm_custom_bypass(const char *code) { + this->arm_with_code_(&AlarmControlPanelCall::arm_custom_bypass, code); } -void AlarmControlPanel::arm_vacation(optional code) { - auto call = this->make_call(); - call.arm_vacation(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); -} - -void AlarmControlPanel::arm_custom_bypass(optional code) { - auto call = this->make_call(); - call.arm_custom_bypass(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); -} - -void AlarmControlPanel::disarm(optional code) { - auto call = this->make_call(); - call.disarm(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); -} +void AlarmControlPanel::disarm(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::disarm, code); } } // namespace esphome::alarm_control_panel diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.h b/esphome/components/alarm_control_panel/alarm_control_panel.h index 340f15bcd6..e8dc197e26 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel.h @@ -76,37 +76,53 @@ class AlarmControlPanel : public EntityBase { * * @param code The code */ - void arm_away(optional code = nullopt); + void arm_away(const char *code = nullptr); + void arm_away(const optional &code) { + this->arm_away(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in home mode * * @param code The code */ - void arm_home(optional code = nullopt); + void arm_home(const char *code = nullptr); + void arm_home(const optional &code) { + this->arm_home(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in night mode * * @param code The code */ - void arm_night(optional code = nullopt); + void arm_night(const char *code = nullptr); + void arm_night(const optional &code) { + this->arm_night(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in vacation mode * * @param code The code */ - void arm_vacation(optional code = nullopt); + void arm_vacation(const char *code = nullptr); + void arm_vacation(const optional &code) { + this->arm_vacation(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in custom bypass mode * * @param code The code */ - void arm_custom_bypass(optional code = nullopt); + void arm_custom_bypass(const char *code = nullptr); + void arm_custom_bypass(const optional &code) { + this->arm_custom_bypass(code.has_value() ? code.value().c_str() : nullptr); + } /** disarm the alarm * * @param code The code */ - void disarm(optional code = nullopt); + void disarm(const char *code = nullptr); + void disarm(const optional &code) { this->disarm(code.has_value() ? code.value().c_str() : nullptr); } /** Get the state * @@ -118,6 +134,8 @@ class AlarmControlPanel : public EntityBase { protected: friend AlarmControlPanelCall; + // Helper to reduce code duplication for arm/disarm methods + void arm_with_code_(AlarmControlPanelCall &(AlarmControlPanelCall::*arm_method)(), const char *code); // in order to store last panel state in flash ESPPreferenceObject pref_; // current state diff --git a/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp b/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp index 5e98d58368..ba58ee3904 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp @@ -10,8 +10,10 @@ static const char *const TAG = "alarm_control_panel"; AlarmControlPanelCall::AlarmControlPanelCall(AlarmControlPanel *parent) : parent_(parent) {} -AlarmControlPanelCall &AlarmControlPanelCall::set_code(const std::string &code) { - this->code_ = code; +AlarmControlPanelCall &AlarmControlPanelCall::set_code(const char *code) { + if (code != nullptr) { + this->code_ = std::string(code); + } return *this; } diff --git a/esphome/components/alarm_control_panel/alarm_control_panel_call.h b/esphome/components/alarm_control_panel/alarm_control_panel_call.h index cff00900dd..58764ea166 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel_call.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel_call.h @@ -14,7 +14,8 @@ class AlarmControlPanelCall { public: AlarmControlPanelCall(AlarmControlPanel *parent); - AlarmControlPanelCall &set_code(const std::string &code); + AlarmControlPanelCall &set_code(const char *code); + AlarmControlPanelCall &set_code(const std::string &code) { return this->set_code(code.c_str()); } AlarmControlPanelCall &arm_away(); AlarmControlPanelCall &arm_home(); AlarmControlPanelCall &arm_night(); diff --git a/esphome/components/alarm_control_panel/automation.h b/esphome/components/alarm_control_panel/automation.h index ce5ceadb47..4ff34de0d5 100644 --- a/esphome/components/alarm_control_panel/automation.h +++ b/esphome/components/alarm_control_panel/automation.h @@ -66,15 +66,7 @@ template class ArmAwayAction : public Action { TEMPLATABLE_VALUE(std::string, code) - void play(const Ts &...x) override { - auto call = this->alarm_control_panel_->make_call(); - auto code = this->code_.optional_value(x...); - if (code.has_value()) { - call.set_code(code.value()); - } - call.arm_away(); - call.perform(); - } + void play(const Ts &...x) override { this->alarm_control_panel_->arm_away(this->code_.optional_value(x...)); } protected: AlarmControlPanel *alarm_control_panel_; @@ -86,15 +78,7 @@ template class ArmHomeAction : public Action { TEMPLATABLE_VALUE(std::string, code) - void play(const Ts &...x) override { - auto call = this->alarm_control_panel_->make_call(); - auto code = this->code_.optional_value(x...); - if (code.has_value()) { - call.set_code(code.value()); - } - call.arm_home(); - call.perform(); - } + void play(const Ts &...x) override { this->alarm_control_panel_->arm_home(this->code_.optional_value(x...)); } protected: AlarmControlPanel *alarm_control_panel_; @@ -106,15 +90,7 @@ template class ArmNightAction : public Action { TEMPLATABLE_VALUE(std::string, code) - void play(const Ts &...x) override { - auto call = this->alarm_control_panel_->make_call(); - auto code = this->code_.optional_value(x...); - if (code.has_value()) { - call.set_code(code.value()); - } - call.arm_night(); - call.perform(); - } + void play(const Ts &...x) override { this->alarm_control_panel_->arm_night(this->code_.optional_value(x...)); } protected: AlarmControlPanel *alarm_control_panel_;