diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 494470cb48..29d33bfc76 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -378,14 +378,19 @@ async def to_code(config): # Track if any network uses Enterprise authentication has_eap = False - def add_sta(ap, network): - ip_config = network.get(CONF_MANUAL_IP, config.get(CONF_MANUAL_IP)) - cg.add(var.add_sta(wifi_network(network, ap, ip_config))) + # Initialize FixedVector with the count of networks + networks = config.get(CONF_NETWORKS, []) + if networks: + cg.add(var.init_sta(len(networks))) - for network in config.get(CONF_NETWORKS, []): - if CONF_EAP in network: - has_eap = True - cg.with_local_variable(network[CONF_ID], WiFiAP(), add_sta, network) + def add_sta(ap: cg.MockObj, network: dict) -> None: + ip_config = network.get(CONF_MANUAL_IP, config.get(CONF_MANUAL_IP)) + cg.add(var.add_sta(wifi_network(network, ap, ip_config))) + + for network in networks: + if CONF_EAP in network: + has_eap = True + cg.with_local_variable(network[CONF_ID], WiFiAP(), add_sta, network) if CONF_AP in config: conf = config[CONF_AP] diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index c89384d742..b278e5a386 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -330,9 +330,11 @@ float WiFiComponent::get_loop_priority() const { return 10.0f; // before other loop components } +void WiFiComponent::init_sta(size_t count) { this->sta_.init(count); } void WiFiComponent::add_sta(const WiFiAP &ap) { this->sta_.push_back(ap); } void WiFiComponent::set_sta(const WiFiAP &ap) { this->clear_sta(); + this->init_sta(1); this->add_sta(ap); } void WiFiComponent::clear_sta() { this->sta_.clear(); } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 10aa82a065..42f78dbfac 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -219,6 +219,7 @@ class WiFiComponent : public Component { void set_sta(const WiFiAP &ap); WiFiAP get_sta() { return this->selected_ap_; } + void init_sta(size_t count); void add_sta(const WiFiAP &ap); void clear_sta(); @@ -393,7 +394,7 @@ class WiFiComponent : public Component { #endif std::string use_address_; - std::vector sta_; + FixedVector sta_; std::vector sta_priorities_; wifi_scan_vector_t scan_result_; WiFiAP selected_ap_; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 234d2a7d7d..9b0591c9c5 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -194,12 +194,8 @@ template class FixedVector { size_ = 0; } - public: - FixedVector() = default; - - /// Constructor from initializer list - allocates exact size needed - /// This enables brace initialization: FixedVector v = {1, 2, 3}; - FixedVector(std::initializer_list init_list) { + // Helper to assign from initializer list (shared by constructor and assignment operator) + void assign_from_initializer_list_(std::initializer_list init_list) { init(init_list.size()); size_t idx = 0; for (const auto &item : init_list) { @@ -209,6 +205,13 @@ template class FixedVector { size_ = init_list.size(); } + public: + FixedVector() = default; + + /// Constructor from initializer list - allocates exact size needed + /// This enables brace initialization: FixedVector v = {1, 2, 3}; + FixedVector(std::initializer_list init_list) { assign_from_initializer_list_(init_list); } + ~FixedVector() { cleanup_(); } // Disable copy operations (avoid accidental expensive copies) @@ -234,6 +237,15 @@ template class FixedVector { return *this; } + /// Assignment from initializer list - avoids temporary and move overhead + /// This enables: FixedVector v; v = {1, 2, 3}; + FixedVector &operator=(std::initializer_list init_list) { + cleanup_(); + reset_(); + assign_from_initializer_list_(init_list); + return *this; + } + // Allocate capacity - can be called multiple times to reinit void init(size_t n) { cleanup_();