[ota] Replace std::function callbacks with listener interface - #12167
Conversation
|
To use the changes from this PR as an external component, add the following to your ESPHome configuration YAML file: external_components:
- source: github://pr#12167
components: [esp32_ble_tracker, esphome, http_request, micro_wake_word, ota, speaker, web_server]
refresh: 1h(Added by the PR bot) |
|
👋 Hi there! This PR modifies 13 file(s) with codeowners. @oarcher, @jesserockz, @kahrendt, @synesthesiam - As codeowner(s) of the affected files, your review would be appreciated! 🙏 Note: Automatic review request may have failed, but you're still welcome to review. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #12167 +/- ##
=======================================
Coverage 72.66% 72.66%
=======================================
Files 53 53
Lines 11193 11193
Branches 1517 1517
=======================================
Hits 8133 8133
Misses 2667 2667
Partials 393 393 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR refactors the OTA component to replace std::function callbacks with listener interfaces, following the pattern established in PR #12155 for WiFi. This change reduces memory footprint (16+ bytes per callback down to 4 bytes per pointer) and improves performance through more efficient virtual function dispatch.
Key Changes:
- Introduces
OTAStateListenerandOTAGlobalStateListenerinterfaces for per-component and global OTA state notifications - Replaces
CallbackManagerwithstd::vector<OTAStateListener*>inOTAComponent - Updates all OTA triggers to implement
OTAStateListenerdirectly instead of using lambdas - Adds
notify_state_()andnotify_state_deferred_()methods for thread-safe notifications
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| esphome/core/defines.h | Renames USE_OTA_STATE_CALLBACK to USE_OTA_STATE_LISTENER |
| esphome/components/ota/ota_backend.h | Introduces listener interfaces and updates OTA component API |
| esphome/components/ota/ota_backend.cpp | Implements bridge pattern for global listeners |
| esphome/components/ota/automation.h | Converts all OTA triggers to implement OTAStateListener |
| esphome/components/ota/init.py | Adds request_ota_state_listeners() for on-demand feature compilation |
| esphome/components/http_request/update/* | Updates to use listener interface |
| esphome/components/http_request/ota/* | Updates to use notify_state_() |
| esphome/components/esphome/ota/* | Updates to use notify_state_() |
| esphome/components/web_server/ota/* | Updates to use notify_state_deferred_() for thread safety |
| esphome/components/speaker/media_player/init.py | Updates to use request_ota_state_listeners() |
| esphome/components/micro_wake_word/init.py | Updates to use request_ota_state_listeners() |
| esphome/components/esp32_ble_tracker/init.py | Updates to use request_ota_state_listeners() |
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
|
esp32_ble_tracker disconnect still works fine |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
Memory Impact AnalysisComponents:
This analysis runs automatically when components change. Memory usage is measured from a merged configuration with 7 components. |
|
web server ota callbacks with defer ok as well |
# Conflicts: # esphome/components/esphome/ota/ota_esphome.cpp
|
👋 Hi there! This PR modifies 20 file(s) with codeowners. @esphome/core - As codeowner(s) of the affected files, your review would be appreciated! 🙏 Note: Automatic review request may have failed, but you're still welcome to review. |
|
Thanks |
What does this implement/fix?
Refactors the OTA component to use listener interfaces instead of
std::functioncallbacks, following the pattern established in #12155 for WiFi.Changes
Memory and Performance Benefits
std::function<void(OTAState, 8000 float, uint8_t)>(16+ bytes each) withOTAStateListener*pointers (4 bytes each)std::functionindirection (~6+ cycles)std::functiontemplate instantiation overhead from firmwareArchitecture
New Listener Interface:
OTA Component Changes:
OTAComponentnow maintainsstd::vector<OTAStateListener*>instead ofCallbackManageradd_state_listener(OTAStateListener*)for registering listenersnotify_state_()for notifications (also notifies global listeners automatically)notify_state_deferred_()for thread-safe notifications from separate tasksTrigger Updates:
OTAStartTrigger,OTAEndTrigger,OTAProgressTrigger, etc.) now implementOTAStateListenerinterface directlyOTAStateTrigger<OTAState State>to reduce code duplicationGlobal Listener Updates:
esp32_ble_tracker,micro_wake_word, andspeaker_media_playernow implementOTAGlobalStateListenerinterface instead of using lambda callbacks#ifdef USE_OTA_STATE_LISTENERConsumer Updates:
HttpRequestUpdatenow implementsOTAStateListenerinstead of using lambda callbackesphomeandhttp_requestOTA usenotify_state_()web_serverOTA usesnotify_state_deferred_()for thread safetyPython Changes
USE_OTA_STATE_CALLBACKtoUSE_OTA_STATE_LISTENERrequest_ota_state_listeners()function for components to request the featureota.request_ota_state_listeners()instead of addingcg.add_define("USE_OTA_STATE_LISTENER")directly - this is more future-proof as it allows the OTA component to manage the feature enablementTypes of changes
Related issue or feature (if applicable):
Pull request in esphome-docs with documentation (if applicable):
Test Environment
Example entry for
config.yaml:Checklist:
tests/folder).If user exposed functionality or configuration variables are added/changed:
Migration Guide for External Components
If you have an external component that uses the OTA state callback API:
Before:
After:
For global OTA state (listening to any OTA platform):
Before:
After:
Python code generation: