ESPHome 2026.8.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
22template<typename... Ts> class OpenThreadComponentPollPeriodAction;
23
24class OpenThreadComponent final : public Component {
25 public:
28 void dump_config() override;
29 void setup() override;
30 bool teardown() override;
31 float get_setup_priority() const override { return setup_priority::WIFI; }
32
33 bool is_connected() const { return this->connected_; }
35 bool is_lock_initialized() const { return this->lock_initialized_; }
37 std::optional<otIp6Address> get_omr_address();
38 void ot_main();
39 void on_factory_reset(std::function<void()> callback);
41
44 const char *get_use_address() const { return this->use_address_; }
45 void set_use_address(const char *use_address) { this->use_address_ = use_address; }
46#if CONFIG_OPENTHREAD_MTD
47 void set_poll_period(uint32_t poll_period) { this->poll_period_ = poll_period; }
48 uint32_t get_poll_period() const { return this->poll_period_; }
49#endif
50 void set_output_power(int8_t output_power) { this->output_power_ = output_power; }
51 void set_connected(bool connected) { this->connected_ = connected; }
52 static void on_state_changed(otChangedFlags flags, void *context);
53
54 protected:
55 // Actions re-apply link mode under the OT lock; allow them to call apply_linkmode_()
56 // without exposing this lock-sensitive, raw-instance method on the public API.
57 template<typename... Ts> friend class OpenThreadComponentPollPeriodAction;
58
63 void apply_linkmode_(otInstance *instance);
64
65 std::optional<otIp6Address> get_omr_address_(InstanceLock &lock);
66 otInstance *get_openthread_instance_();
67 int openthread_stop_();
68 std::function<void()> factory_reset_external_callback_;
69#if CONFIG_OPENTHREAD_MTD
71#endif
72 std::optional<int8_t> output_power_{};
73 std::atomic<bool> lock_initialized_{false};
74 bool teardown_started_{false};
75 bool teardown_complete_{false};
76 bool connected_{false};
77
78 private:
79 // Stores a pointer to a string literal (static storage duration).
80 // ONLY set from Python-generated code with string literals - never dynamic strings.
81 const char *use_address_{nullptr};
82};
83
84extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
85
86class OpenThreadSrpComponent final : public Component {
87 public:
89 // This has to run after the mdns component or else no services are available to advertise
90 float get_setup_priority() const override { return this->mdns_->get_setup_priority() - 1.0f; }
91 void setup() override;
92 static void srp_callback(otError err, const otSrpClientHostInfo *host_info, const otSrpClientService *services,
93 const otSrpClientService *removed_services, void *context);
94 static void srp_start_callback(const otSockAddr *server_socket_address, void *context);
95 static void srp_factory_reset_callback(otError err, const otSrpClientHostInfo *host_info,
96 const otSrpClientService *services, const otSrpClientService *removed_services,
97 void *context);
98
99 protected:
101 std::vector<std::unique_ptr<uint8_t[]>> memory_pool_;
102 void *pool_alloc_(size_t size);
103};
104
105// RAII guard for the OpenThread API lock. Modeled on std::unique_lock: the
106// guard may or may not own the lock (try_acquire can fail), so check it with
107// operator bool before use. Non-copyable and non-movable: the factories return
108// by value via guaranteed copy elision, so a guard is never duplicated and the
109// lock is released exactly once, when the owning guard goes out of scope.
111 public:
112 // May fail to acquire within delay ms; check the returned guard with operator bool.
113 static InstanceLock try_acquire(int delay);
114 // Blocks until the lock is held.
115 static InstanceLock acquire();
116 InstanceLock(const InstanceLock &) = delete;
121
122 explicit operator bool() const { return this->owns_; }
123
124 // Returns the global openthread instance. Only valid on an owning guard
125 // (operator bool is true); the instance must not be used without the lock held.
126 otInstance *get_instance();
127
128 private:
129 explicit InstanceLock(bool owns) : owns_(owns) {}
130 bool owns_;
131};
132
133} // namespace esphome::openthread
134#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:47
void set_use_address(const char *use_address)
Definition openthread.h:45
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:72
std::function< void()> factory_reset_external_callback_
Definition openthread.h:68
void set_output_power(int8_t output_power)
Definition openthread.h:50
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:35
std::optional< otIp6Address > get_omr_address()
float get_setup_priority() const override
Definition openthread.h:31
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:44
Action to set single poll period parameter.
Definition openthread.h:22
std::vector< std::unique_ptr< uint8_t[]> > memory_pool_
Definition openthread.h:101
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:90
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:100
uint16_t flags
std::array< IPAddress, 5 > IPAddresses
Definition ip_address.h:299
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