ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
provisioning.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_PROVISIONING
8
9#include <cstdint>
10
11namespace esphome::provisioning {
12
13// Central provisioning-window manager (EN18031). A device that ships unprovisioned
14// (secure transports enabled with no credentials, configured by the controller on
15// first connection) opens a provisioning window at boot. Each transport that needs
16// provisioning registers as a "source" and reports its state; the device is
17// considered provisioned once every registered source is provisioned.
18//
19// Network connectivity is a built-in source: a device with a network interface but
20// no other provisioning-capable component (no api encryption, etc.) is still
21// considered provisioned once it has connected via any interface -- so an
22// Improv-only device reports its state correctly.
23//
24// If the window times out while still unprovisioned it closes: the closed state is
25// RAM-only (a power cycle / reset reopens it) and the `on_timeout` automation fires.
26// Components query window_pending()/closed() to suppress reboot timeouts and refuse
27// further provisioning. This manager owns no transport knowledge; transports
28// (api, and later mqtt/wireguard/...) drive it through the source API.
30 public:
31 // Maximum number of provisioning sources, limited by the width of the state masks.
32 static constexpr uint8_t MAX_SOURCES = 32;
33
35
36 void loop() override;
37 void dump_config() override;
38 float get_setup_priority() const override { return setup_priority::BEFORE_CONNECTION; }
39
40 void set_timeout(uint32_t timeout) { this->timeout_ = timeout; }
41
42 // Register a provisioning source. Returns a bit index the source uses to report
43 // its state via set_source_provisioned(). Call once, from the source's setup().
44 uint8_t register_source();
45 // Report whether the given source currently holds valid credentials.
46 void set_source_provisioned(uint8_t source, bool provisioned) {
47 if (source >= MAX_SOURCES)
48 return;
49 if (provisioned) {
50 this->provisioned_mask_ |= (1UL << source);
51 } else {
52 this->provisioned_mask_ &= ~(1UL << source);
53 }
54 }
55
56 // True once every registered source is provisioned. Config validation guarantees
57 // at least one source, and the built-in connectivity source registers in the
58 // constructor, so registered_mask_ is never zero in practice.
59 bool is_provisioned() const { return (this->provisioned_mask_ & this->registered_mask_) == this->registered_mask_; }
60 // True while provisioning is still pending: the device is unprovisioned, whether
61 // the window is still open or has already closed. Reboot timeouts are suppressed
62 // while this holds so the device never auto-reboots (and silently reopens the
63 // window) while unprovisioned.
64 bool window_pending() const { return !this->is_provisioned(); }
65 // True once the window has expired without the device being provisioned.
66 bool closed() const { return this->closed_; }
67
68 // Register a callback fired once when the window closes (runtime expiry). Used
69 // internally by transports/Improv to stop accepting provisioning. The user-facing
70 // on_timeout automation is wired to get_timeout_trigger() instead.
71 template<typename F> void add_on_closed_callback(F &&callback) {
72 this->closed_callback_.add(std::forward<F>(callback));
73 }
75
76 protected:
77 void close_window_();
78
84 uint8_t source_count_{0};
85 bool closed_{false};
86#ifdef USE_NETWORK
87 // Built-in connectivity source (see loop()): registered in the constructor and
88 // latched provisioned once the device has connected via any network interface.
89 uint8_t network_source_{0};
90#endif
91};
92
93extern ProvisioningManager *global_provisioning_manager; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
94
95} // namespace esphome::provisioning
96#endif // USE_PROVISIONING
LazyCallbackManager< void()> closed_callback_
void set_source_provisioned(uint8_t source, bool provisioned)
ProvisioningManager * global_provisioning_manager
constexpr float BEFORE_CONNECTION
For components that should be initialized after WiFi and before API is connected.
Definition component.h:53
static void uint32_t