From 8390a98614b65ace4c5333764006e66214006b28 Mon Sep 17 00:00:00 2001 From: Rapsssito Date: Mon, 16 Feb 2026 12:36:22 +0100 Subject: [PATCH] [ethernet, network, openthread, wifi] centralize esp32 netif intialization --- .../components/espnow/espnow_component.cpp | 13 ++++---- .../ethernet/ethernet_component.cpp | 12 ++++--- esphome/components/network/esp_utils.cpp | 33 +++++++++++++++++++ esphome/components/network/esp_utils.h | 15 +++++++++ .../components/openthread/openthread_esp.cpp | 9 +++-- .../wifi/wifi_component_esp_idf.cpp | 16 ++++----- 6 files changed, 77 insertions(+), 21 deletions(-) create mode 100644 esphome/components/network/esp_utils.cpp create mode 100644 esphome/components/network/esp_utils.h diff --git a/esphome/components/espnow/espnow_component.cpp b/esphome/components/espnow/espnow_component.cpp index 991803d8703..d2e53d64d8a 100644 --- a/esphome/components/espnow/espnow_component.cpp +++ b/esphome/components/espnow/espnow_component.cpp @@ -21,6 +21,7 @@ #ifdef USE_WIFI #include "esphome/components/wifi/wifi_component.h" #endif +#include "esphome/components/network/esp_utils.h" namespace esphome::espnow { @@ -149,11 +150,13 @@ bool ESPNowComponent::is_wifi_enabled() { } void ESPNowComponent::setup() { -#ifndef USE_WIFI // Initialize LwIP stack for wake_loop_threadsafe() socket support - // When WiFi component is present, it handles esp_netif_init() - ESP_ERROR_CHECK(esp_netif_init()); -#endif + bool success = network::esp_init(); + if (!success) { + ESP_LOGE(TAG, "Failed to initialize network interface"); + this->mark_failed(); + return; + } if (this->enable_on_boot_) { this->enable_(); @@ -174,8 +177,6 @@ void ESPNowComponent::enable() { void ESPNowComponent::enable_() { if (!this->is_wifi_enabled()) { - esp_event_loop_create_default(); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index f9d98ad51b6..061c3106c85 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -19,6 +19,8 @@ #include #endif +#include "esphome/components/network/esp_utils.h" + namespace esphome { namespace ethernet { @@ -102,10 +104,12 @@ void EthernetComponent::setup() { ESPHL_ERROR_CHECK(err, "SPI bus initialize error"); #endif - err = esp_netif_init(); - ESPHL_ERROR_CHECK(err, "ETH netif init error"); - err = esp_event_loop_create_default(); - ESPHL_ERROR_CHECK(err, "ETH event loop error"); + bool success = network::esp_init(); + if (!success) { + ESP_LOGE(TAG, "Failed to initialize network interface"); + this->mark_failed(); + return; + } esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); this->eth_netif_ = esp_netif_new(&cfg); diff --git a/esphome/components/network/esp_utils.cpp b/esphome/components/network/esp_utils.cpp new file mode 100644 index 00000000000..c04dd09d567 --- /dev/null +++ b/esphome/components/network/esp_utils.cpp @@ -0,0 +1,33 @@ +#include "esp_utils.h" + +#include "esphome/core/defines.h" +#if defined(USE_NETWORK) && defined(USE_ESP32) +#include "esphome/core/log.h" +#include "esp_err.h" +#include "esp_netif.h" +#include "esp_event.h" +namespace esphome { +namespace network { + +static const char *const TAG = "network_esp"; + +bool esp_init() { + esp_err_t err; + err = esp_netif_init(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_netif_init failed: (%d) %s", err, esp_err_to_name(err)); + return false; + } + err = esp_event_loop_create_default(); + // ESP_ERR_INVALID_STATE is returned if the default loop already exists, + // which is fine since we just want to make sure it exists + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + ESP_LOGE(TAG, "esp_event_loop_create_default failed: (%d) %s", err, esp_err_to_name(err)); + return false; + } + return true; +} + +} // namespace network +} // namespace esphome +#endif diff --git a/esphome/components/network/esp_utils.h b/esphome/components/network/esp_utils.h new file mode 100644 index 00000000000..37e9da46b0f --- /dev/null +++ b/esphome/components/network/esp_utils.h @@ -0,0 +1,15 @@ +#pragma once +#include "esphome/core/defines.h" +#if defined(USE_NETWORK) && defined(USE_ESP32) +#include "esp_netif.h" +#include "esp_event.h" +namespace esphome { +namespace network { + +/// Initialize ESP-IDF network interfaces and ensure the default event loop exists. +/// Returns true on success; logs and returns false on failure. +bool esp_init(); + +} // namespace network +} // namespace esphome +#endif diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 79cd8098093..be59ad7a757 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -10,6 +10,7 @@ #include "esp_task_wdt.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/components/network/esp_utils.h" #include "esp_err.h" #include "esp_event.h" @@ -35,8 +36,12 @@ void OpenThreadComponent::setup() { .max_fds = 3, }; ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - ESP_ERROR_CHECK(esp_netif_init()); + bool success = network::esp_init(); + if (!success) { + ESP_LOGE(TAG, "Failed to initialize network interface"); + this->mark_failed(); + return; + } ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); xTaskCreate( diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 52ee4821215..1a49efa831a 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -31,6 +31,7 @@ #ifdef USE_CAPTIVE_PORTAL #include "esphome/components/captive_portal/captive_portal.h" #endif +#include "esphome/components/network/esp_utils.h" #include "lwip/apps/sntp.h" #include "lwip/dns.h" @@ -138,9 +139,10 @@ void WiFiComponent::wifi_pre_setup_() { get_mac_address_raw(mac); set_mac_address(mac); } - esp_err_t err = esp_netif_init(); - if (err != ERR_OK) { - ESP_LOGE(TAG, "esp_netif_init failed: %s", esp_err_to_name(err)); + bool success = network::esp_init(); + if (!success) { + ESP_LOGE(TAG, "Failed to initialize network interface"); + this->mark_failed(); return; } s_wifi_event_group = xEventGroupCreate(); @@ -154,13 +156,9 @@ void WiFiComponent::wifi_pre_setup_() { ESP_LOGE(TAG, "xQueueCreate failed"); return; } - err = esp_event_loop_create_default(); - if (err != ERR_OK) { - ESP_LOGE(TAG, "esp_event_loop_create_default failed: %s", esp_err_to_name(err)); - return; - } esp_event_handler_instance_t instance_wifi_id, instance_ip_id; - err = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, nullptr, &instance_wifi_id); + esp_err_t err = + esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, nullptr, &instance_wifi_id); if (err != ERR_OK) { ESP_LOGE(TAG, "esp_event_handler_instance_register failed: %s", esp_err_to_name(err)); return;