ESPHome 2025.6.1
Loading...
Searching...
No Matches
openthread_esp.cpp
Go to the documentation of this file.
2#if defined(USE_OPENTHREAD) && defined(USE_ESP_IDF)
3#include <openthread/logging.h>
4#include "openthread.h"
5
6#include "esp_log.h"
7#include "esp_openthread.h"
8#include "esp_openthread_lock.h"
9
10#include "esp_task_wdt.h"
12#include "esphome/core/log.h"
13
14#include "esp_err.h"
15#include "esp_event.h"
16#include "esp_netif.h"
17#include "esp_netif_types.h"
18#include "esp_openthread_cli.h"
19#include "esp_openthread_netif_glue.h"
20#include "esp_vfs_eventfd.h"
21#include "freertos/FreeRTOS.h"
22#include "freertos/task.h"
23#include "nvs_flash.h"
24
25static const char *const TAG = "openthread";
26
27namespace esphome {
28namespace openthread {
29
31 ESP_LOGCONFIG(TAG, "Running setup");
32 // Used eventfds:
33 // * netif
34 // * ot task queue
35 // * radio driver
36 esp_vfs_eventfd_config_t eventfd_config = {
37 .max_fds = 3,
38 };
39 ESP_ERROR_CHECK(nvs_flash_init());
40 ESP_ERROR_CHECK(esp_event_loop_create_default());
41 ESP_ERROR_CHECK(esp_netif_init());
42 ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
43
44 xTaskCreate(
45 [](void *arg) {
46 static_cast<OpenThreadComponent *>(arg)->ot_main();
47 vTaskDelete(nullptr);
48 },
49 "ot_main", 10240, this, 5, nullptr);
50}
51
52static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) {
53 esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
54 esp_netif_t *netif = esp_netif_new(&cfg);
55 assert(netif != nullptr);
56 ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config)));
57
58 return netif;
59}
60
62 esp_openthread_platform_config_t config = {
63 .radio_config =
64 {
65 .radio_mode = RADIO_MODE_NATIVE,
66 .radio_uart_config = {},
67 },
68 .host_config =
69 {
70 // There is a conflict between esphome's logger which also
71 // claims the usb serial jtag device.
72 // .host_connection_mode = HOST_CONNECTION_MODE_CLI_USB,
73 // .host_usb_config = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(),
74 },
75 .port_config =
76 {
77 .storage_partition_name = "nvs",
78 .netif_queue_size = 10,
79 .task_queue_size = 10,
80 },
81 };
82
83 // Initialize the OpenThread stack
84 // otLoggingSetLevel(OT_LOG_LEVEL_DEBG);
85 ESP_ERROR_CHECK(esp_openthread_init(&config));
86
87#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE
88 ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance()));
89#endif
90
91#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC
92 // The OpenThread log level directly matches ESP log level
93 (void) otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL);
94#endif
95 // Initialize the OpenThread cli
96#if CONFIG_OPENTHREAD_CLI
97 esp_openthread_cli_init();
98#endif
99
100 esp_netif_t *openthread_netif;
101 // Initialize the esp_netif bindings
102 openthread_netif = init_openthread_netif(&config);
103 esp_netif_set_default_netif(openthread_netif);
104
105#if CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
106 esp_cli_custom_command_init();
107#endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION
108
109 // Run the main loop
110#if CONFIG_OPENTHREAD_CLI
111 esp_openthread_cli_create_task();
112#endif
113 ESP_LOGI(TAG, "Activating dataset...");
114 otOperationalDatasetTlvs dataset;
115
116#ifdef CONFIG_OPENTHREAD_FORCE_DATASET
117 ESP_ERROR_CHECK(esp_openthread_auto_start(NULL));
118#else
119 otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset);
120 ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL));
121#endif
122 esp_openthread_launch_mainloop();
123
124 // Clean up
125 esp_openthread_netif_glue_deinit();
126 esp_netif_destroy(openthread_netif);
127
128 esp_vfs_eventfd_unregister();
129}
130
132 network::IPAddresses addresses;
133 struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
134 uint8_t count = 0;
135 esp_netif_t *netif = esp_netif_get_default_netif();
136 count = esp_netif_get_all_ip6(netif, if_ip6s);
137 assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES);
138 for (int i = 0; i < count; i++) {
139 addresses[i + 1] = network::IPAddress(&if_ip6s[i]);
140 }
141 return addresses;
142}
143
144std::optional<InstanceLock> InstanceLock::try_acquire(int delay) {
145 if (esp_openthread_lock_acquire(delay)) {
146 return InstanceLock();
147 }
148 return {};
149}
150
152 while (!esp_openthread_lock_acquire(100)) {
153 esp_task_wdt_reset();
154 }
155 return InstanceLock();
156}
157
158otInstance *InstanceLock::get_instance() { return esp_openthread_get_instance(); }
159
160InstanceLock::~InstanceLock() { esp_openthread_lock_release(); }
161
162} // namespace openthread
163} // namespace esphome
164#endif
static std::optional< InstanceLock > try_acquire(int delay)
std::array< IPAddress, 5 > IPAddresses
Definition ip_address.h:143
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:29