diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index faeccd910e0..e01b84cb575 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -17,7 +17,7 @@ from esphome.core import HexInt from esphome.types import ConfigType CODEOWNERS = ["@jesserockz"] -AUTO_LOAD = ["socket"] +AUTO_LOAD = ["socket", "network"] byte_vector = cg.std_vector.template(cg.uint8) peer_address_t = cg.std_ns.class_("array").template(cg.uint8, 6) diff --git a/esphome/components/espnow/espnow_component.cpp b/esphome/components/espnow/espnow_component.cpp index d2e53d64d8a..c7b6aa500b4 100644 --- a/esphome/components/espnow/espnow_component.cpp +++ b/esphome/components/espnow/espnow_component.cpp @@ -21,7 +21,6 @@ #ifdef USE_WIFI #include "esphome/components/wifi/wifi_component.h" #endif -#include "esphome/components/network/esp_utils.h" namespace esphome::espnow { @@ -151,12 +150,7 @@ bool ESPNowComponent::is_wifi_enabled() { void ESPNowComponent::setup() { // Initialize LwIP stack for wake_loop_threadsafe() socket support - bool success = network::esp_init(); - if (!success) { - ESP_LOGE(TAG, "Failed to initialize network interface"); - this->mark_failed(); - return; - } + // Network interface setup handled by network component if (this->enable_on_boot_) { this->enable_(); diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 061c3106c85..c651a7d50af 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -19,8 +19,6 @@ #include #endif -#include "esphome/components/network/esp_utils.h" - namespace esphome { namespace ethernet { @@ -103,13 +101,7 @@ void EthernetComponent::setup() { err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO); ESPHL_ERROR_CHECK(err, "SPI bus initialize error"); #endif - - bool success = network::esp_init(); - if (!success) { - ESP_LOGE(TAG, "Failed to initialize network interface"); - this->mark_failed(); - return; - } + // Network interface setup handled by network component esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); this->eth_netif_ = esp_netif_new(&cfg); diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 1f75b12178a..3c78ea681ca 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -5,7 +5,7 @@ import esphome.codegen as cg from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.components.psram import is_guaranteed as psram_is_guaranteed import esphome.config_validation as cv -from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT +from esphome.const import CONF_ENABLE_IPV6, CONF_ID, CONF_MIN_IPV6_ADDR_COUNT from esphome.core import CORE, CoroPriority, coroutine_with_priority CODEOWNERS = ["@esphome/core"] @@ -19,6 +19,7 @@ KEY_HIGH_PERFORMANCE_NETWORKING = "high_performance_networking" CONF_ENABLE_HIGH_PERFORMANCE = "enable_high_performance" network_ns = cg.esphome_ns.namespace("network") +NetworkComponent = network_ns.class_("NetworkComponent", cg.Component) IPAddress = network_ns.class_("IPAddress") @@ -107,6 +108,7 @@ def has_high_performance_networking() -> bool: CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(): cv.declare_id(NetworkComponent), cv.SplitDefault( CONF_ENABLE_IPV6, esp8266=False, @@ -224,3 +226,11 @@ async def to_code(config): cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY") if CORE.is_bk72xx: cg.add_build_flag("-DCONFIG_IPV6") + + CORE.add_job(network_component_to_code, config) + + +@coroutine_with_priority(CoroPriority.NETWORK_SERVICES) +async def network_component_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) diff --git a/esphome/components/network/esp_utils.h b/esphome/components/network/esp_utils.h deleted file mode 100644 index 37e9da46b0f..00000000000 --- a/esphome/components/network/esp_utils.h +++ /dev/null @@ -1,15 +0,0 @@ -#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/network/esp_utils.cpp b/esphome/components/network/network_component.cpp similarity index 62% rename from esphome/components/network/esp_utils.cpp rename to esphome/components/network/network_component.cpp index d66dc27b9bc..e9c4dcd7464 100644 --- a/esphome/components/network/esp_utils.cpp +++ b/esphome/components/network/network_component.cpp @@ -1,37 +1,35 @@ -#include "esp_utils.h" +#include "network_component.h" #include "esphome/core/defines.h" -#if defined(USE_NETWORK) && defined(USE_ESP32) +#ifdef USE_NETWORK #include "esphome/core/log.h" +#ifdef USE_ESP32 #include "esp_err.h" #include "esp_netif.h" #include "esp_event.h" +#endif namespace esphome { namespace network { -static const char *const TAG = "network_esp"; +static const char *const TAG = "network"; -static bool initialized = false; - -bool esp_init() { - if (initialized) { - return true; - } +void NetworkComponent::setup() { + // Initialize ESP-IDF network interfaces and ensure the default event loop exists. +#ifdef USE_ESP32 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; + this->mark_failed(); + return; } err = esp_event_loop_create_default(); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_event_loop_create_default failed: (%d) %s", err, esp_err_to_name(err)); - return false; + this->mark_failed(); + return; } - initialized = true; - return true; -} - +#endif } // namespace network } // namespace esphome #endif diff --git a/esphome/components/network/network_component.h b/esphome/components/network/network_component.h new file mode 100644 index 00000000000..9530668a06e --- /dev/null +++ b/esphome/components/network/network_component.h @@ -0,0 +1,18 @@ +#pragma once +#include "esphome/core/defines.h" +#ifdef USE_NETWORK + +#ifdef USE_ESP32 +#include "esp_netif.h" +#include "esp_event.h" +#endif +namespace esphome { +namespace network { +class NetworkComponent : public Component { + public: + void setup() override; + float get_setup_priority() const override { return setup_priority::AFTER_BLUETOOTH; } +}; +} // namespace network +} // namespace esphome +#endif diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index be59ad7a757..451ff025e02 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -10,7 +10,6 @@ #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,13 +34,8 @@ void OpenThreadComponent::setup() { esp_vfs_eventfd_config_t eventfd_config = { .max_fds = 3, }; + // Network interface setup handled by network component ESP_ERROR_CHECK(nvs_flash_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 1a49efa831a..39537b2cffa 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -31,7 +31,6 @@ #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" @@ -139,12 +138,7 @@ void WiFiComponent::wifi_pre_setup_() { get_mac_address_raw(mac); set_mac_address(mac); } - bool success = network::esp_init(); - if (!success) { - ESP_LOGE(TAG, "Failed to initialize network interface"); - this->mark_failed(); - return; - } + // Network interface setup handled by network component s_wifi_event_group = xEventGroupCreate(); if (s_wifi_event_group == nullptr) { ESP_LOGE(TAG, "xEventGroupCreate failed");