ESPHome 2026.10.0-dev
Loading...
Searching...
No Matches
openthread.h
Go to the documentation of this file.
1#pragma once
3#ifdef USE_OPENTHREAD
4
8
9#include <openthread/srp_client.h>
10#include <openthread/srp_client_buffers.h>
11#include <openthread/instance.h>
12#include <openthread/thread.h>
13
14#include <atomic>
15#include <optional>
16#include <vector>
17
18namespace esphome::openthread {
19
20class InstanceLock;
21
27
28template<typename... Ts> class OpenThreadComponentPollPeriodAction;
29
30class OpenThreadComponent final : public Component {
31 public:
34 void dump_config() override;
35 void setup() override;
36 bool teardown() override;
37 float get_setup_priority() const override { return setup_priority::WIFI; }
38
39 bool is_connected() const { return this->connected_; }
41 bool is_lock_initialized() const { return this->lock_initialized_; }
43 std::optional<otIp6Address> get_omr_address();
44 void ot_main();
45 void on_factory_reset(std::function<void()> callback);
47
50 const char *get_use_address() const { return this->use_address_; }
51 void set_use_address(const char *use_address) { this->use_address_ = use_address; }
52#if CONFIG_OPENTHREAD_MTD
53 void set_poll_period(uint32_t poll_period) { this->poll_period_ = poll_period; }
54 uint32_t get_poll_period() const { return this->poll_period_; }
55#endif
56 void set_output_power(int8_t output_power) { this->output_power_ = output_power; }
57 void set_connected(bool connected) { this->connected_ = connected; }
58 static void on_state_changed(otChangedFlags flags, void *context);
59
60 protected:
61 // Actions re-apply link mode under the OT lock; allow them to call apply_linkmode_()
62 // without exposing this lock-sensitive, raw-instance method on the public API.
63 template<typename... Ts> friend class OpenThreadComponentPollPeriodAction;
64
69 void apply_linkmode_(otInstance *instance);
70
71 std::optional<otIp6Address> get_omr_address_(InstanceLock &lock);
72 otInstance *get_openthread_instance_();
73 int openthread_stop_();
74 std::function<void()> factory_reset_external_callback_;
75#if CONFIG_OPENTHREAD_MTD
77#endif
78 std::optional<int8_t> output_power_{};
79 std::atomic<bool> lock_initialized_{false};
81 std::atomic<bool> connected_{false};
82
83 private:
84 // Stores a pointer to a string literal (static storage duration).
85 // ONLY set from Python-generated code with string literals - never dynamic strings.
86 const char *use_address_{nullptr};
87};
88
89extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
90
91class OpenThreadSrpComponent final : public Component {
92 public:
94 // This has to run after the mdns component or else no services are available to advertise
95 float get_setup_priority() const override { return this->mdns_->get_setup_priority() - 1.0f; }
96 void setup() override;
97 static void srp_callback(otError err, const otSrpClientHostInfo *host_info, const otSrpClientService *services,
98 const otSrpClientService *removed_services, void *context);
99 static void srp_start_callback(const otSockAddr *server_socket_address, void *context);
100 static void srp_factory_reset_callback(otError err, const otSrpClientHostInfo *host_info,
101 const otSrpClientService *services, const otSrpClientService *removed_services,
102 void *context);
103
104 protected:
106 std::vector<std::unique_ptr<uint8_t[]>> memory_pool_;
107 void *pool_alloc_(size_t size);
108};
109
110// RAII guard for the OpenThread API lock. Modeled on std::unique_lock: the
111// guard may or may not own the lock (try_acquire can fail), so check it with
112// operator bool before use. Non-copyable and non-movable: the factories return
113// by value via guaranteed copy elision, so a guard is never duplicated and the
114// lock is released exactly once, when the owning guard goes out of scope.
116 public:
117 // May fail to acquire within delay ms; check the returned guard with operator bool.
118 static InstanceLock try_acquire(int delay);
119 // Blocks until the lock is held.
120 static InstanceLock acquire();
121 InstanceLock(const InstanceLock &) = delete;
126
127 explicit operator bool() const { return this->owns_; }
128
129 // Returns the global openthread instance. Only valid on an owning guard
130 // (operator bool is true); the instance must not be used without the lock held.
131 otInstance *get_instance();
132
133 private:
134 explicit InstanceLock(bool owns) : owns_(owns) {}
135 bool owns_;
136};
137
138} // namespace esphome::openthread
139#endif
float get_setup_priority() const override
static InstanceLock try_acquire(int delay)
InstanceLock & operator=(const InstanceLock &)=delete
InstanceLock(InstanceLock &&)=delete
InstanceLock(const InstanceLock &)=delete
InstanceLock & operator=(InstanceLock &&)=delete
void set_poll_period(uint32_t poll_period)
Definition openthread.h:53
void set_use_address(const char *use_address)
Definition openthread.h:51
std::optional< otIp6Address > get_omr_address_(InstanceLock &lock)
void apply_linkmode_(otInstance *instance)
Apply Link Mode settings (incl poll period).
std::optional< int8_t > output_power_
Definition openthread.h:78
std::function< void()> factory_reset_external_callback_
Definition openthread.h:74
void set_output_power(int8_t output_power)
Definition openthread.h:56
std::atomic< TeardownStage > teardown_stage_
Definition openthread.h:80
static void on_state_changed(otChangedFlags flags, void *context)
bool is_lock_initialized() const
Returns true once esp_openthread_init() has completed and the OT lock is usable.
Definition openthread.h:41
std::optional< otIp6Address > get_omr_address()
float get_setup_priority() const override
Definition openthread.h:37
void on_factory_reset(std::function< void()> callback)
const char * get_use_address() const
Returns nullptr when no explicit use_address is configured and the address is derived at runtime from...
Definition openthread.h:50
Action to set single poll period parameter.
Definition openthread.h:28
std::vector< std::unique_ptr< uint8_t[]> > memory_pool_
Definition openthread.h:106
static void srp_start_callback(const otSockAddr *server_socket_address, void *context)
void set_mdns(esphome::mdns::MDNSComponent *mdns)
static void srp_factory_reset_callback(otError err, const otSrpClientHostInfo *host_info, const otSrpClientService *services, const otSrpClientService *removed_services, void *context)
float get_setup_priority() const override
Definition openthread.h:95
static void srp_callback(otError err, const otSrpClientHostInfo *host_info, const otSrpClientService *services, const otSrpClientService *removed_services, void *context)
esphome::mdns::MDNSComponent * mdns_
Definition openthread.h:105
uint16_t flags
std::array< IPAddress, 5 > IPAddresses
Definition ip_address.h:301
OpenThreadComponent * global_openthread_component
constexpr float WIFI
Definition component.h:50
uint16_t size
Definition helpers.cpp:25
void HOT delay(uint32_t ms)
Definition hal.cpp:85
static void uint32_t
SemaphoreHandle_t lock