openthread: cleanup

This commit is contained in:
Mathieu Rene 2024-10-20 16:31:30 -04:00
parent 2519f87cd8
commit cdea089a9b
4 changed files with 51 additions and 47 deletions

View file

@ -1,4 +1,5 @@
#include "esphome/core/defines.h" #include "esphome/core/defines.h"
#ifdef USE_OPENTHREAD #ifdef USE_OPENTHREAD
#include "openthread.h" #include "openthread.h"
@ -27,7 +28,7 @@ OpenThreadComponent *global_openthread_component = nullptr;
OpenThreadComponent::OpenThreadComponent() { global_openthread_component = this; } OpenThreadComponent::OpenThreadComponent() { global_openthread_component = this; }
OpenThreadComponent::~OpenThreadComponent() { OpenThreadComponent::~OpenThreadComponent() {
auto lock = OpenThreadLockGuard::try_acquire(100); auto lock = InstanceLock::try_acquire(100);
if (!lock) { if (!lock) {
ESP_LOGW(TAG, "Failed to acquire OpenThread lock in destructor, leaking memory"); ESP_LOGW(TAG, "Failed to acquire OpenThread lock in destructor, leaking memory");
return; return;
@ -35,12 +36,11 @@ OpenThreadComponent::~OpenThreadComponent() {
otInstance *instance = lock->get_instance(); otInstance *instance = lock->get_instance();
otSrpClientClearHostAndServices(instance); otSrpClientClearHostAndServices(instance);
otSrpClientBuffersFreeAllServices(instance); otSrpClientBuffersFreeAllServices(instance);
global_openthread_component = nullptr; global_openthread_component = nullptr;
} }
bool OpenThreadComponent::is_connected() { bool OpenThreadComponent::is_connected() {
auto lock = OpenThreadLockGuard::try_acquire(100); auto lock = InstanceLock::try_acquire(100);
if (!lock) { if (!lock) {
ESP_LOGW(TAG, "Failed to acquire OpenThread lock in is_connected"); ESP_LOGW(TAG, "Failed to acquire OpenThread lock in is_connected");
return false; return false;
@ -59,26 +59,21 @@ bool OpenThreadComponent::is_connected() {
// Gets the off-mesh routable address // Gets the off-mesh routable address
std::optional<otIp6Address> OpenThreadComponent::get_omr_address() { std::optional<otIp6Address> OpenThreadComponent::get_omr_address() {
auto lock = OpenThreadLockGuard::acquire(); auto lock = InstanceLock::acquire();
return this->get_omr_address_(lock); return this->get_omr_address_(lock);
} }
std::optional<otIp6Address> OpenThreadComponent::get_omr_address_(std::optional<OpenThreadLockGuard> &lock) { std::optional<otIp6Address> OpenThreadComponent::get_omr_address_(std::optional<InstanceLock> &lock) {
otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
otInstance *instance = nullptr; otInstance *instance = nullptr;
instance = lock->get_instance(); instance = lock->get_instance();
otBorderRouterConfig aConfig; otBorderRouterConfig aConfig;
while (otNetDataGetNextOnMeshPrefix(instance, &iterator, &aConfig) != OT_ERROR_NONE) { if (otNetDataGetNextOnMeshPrefix(instance, &iterator, &aConfig) != OT_ERROR_NONE) {
lock.reset(); return std::nullopt;
vTaskDelay(100);
lock = OpenThreadLockGuard::try_acquire(portMAX_DELAY);
if (!lock) {
ESP_LOGW(TAG, "Could not re-acquire lock");
return {};
} }
};
const otIp6Prefix *omrPrefix = &aConfig.mPrefix; const otIp6Prefix *omrPrefix = &aConfig.mPrefix;
const otNetifAddress *unicastAddrs = otIp6GetUnicastAddresses(instance); const otNetifAddress *unicastAddrs = otIp6GetUnicastAddresses(instance);
for (const otNetifAddress *addr = unicastAddrs; addr; addr = addr->mNext) { for (const otNetifAddress *addr = unicastAddrs; addr; addr = addr->mNext) {
@ -87,15 +82,26 @@ std::optional<otIp6Address> OpenThreadComponent::get_omr_address_(std::optional<
return *localIp; return *localIp;
} }
} }
ESP_LOGW(TAG, "Could not find the OMR address");
return {}; return {};
} }
void srpCallback(otError aError, const otSrpClientHostInfo *aHostInfo, const otSrpClientService *aServices,
const otSrpClientService *aRemovedServices, void *aContext) {
ESP_LOGW(TAG, "*** SRP callback *** error=%d hostInfo=%p services=%p removedServices=%p", aError, aHostInfo,
aServices, aRemovedServices);
}
void srpStartCallback(const otSockAddr *aServerSockAddr, void *aContext) {
ESP_LOGW(TAG, "*** SRP start callback ***");
}
void OpenThreadComponent::srp_setup_() { void OpenThreadComponent::srp_setup_() {
otError error; otError error;
auto lock = OpenThreadLockGuard::acquire(); auto lock = InstanceLock::acquire();
otInstance *instance = lock->get_instance(); otInstance *instance = lock->get_instance();
otSrpClientSetCallback(instance, srpCallback, nullptr);
// set the host name // set the host name
uint16_t size; uint16_t size;
char *existing_host_name = otSrpClientBuffersGetHostNameString(instance, &size); char *existing_host_name = otSrpClientBuffersGetHostNameString(instance, &size);
@ -168,7 +174,8 @@ void OpenThreadComponent::srp_setup_() {
} }
} }
otSrpClientEnableAutoStartMode(instance, nullptr, nullptr); otSrpClientEnableAutoStartMode(instance, srpStartCallback, nullptr);
ESP_LOGW(TAG, "Finished SRP setup **** ");
} }
void *OpenThreadComponent::pool_alloc_(size_t size) { void *OpenThreadComponent::pool_alloc_(size_t size) {

View file

@ -14,7 +14,7 @@
namespace esphome { namespace esphome {
namespace openthread { namespace openthread {
class OpenThreadLockGuard; class InstanceLock;
class OpenThreadComponent : public Component { class OpenThreadComponent : public Component {
public: public:
@ -32,13 +32,11 @@ class OpenThreadComponent : public Component {
protected: protected:
void srp_setup_(); void srp_setup_();
std::optional<otIp6Address> get_omr_address_(std::optional<OpenThreadLockGuard> &lock); std::optional<otIp6Address> get_omr_address_(std::optional<InstanceLock> &lock);
std::string host_name_; std::string host_name_;
void *pool_alloc_(size_t size); void *pool_alloc_(size_t size);
private: private:
// void platform_init();
esphome::mdns::MDNSComponent *mdns_{nullptr}; esphome::mdns::MDNSComponent *mdns_{nullptr};
std::vector<esphome::mdns::MDNSService> mdns_services_; std::vector<esphome::mdns::MDNSService> mdns_services_;
std::vector<std::unique_ptr<uint8_t[]>> memory_pool_; std::vector<std::unique_ptr<uint8_t[]>> memory_pool_;
@ -46,11 +44,11 @@ class OpenThreadComponent : public Component {
extern OpenThreadComponent *global_openthread_component; extern OpenThreadComponent *global_openthread_component;
class OpenThreadLockGuard { class InstanceLock {
public: public:
static std::optional<OpenThreadLockGuard> try_acquire(int delay); static std::optional<InstanceLock> try_acquire(int delay);
static std::optional<OpenThreadLockGuard> acquire(); static std::optional<InstanceLock> acquire();
~OpenThreadLockGuard(); ~InstanceLock();
// Returns the global openthread instance guarded by this lock // Returns the global openthread instance guarded by this lock
otInstance *get_instance(); otInstance *get_instance();
@ -58,7 +56,7 @@ class OpenThreadLockGuard {
private: private:
// Use a private constructor in order to force thehandling // Use a private constructor in order to force thehandling
// of acquisition failure // of acquisition failure
OpenThreadLockGuard() {} InstanceLock() {}
}; };
} // namespace openthread } // namespace openthread

View file

@ -48,12 +48,12 @@ void OpenThreadComponent::setup() {
}, },
"ot_main", 10240, this, 5, nullptr); "ot_main", 10240, this, 5, nullptr);
xTaskCreate( // xTaskCreate(
[](void *arg) { // [](void *arg) {
static_cast<OpenThreadComponent *>(arg)->srp_setup_(); // static_cast<OpenThreadComponent *>(arg)->srp_setup_();
vTaskDelete(nullptr); // vTaskDelete(nullptr);
}, // },
"ot_srp_setup", 10240, this, 5, nullptr); // "ot_srp_setup", 10240, this, 5, nullptr);
ESP_LOGI(TAG, "OpenThread started"); ESP_LOGI(TAG, "OpenThread started");
} }
@ -92,6 +92,8 @@ void OpenThreadComponent::ot_main() {
// Initialize the OpenThread stack // Initialize the OpenThread stack
ESP_ERROR_CHECK(esp_openthread_init(&config)); ESP_ERROR_CHECK(esp_openthread_init(&config));
this->srp_setup_();
#if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE #if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE
ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance()));
#endif #endif
@ -132,9 +134,6 @@ void OpenThreadComponent::ot_main() {
esp_vfs_eventfd_unregister(); esp_vfs_eventfd_unregister();
} }
// TODO: This gets used by mqtt in order to register the device's IP. Likely it doesn't
// make sense to return thread-local addresses, since they can't be reached from outside the thread network.
// It could make more sense to return the off-mesh-routable address instead.
network::IPAddresses OpenThreadComponent::get_ip_addresses() { network::IPAddresses OpenThreadComponent::get_ip_addresses() {
network::IPAddresses addresses; network::IPAddresses addresses;
struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
@ -148,23 +147,23 @@ network::IPAddresses OpenThreadComponent::get_ip_addresses() {
return addresses; return addresses;
} }
std::optional<OpenThreadLockGuard> OpenThreadLockGuard::try_acquire(int delay) { std::optional<InstanceLock> InstanceLock::try_acquire(int delay) {
if (esp_openthread_lock_acquire(delay)) { if (esp_openthread_lock_acquire(delay)) {
return OpenThreadLockGuard(); return InstanceLock();
} }
return {}; return {};
} }
std::optional<OpenThreadLockGuard> OpenThreadLockGuard::acquire() { std::optional<InstanceLock> InstanceLock::acquire() {
while (!esp_openthread_lock_acquire(100)) { while (!esp_openthread_lock_acquire(100)) {
esp_task_wdt_reset(); esp_task_wdt_reset();
} }
return OpenThreadLockGuard(); return InstanceLock();
} }
otInstance *OpenThreadLockGuard::get_instance() { return esp_openthread_get_instance(); } otInstance *InstanceLock::get_instance() { return esp_openthread_get_instance(); }
OpenThreadLockGuard::~OpenThreadLockGuard() { esp_openthread_lock_release(); } InstanceLock::~InstanceLock() { esp_openthread_lock_release(); }
} // namespace openthread } // namespace openthread
} // namespace esphome } // namespace esphome

View file

@ -8,12 +8,12 @@
namespace esphome { namespace esphome {
namespace openthread_info { namespace openthread_info {
using esphome::openthread::OpenThreadLockGuard; using esphome::openthread::InstanceLock;
class OpenThreadInstancePollingComponent : public PollingComponent { class OpenThreadInstancePollingComponent : public PollingComponent {
public: public:
void update() override { void update() override {
auto lock = OpenThreadLockGuard::try_acquire(100); auto lock = InstanceLock::try_acquire(10);
if (!lock) { if (!lock) {
return; return;
} }
@ -93,7 +93,7 @@ class ExtAddrOpenThreadInfo : public OpenThreadInstancePollingComponent, public
auto extaddr = otLinkGetExtendedAddress(instance); auto extaddr = otLinkGetExtendedAddress(instance);
if (!std::equal(this->last_extaddr_.begin(), this->last_extaddr_.end(), extaddr->m8)) { if (!std::equal(this->last_extaddr_.begin(), this->last_extaddr_.end(), extaddr->m8)) {
std::copy(extaddr->m8, extaddr->m8 + 8, this->last_extaddr_.begin()); std::copy(extaddr->m8, extaddr->m8 + 8, this->last_extaddr_.begin());
this->publish_state(format_hex_pretty(extaddr->m8, 8)); this->publish_state(format_hex(extaddr->m8, 8));
} }
} }
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
@ -112,7 +112,7 @@ class Eui64OpenThreadInfo : public OpenThreadInstancePollingComponent, public te
if (!std::equal(this->last_eui64_.begin(), this->last_eui64_.end(), addr.m8)) { if (!std::equal(this->last_eui64_.begin(), this->last_eui64_.end(), addr.m8)) {
std::copy(addr.m8, addr.m8 + 8, this->last_eui64_.begin()); std::copy(addr.m8, addr.m8 + 8, this->last_eui64_.begin());
this->publish_state(format_hex_pretty(this->last_eui64_.begin(), 8)); this->publish_state(format_hex(this->last_eui64_.begin(), 8));
} }
} }
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
@ -176,7 +176,7 @@ class NetworkKeyOpenThreadInfo : public DatasetOpenThreadInfo, public text_senso
void update_dataset_(otOperationalDataset *dataset) override { void update_dataset_(otOperationalDataset *dataset) override {
if (!std::equal(this->last_key_.begin(), this->last_key_.end(), dataset->mNetworkKey.m8)) { if (!std::equal(this->last_key_.begin(), this->last_key_.end(), dataset->mNetworkKey.m8)) {
std::copy(dataset->mNetworkKey.m8, dataset->mNetworkKey.m8 + 16, this->last_key_.begin()); std::copy(dataset->mNetworkKey.m8, dataset->mNetworkKey.m8 + 16, this->last_key_.begin());
this->publish_state(format_hex_pretty(dataset->mNetworkKey.m8, 16)); this->publish_state(format_hex(dataset->mNetworkKey.m8, 16));
} }
} }
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
@ -211,7 +211,7 @@ class ExtPanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor:
void update_dataset_(otOperationalDataset *dataset) override { void update_dataset_(otOperationalDataset *dataset) override {
if (!std::equal(this->last_extpanid_.begin(), this->last_extpanid_.end(), dataset->mExtendedPanId.m8)) { if (!std::equal(this->last_extpanid_.begin(), this->last_extpanid_.end(), dataset->mExtendedPanId.m8)) {
std::copy(dataset->mExtendedPanId.m8, dataset->mExtendedPanId.m8 + 8, this->last_extpanid_.begin()); std::copy(dataset->mExtendedPanId.m8, dataset->mExtendedPanId.m8 + 8, this->last_extpanid_.begin());
this->publish_state(format_hex_pretty(this->last_extpanid_.begin(), 8)); this->publish_state(format_hex(this->last_extpanid_.begin(), 8));
} }
} }