From 403235e2d4ec6a27ac4ad35f79b7dc2afb413611 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Feb 2026 11:20:29 -0500 Subject: [PATCH] [wifi] Add band_mode configuration for ESP32-C5 dual-band WiFi (#14148) Co-authored-by: Claude Opus 4.6 --- esphome/components/wifi/__init__.py | 22 ++++++++++++++++++- esphome/components/wifi/wifi_component.cpp | 16 ++++++++++++++ esphome/components/wifi/wifi_component.h | 13 +++++++++++ .../wifi/wifi_component_esp_idf.cpp | 7 ++++++ tests/components/wifi/test.esp32-c5-idf.yaml | 5 +++++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/components/wifi/test.esp32-c5-idf.yaml diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index afceec6c54..540d0a0ab1 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -5,7 +5,12 @@ from esphome import automation from esphome.automation import Condition import esphome.codegen as cg from esphome.components.const import CONF_USE_PSRAM -from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant +from esphome.components.esp32 import ( + add_idf_sdkconfig_option, + const, + get_esp32_variant, + only_on_variant, +) from esphome.components.network import ( has_high_performance_networking, ip_address_literal, @@ -64,6 +69,7 @@ _LOGGER = logging.getLogger(__name__) NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4] CONF_SAVE = "save" +CONF_BAND_MODE = "band_mode" CONF_MIN_AUTH_MODE = "min_auth_mode" CONF_POST_CONNECT_ROAMING = "post_connect_roaming" @@ -90,6 +96,13 @@ WIFI_POWER_SAVE_MODES = { "HIGH": WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH, } +WiFiBandMode = cg.global_ns.enum("wifi_band_mode_t") +WIFI_BAND_MODES = { + "AUTO": WiFiBandMode.WIFI_BAND_MODE_AUTO, + "2.4GHZ": WiFiBandMode.WIFI_BAND_MODE_2G_ONLY, + "5GHZ": WiFiBandMode.WIFI_BAND_MODE_5G_ONLY, +} + WifiMinAuthMode = wifi_ns.enum("WifiMinAuthMode") WIFI_MIN_AUTH_MODES = { "WPA": WifiMinAuthMode.WIFI_MIN_AUTH_MODE_WPA, @@ -353,6 +366,11 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ENABLE_RRM, esp32=False): cv.All( cv.boolean, cv.only_on_esp32 ), + cv.Optional(CONF_BAND_MODE): cv.All( + cv.enum(WIFI_BAND_MODES, upper=True), + cv.only_on_esp32, + only_on_variant(supported=[const.VARIANT_ESP32C5]), + ), cv.Optional(CONF_PASSIVE_SCAN, default=False): cv.boolean, cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, cv.Optional(CONF_POST_CONNECT_ROAMING, default=True): cv.boolean, @@ -527,6 +545,8 @@ async def to_code(config): cg.add(var.set_btm(config[CONF_ENABLE_BTM])) if config[CONF_ENABLE_RRM]: cg.add(var.set_rrm(config[CONF_ENABLE_RRM])) + if CONF_BAND_MODE in config: + cg.add(var.set_band_mode(config[CONF_BAND_MODE])) if config.get(CONF_USE_PSRAM): add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index a2efac8d26..8b3060c7c3 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1469,6 +1469,22 @@ void WiFiComponent::dump_config() { ESP_LOGCONFIG(TAG, " Disabled"); return; } +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + const char *band_mode_s; + switch (this->band_mode_) { + case WIFI_BAND_MODE_2G_ONLY: + band_mode_s = "2.4GHz"; + break; + case WIFI_BAND_MODE_5G_ONLY: + band_mode_s = "5GHz"; + break; + case WIFI_BAND_MODE_AUTO: + default: + band_mode_s = "Auto"; + break; + } + ESP_LOGCONFIG(TAG, " Band Mode: %s", band_mode_s); +#endif if (this->is_connected()) { this->print_connect_params_(); } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 4a038f602c..5f903e092a 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -45,6 +45,10 @@ extern "C" { #include #endif +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) +#include +#endif + #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) #include #include @@ -435,6 +439,9 @@ class WiFiComponent : public Component { void set_power_save_mode(WiFiPowerSaveMode power_save); void set_min_auth_mode(WifiMinAuthMode min_auth_mode) { min_auth_mode_ = min_auth_mode; } void set_output_power(float output_power) { output_power_ = output_power; } +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + void set_band_mode(wifi_band_mode_t band_mode) { this->band_mode_ = band_mode; } +#endif void set_passive_scan(bool passive); @@ -652,6 +659,9 @@ class WiFiComponent : public Component { bool wifi_sta_pre_setup_(); bool wifi_apply_output_power_(float output_power); bool wifi_apply_power_save_(); +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + bool wifi_apply_band_mode_(); +#endif bool wifi_sta_ip_config_(const optional &manual_ip); bool wifi_apply_hostname_(); bool wifi_sta_connect_(const WiFiAP &ap); @@ -774,6 +784,9 @@ class WiFiComponent : public Component { // 1-byte enums and integers WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF}; WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE}; +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + wifi_band_mode_t band_mode_{WIFI_BAND_MODE_AUTO}; +#endif WifiMinAuthMode min_auth_mode_{WIFI_MIN_AUTH_MODE_WPA2}; WiFiRetryPhase retry_phase_{WiFiRetryPhase::INITIAL_CONNECT}; uint8_t num_retried_{0}; diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 52ee482121..57bbceb1b8 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -292,6 +292,10 @@ bool WiFiComponent::wifi_apply_power_save_() { return success; } +#ifdef SOC_WIFI_SUPPORT_5G +bool WiFiComponent::wifi_apply_band_mode_() { return esp_wifi_set_band_mode(this->band_mode_) == ESP_OK; } +#endif + bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // enable STA if (!this->wifi_mode_(true, {})) @@ -726,6 +730,9 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { s_sta_started = true; // re-apply power save mode wifi_apply_power_save_(); +#ifdef SOC_WIFI_SUPPORT_5G + wifi_apply_band_mode_(); +#endif } else if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_STA_STOP) { ESP_LOGV(TAG, "STA stop"); diff --git a/tests/components/wifi/test.esp32-c5-idf.yaml b/tests/components/wifi/test.esp32-c5-idf.yaml new file mode 100644 index 0000000000..92a52db09e --- /dev/null +++ b/tests/components/wifi/test.esp32-c5-idf.yaml @@ -0,0 +1,5 @@ +wifi: + band_mode: 5GHZ + +packages: + - !include common.yaml