ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
ota_backend.cpp
Go to the documentation of this file.
1#include "ota_backend.h"
2
3namespace esphome::ota {
4
5bool version_is_older(const char *candidate, const char *reference) {
6 if (candidate == nullptr || reference == nullptr)
7 return false;
8 while (true) {
9 uint32_t a = 0;
10 while (*candidate >= '0' && *candidate <= '9') {
11 a = a * 10 + static_cast<uint32_t>(*candidate - '0');
12 candidate++;
13 }
14 uint32_t b = 0;
15 while (*reference >= '0' && *reference <= '9') {
16 b = b * 10 + static_cast<uint32_t>(*reference - '0');
17 reference++;
18 }
19 if (a != b)
20 return a < b;
21 // Components equal so far; advance past a single separator on each side.
22 const bool a_more = (*candidate == '.');
23 const bool b_more = (*reference == '.');
24 if (a_more)
25 candidate++;
26 if (b_more)
27 reference++;
28 if (!a_more && !b_more)
29 return false; // Both strings exhausted with all components equal.
30 }
31}
32
33#ifdef USE_OTA_STATE_LISTENER
34OTAGlobalCallback *global_ota_callback{nullptr}; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
35
37 if (global_ota_callback == nullptr) {
38 global_ota_callback = new OTAGlobalCallback(); // NOLINT(cppcoreguidelines-owning-memory)
39 }
41}
42
43void OTAComponent::notify_state_deferred_(OTAState state, float progress, uint8_t error) {
44 // Pack state, error, and progress into a single uint32_t so the lambda
45 // captures only [this, packed] (8 bytes) — fits in std::function SBO.
46 // Layout: [state:8][error:8][progress_fixed:16] where progress is 0–10000 (0.01% resolution)
47 static_assert(OTA_ERROR <= 0xFF, "OTAState must fit in 8 bits for packing");
48 uint32_t packed = (static_cast<uint32_t>(state) << 24) | (static_cast<uint32_t>(error) << 16) |
49 static_cast<uint16_t>(progress * 100.0f);
50 this->defer([this, packed]() {
51 this->notify_state_(static_cast<OTAState>(packed >> 24), static_cast<float>(packed & 0xFFFF) / 100.0f,
52 static_cast<uint8_t>(packed >> 16));
53 });
54}
55
56void OTAComponent::notify_state_(OTAState state, float progress, uint8_t error) {
57 for (auto *listener : this->state_listeners_) {
58 listener->on_ota_state(state, progress, error);
59 }
60 get_global_ota_callback()->notify_ota_state(state, progress, error, this);
61}
62#endif
63
64} // namespace esphome::ota
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
void notify_state_deferred_(OTAState state, float progress, uint8_t error)
Notify state with deferral to main loop (for thread safety).
std::vector< OTAStateListener * > state_listeners_
void notify_state_(OTAState state, float progress, uint8_t error)
Global callback that aggregates OTA state from all OTA components.
void notify_ota_state(OTAState state, float progress, uint8_t error, OTAComponent *component)
bool state
Definition fan.h:2
bool version_is_older(const char *candidate, const char *reference)
Compare two dotted-numeric version strings (such as "1.2.3").
OTAGlobalCallback * get_global_ota_callback()
OTAGlobalCallback * global_ota_callback
static void uint32_t