1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-11 14:23:47 +01:00

Openthread code updates (#9047)

This commit is contained in:
Jesse Hills
2025-06-11 22:41:38 +12:00
committed by GitHub
parent 052f558131
commit c3c3a27af2
6 changed files with 90 additions and 103 deletions

View File

@@ -8,7 +8,6 @@ from esphome.components.esp32 import (
from esphome.components.mdns import MDNSComponent
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID
from esphome.core import CORE
import esphome.final_validate as fv
from .const import (
@@ -140,7 +139,6 @@ async def to_code(config):
await cg.register_component(ot, config)
srp = cg.new_Pvariable(config[CONF_SRP_ID])
cg.add(srp.set_host_name(cg.RawExpression(f'"{CORE.name}"')))
mdns_component = await cg.get_variable(config[CONF_MDNS_ID])
cg.add(srp.set_mdns(mdns_component))
await cg.register_component(srp, config)

View File

@@ -14,15 +14,17 @@
#include <cstring>
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#define TAG "openthread"
static const char *const TAG = "openthread";
namespace esphome {
namespace openthread {
OpenThreadComponent *global_openthread_component = nullptr;
OpenThreadComponent *global_openthread_component = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
OpenThreadComponent::OpenThreadComponent() { global_openthread_component = this; }
@@ -58,63 +60,67 @@ bool OpenThreadComponent::is_connected() {
// Gets the off-mesh routable address
std::optional<otIp6Address> OpenThreadComponent::get_omr_address() {
auto lock = InstanceLock::acquire();
InstanceLock lock = InstanceLock::acquire();
return this->get_omr_address_(lock);
}
std::optional<otIp6Address> OpenThreadComponent::get_omr_address_(std::optional<InstanceLock> &lock) {
std::optional<otIp6Address> OpenThreadComponent::get_omr_address_(InstanceLock &lock) {
otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
otInstance *instance = nullptr;
instance = lock->get_instance();
instance = lock.get_instance();
otBorderRouterConfig aConfig;
if (otNetDataGetNextOnMeshPrefix(instance, &iterator, &aConfig) != OT_ERROR_NONE) {
otBorderRouterConfig config;
if (otNetDataGetNextOnMeshPrefix(instance, &iterator, &config) != OT_ERROR_NONE) {
return std::nullopt;
}
const otIp6Prefix *omrPrefix = &aConfig.mPrefix;
const otNetifAddress *unicastAddrs = otIp6GetUnicastAddresses(instance);
for (const otNetifAddress *addr = unicastAddrs; addr; addr = addr->mNext) {
const otIp6Address *localIp = &addr->mAddress;
if (otIp6PrefixMatch(&omrPrefix->mPrefix, localIp)) {
return *localIp;
const otIp6Prefix *omr_prefix = &config.mPrefix;
const otNetifAddress *unicast_addresses = otIp6GetUnicastAddresses(instance);
for (const otNetifAddress *addr = unicast_addresses; addr; addr = addr->mNext) {
const otIp6Address *local_ip = &addr->mAddress;
if (otIp6PrefixMatch(&omr_prefix->mPrefix, local_ip)) {
return *local_ip;
}
}
return {};
}
void srpCallback(otError aError, const otSrpClientHostInfo *aHostInfo, const otSrpClientService *aServices,
const otSrpClientService *aRemovedServices, void *aContext) {
if (aError != 0) {
ESP_LOGW(TAG, "SRP client reported an error: %s", otThreadErrorToString(aError));
for (const otSrpClientHostInfo *host = aHostInfo; host; host = nullptr) {
void srp_callback(otError err, const otSrpClientHostInfo *host_info, const otSrpClientService *services,
const otSrpClientService *removed_services, void *context) {
if (err != 0) {
ESP_LOGW(TAG, "SRP client reported an error: %s", otThreadErrorToString(err));
for (const otSrpClientHostInfo *host = host_info; host; host = nullptr) {
ESP_LOGW(TAG, " Host: %s", host->mName);
}
for (const otSrpClientService *service = aServices; service; service = service->mNext) {
for (const otSrpClientService *service = services; service; service = service->mNext) {
ESP_LOGW(TAG, " Service: %s", service->mName);
}
}
}
void srpStartCallback(const otSockAddr *aServerSockAddr, void *aContext) { ESP_LOGI(TAG, "SRP client has started"); }
void srp_start_callback(const otSockAddr *server_socket_address, void *context) {
ESP_LOGI(TAG, "SRP client has started");
}
void OpenThreadSrpComponent::setup() {
otError error;
auto lock = InstanceLock::acquire();
otInstance *instance = lock->get_instance();
InstanceLock lock = InstanceLock::acquire();
otInstance *instance = lock.get_instance();
otSrpClientSetCallback(instance, srpCallback, nullptr);
otSrpClientSetCallback(instance, srp_callback, nullptr);
// set the host name
uint16_t size;
char *existing_host_name = otSrpClientBuffersGetHostNameString(instance, &size);
uint16_t len = this->host_name_.size();
if (len > size) {
const std::string &host_name = App.get_name();
uint16_t host_name_len = host_name.size();
if (host_name_len > size) {
ESP_LOGW(TAG, "Hostname is too long, choose a shorter project name");
return;
}
memcpy(existing_host_name, this->host_name_.c_str(), len + 1);
memset(existing_host_name, 0, size);
memcpy(existing_host_name, host_name.c_str(), host_name_len);
error = otSrpClientSetHostName(instance, existing_host_name);
if (error != 0) {
@@ -150,27 +156,28 @@ void OpenThreadSrpComponent::setup() {
// Set instance name (using host_name)
string = otSrpClientBuffersGetServiceEntryInstanceNameString(entry, &size);
if (this->host_name_.size() > size) {
ESP_LOGW(TAG, "Instance name too long: %s", this->host_name_.c_str());
if (host_name_len > size) {
ESP_LOGW(TAG, "Instance name too long: %s", host_name.c_str());
continue;
}
memcpy(string, this->host_name_.c_str(), this->host_name_.size() + 1);
memset(string, 0, size);
memcpy(string, host_name.c_str(), host_name_len);
// Set port
entry->mService.mPort = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
otDnsTxtEntry *mTxtEntries =
otDnsTxtEntry *txt_entries =
reinterpret_cast<otDnsTxtEntry *>(this->pool_alloc_(sizeof(otDnsTxtEntry) * service.txt_records.size()));
// Set TXT records
entry->mService.mNumTxtEntries = service.txt_records.size();
for (size_t i = 0; i < service.txt_records.size(); i++) {
const auto &txt = service.txt_records[i];
auto value = const_cast<TemplatableValue<std::string> &>(txt.value).value();
mTxtEntries[i].mKey = txt.key.c_str();
mTxtEntries[i].mValue = reinterpret_cast<const uint8_t *>(value.c_str());
mTxtEntries[i].mValueLength = value.size();
txt_entries[i].mKey = strdup(txt.key.c_str());
txt_entries[i].mValue = reinterpret_cast<const uint8_t *>(strdup(value.c_str()));
txt_entries[i].mValueLength = value.size();
}
entry->mService.mTxtEntries = mTxtEntries;
entry->mService.mTxtEntries = txt_entries;
entry->mService.mNumTxtEntries = service.txt_records.size();
// Add service
@@ -181,8 +188,8 @@ void OpenThreadSrpComponent::setup() {
ESP_LOGW(TAG, "Added service: %s", full_service.c_str());
}
otSrpClientEnableAutoStartMode(instance, srpStartCallback, nullptr);
ESP_LOGW(TAG, "Finished SRP setup **** ");
otSrpClientEnableAutoStartMode(instance, srp_start_callback, nullptr);
ESP_LOGW(TAG, "Finished SRP setup");
}
void *OpenThreadSrpComponent::pool_alloc_(size_t size) {
@@ -191,8 +198,6 @@ void *OpenThreadSrpComponent::pool_alloc_(size_t size) {
return ptr;
}
void OpenThreadSrpComponent::set_host_name(std::string host_name) { this->host_name_ = host_name; }
void OpenThreadSrpComponent::set_mdns(esphome::mdns::MDNSComponent *mdns) { this->mdns_ = mdns; }
} // namespace openthread

View File

@@ -2,14 +2,14 @@
#include "esphome/core/defines.h"
#ifdef USE_OPENTHREAD
#include "esphome/core/component.h"
#include "esphome/components/mdns/mdns_component.h"
#include "esphome/components/network/ip_address.h"
#include "esphome/core/component.h"
#include <openthread/thread.h>
#include <vector>
#include <optional>
#include <vector>
namespace esphome {
namespace openthread {
@@ -29,23 +29,19 @@ class OpenThreadComponent : public Component {
void ot_main();
protected:
std::optional<otIp6Address> get_omr_address_(std::optional<InstanceLock> &lock);
std::optional<otIp6Address> get_omr_address_(InstanceLock &lock);
};
extern OpenThreadComponent *global_openthread_component;
extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
class OpenThreadSrpComponent : public Component {
public:
void set_mdns(esphome::mdns::MDNSComponent *mdns);
void set_host_name(std::string host_name);
// This has to run after the mdns component or else no services are available to advertise
float get_setup_priority() const override { return this->mdns_->get_setup_priority() - 1.0; }
protected:
void setup() override;
private:
std::string host_name_;
protected:
esphome::mdns::MDNSComponent *mdns_{nullptr};
std::vector<esphome::mdns::MDNSService> mdns_services_;
std::vector<std::unique_ptr<uint8_t[]>> memory_pool_;
@@ -55,7 +51,7 @@ class OpenThreadSrpComponent : public Component {
class InstanceLock {
public:
static std::optional<InstanceLock> try_acquire(int delay);
static std::optional<InstanceLock> acquire();
static InstanceLock acquire();
~InstanceLock();
// Returns the global openthread instance guarded by this lock

View File

@@ -1,34 +1,34 @@
#include "esphome/core/defines.h"
#if defined(USE_OPENTHREAD) && defined(USE_ESP_IDF)
#include "openthread.h"
#include <openthread/logging.h>
#include "openthread.h"
#include "esp_log.h"
#include "esp_openthread.h"
#include "esp_openthread_lock.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esp_task_wdt.h"
#include "esp_openthread_cli.h"
#include "esp_openthread_netif_glue.h"
#include "esp_err.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "esp_vfs_eventfd.h"
#include "esp_netif.h"
#include "esp_netif_types.h"
#include "esp_err.h"
#include "esp_openthread_cli.h"
#include "esp_openthread_netif_glue.h"
#include "esp_vfs_eventfd.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#define TAG "openthread"
static const char *const TAG = "openthread";
namespace esphome {
namespace openthread {
void OpenThreadComponent::setup() {
ESP_LOGI(TAG, "Setting up OpenThread...");
ESP_LOGCONFIG(TAG, "Running setup");
// Used eventfds:
// * netif
// * ot task queue
@@ -47,8 +47,6 @@ void OpenThreadComponent::setup() {
vTaskDelete(nullptr);
},
"ot_main", 10240, this, 5, nullptr);
ESP_LOGI(TAG, "OpenThread started");
}
static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) {
@@ -150,7 +148,7 @@ std::optional<InstanceLock> InstanceLock::try_acquire(int delay) {
return {};
}
std::optional<InstanceLock> InstanceLock::acquire() {
InstanceLock InstanceLock::acquire() {
while (!esp_openthread_lock_acquire(100)) {
esp_task_wdt_reset();
}