mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 12:53:26 +00:00
[espnow, ethernet, network, openthread, wifi] centralize network initialization for ESP32 (#14012)
Co-authored-by: kbx81 <kbx81x@gmail.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org>
This commit is contained in:
@@ -17,7 +17,7 @@ from esphome.core import HexInt
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@jesserockz"]
|
||||
|
||||
AUTO_LOAD = ["network"]
|
||||
|
||||
byte_vector = cg.std_vector.template(cg.uint8)
|
||||
peer_address_t = cg.std_ns.class_("array").template(cg.uint8, 6)
|
||||
|
||||
@@ -149,12 +149,6 @@ 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
|
||||
|
||||
if (this->enable_on_boot_) {
|
||||
this->enable_();
|
||||
} else {
|
||||
@@ -174,8 +168,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));
|
||||
|
||||
@@ -164,11 +164,7 @@ void EthernetComponent::setup() {
|
||||
err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO);
|
||||
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");
|
||||
// Network interface setup handled by network component
|
||||
|
||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
|
||||
this->eth_netif_ = esp_netif_new(&cfg);
|
||||
|
||||
@@ -5,8 +5,9 @@ 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
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
AUTO_LOAD = ["mdns"]
|
||||
@@ -19,6 +20,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 +109,7 @@ def has_high_performance_networking() -> bool:
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(NetworkComponent),
|
||||
cv.SplitDefault(
|
||||
CONF_ENABLE_IPV6,
|
||||
bk72xx=False,
|
||||
@@ -224,3 +227,15 @@ async def to_code(config):
|
||||
cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_LOW_MEMORY")
|
||||
if CORE.is_rp2040:
|
||||
cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6")
|
||||
# Pvariable creation lives in a separate coroutine at NETWORK_SERVICES so it
|
||||
# emits after wifi/ethernet at COMMUNICATION. This keeps compile-time config
|
||||
# (above) separate from C++ object lifecycle and allows wiring in interface
|
||||
# pointers via get_variable().
|
||||
if CORE.is_esp32:
|
||||
CORE.add_job(network_component_to_code, config)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.NETWORK_SERVICES)
|
||||
async def network_component_to_code(config: ConfigType) -> None:
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
33
esphome/components/network/network_component.cpp
Normal file
33
esphome/components/network/network_component.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "network_component.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::network {
|
||||
|
||||
static const char *const TAG = "network";
|
||||
|
||||
void NetworkComponent::setup() {
|
||||
// Initialize ESP-IDF network interfaces and ensure the default event loop exists
|
||||
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));
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
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));
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace esphome::network
|
||||
#endif
|
||||
14
esphome/components/network/network_component.h
Normal file
14
esphome/components/network/network_component.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "esphome/core/defines.h"
|
||||
#if defined(USE_NETWORK) && defined(USE_ESP32)
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome::network {
|
||||
class NetworkComponent : public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
// AFTER_BLUETOOTH: BLE controller must initialize before esp_netif_init per IDF guidance.
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_BLUETOOTH; }
|
||||
};
|
||||
} // namespace esphome::network
|
||||
#endif
|
||||
@@ -35,9 +35,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());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
|
||||
|
||||
xTaskCreate(
|
||||
|
||||
@@ -634,9 +634,6 @@ void WiFiComponent::setup() {
|
||||
if (this->enable_on_boot_) {
|
||||
this->start();
|
||||
} else {
|
||||
#ifdef USE_ESP32
|
||||
esp_netif_init();
|
||||
#endif
|
||||
this->state_ = WIFI_COMPONENT_STATE_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,23 +145,15 @@ 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));
|
||||
return;
|
||||
}
|
||||
// Network interface setup handled by network component
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
if (s_wifi_event_group == nullptr) {
|
||||
ESP_LOGE(TAG, "xEventGroupCreate 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;
|
||||
|
||||
Reference in New Issue
Block a user