Listener StaticVector Migration: WiFi and Logger
WiFi and Logger components now use StaticVector for listener storage, eliminating heap allocation and STL overhead. External components that register listeners must now call request functions during code generation.
This is a breaking change for external components in ESPHome 2026.1.0 and later.
What changed
Section titled “What changed”Previously, listener vectors were dynamically allocated with std::vector. Now they use compile-time-sized StaticVector based on how many components request listener slots.
If the appropriate request_*_listener() is not called, add_*_listener() will silently fail - your listener will never receive callbacks.
WiFi Listeners
Section titled “WiFi Listeners”Four independent listener types now require separate request functions:
# In your component's __init__.pyfrom esphome.components import wifi
async def to_code(config): # Request the specific listener type(s) you need wifi.request_wifi_ip_state_listener() # For IP/DNS state changes wifi.request_wifi_connect_state_listener() # For SSID/BSSID changes wifi.request_wifi_scan_results_listener() # For scan results wifi.request_wifi_power_save_listener() # For power save mode changesWiFi Listener C++ Registration
Section titled “WiFi Listener C++ Registration”These use interface classes, not lambdas:
// Your component implements the listener interfaceclass MyComponent : public Component, public wifi::WiFiIPStateListener { public: void setup() override { wifi::global_wifi_component->add_ip_state_listener(this); } void on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, const network::IPAddress &dns2) override { // Handle IP state change }};Available listener interfaces:
| Interface | Method Signature |
|---|---|
WiFiIPStateListener | on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, const network::IPAddress &dns2) |
WiFiConnectStateListener | on_wifi_connect_state(StringRef ssid, std::span<const uint8_t, 6> bssid) |
WiFiScanResultsListener | on_wifi_scan_results(const wifi_scan_vector_t<WiFiScanResult> &results) |
WiFiPowerSaveListener | on_wifi_power_save(WiFiPowerSaveMode mode) |
Logger Listeners
Section titled “Logger Listeners”Components implementing LogListener must request a listener slot:
# In your component's __init__.pyfrom esphome.components.logger import request_log_listener
async def to_code(config): request_log_listener() # ... rest of code generationLogger Listener C++ Registration
Section titled “Logger Listener C++ Registration”class MyComponent : public Component, public logger::LogListener { public: void setup() override { if (logger::global_logger != nullptr) logger::global_logger->add_log_listener(this); } void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override { // Handle log message }};Compilation
Section titled “Compilation”External components will compile successfully but listeners will silently fail if the request function is not called. There is no compile-time error - the listener simply won’t receive callbacks.
Finding code that needs updates
Section titled “Finding code that needs updates”# Find WiFi listener registrationsgrep -rn "add_ip_state_listener\|add_connect_state_listener" your_component/grep -rn "add_scan_results_listener\|add_power_save_listener" your_component/
# Find log listener registrationsgrep -rn "add_log_listener" your_component/Why this change
Section titled “Why this change”- Flash savings: 1,048 bytes on ESP8266 (WiFi), 268 bytes (Logger)
- Unused code elimination: Only requested listener types are compiled
- Exact sizing: StaticVectors sized precisely for actual component count
- No heap fragmentation: Compile-time allocation instead of runtime
Reference Pull Requests
Section titled “Reference Pull Requests”- esphome/esphome#13197 - WiFi Listeners
- esphome/esphome#13196 - Logger Listeners
Questions?
Section titled “Questions?”If you have questions about migrating your external component, please ask in:
- ESPHome Discord - #devs channel
- ESPHome GitHub Discussions
Copyright © 2026 ESPHome - A project from the Open Home Foundation
Comments
Feel free to leave a comment here to discuss this post with others. You can ask questions, share your experience, or suggest improvements. If you have a question about a specific feature or issue, please consider using the ESPHome Discord. Stick to English and follow ESPHome's code of conduct. These comments exist on a discussion on GitHub, so you can also comment there directly if you prefer.