[wifi] Skip setters that pass the default priority, timeouts, power save and auth mode (#19229)

This commit is contained in:
J. Nick Koston
2026-09-14 16:52:57 +12:00
committed by GitHub
parent 8109aa96f6
commit cba4f5bc05
7 changed files with 110 additions and 9 deletions
+21 -7
View File
@@ -169,6 +169,9 @@ MAX_WIFI_NETWORKS = 127
# get best-effort connection attempts. Longer timeout ensures we exhaust all options
# before falling back to AP mode. Aligned with improv wifi_timeout default.
DEFAULT_AP_TIMEOUT = "90s"
DEFAULT_REBOOT_TIMEOUT = "15min"
# Both defaults also match the C++ initializers in wifi_component.h; codegen skips
# the setter when the config equals them.
wifi_ns = cg.esphome_ns.namespace("wifi")
EAPAuth = wifi_ns.struct("EAPAuth")
@@ -496,7 +499,7 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_AP): wifi_network_ap,
cv.Optional(CONF_DOMAIN, default=".local"): cv.domain_name,
cv.Optional(
CONF_REBOOT_TIMEOUT, default="15min"
CONF_REBOOT_TIMEOUT, default=DEFAULT_REBOOT_TIMEOUT
): cv.positive_time_period_milliseconds,
cv.SplitDefault(
CONF_POWER_SAVE_MODE,
@@ -606,7 +609,8 @@ def wifi_network(config, ap, static_ip):
cg.add(ap.set_channel(config[CONF_CHANNEL]))
if static_ip is not None:
cg.add(ap.set_manual_ip(manual_ip(static_ip)))
if CONF_PRIORITY in config:
# priority_ is 0 in C++; skip the setter when the config matches it.
if config.get(CONF_PRIORITY, 0) != 0:
cg.add(ap.set_priority(config[CONF_PRIORITY]))
return ap
@@ -655,7 +659,9 @@ async def to_code(config):
WiFiAP(),
lambda ap: cg.add(var.set_ap(wifi_network(conf, ap, ip_config))),
)
cg.add(var.set_ap_timeout(conf[CONF_AP_TIMEOUT]))
# Skip the setter when the config matches the C++ initializer.
if (ap_timeout := conf[CONF_AP_TIMEOUT]) != cv.time_period(DEFAULT_AP_TIMEOUT):
cg.add(var.set_ap_timeout(ap_timeout))
cg.add_define("USE_WIFI_AP")
# ESP32: register the WiFi stack with the esp32 sdkconfig reconciler, which
@@ -677,10 +683,18 @@ async def to_code(config):
if has_manual_ip:
cg.add_define("USE_WIFI_MANUAL_IP")
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
cg.add(var.set_power_save_mode(config[CONF_POWER_SAVE_MODE]))
if CONF_MIN_AUTH_MODE in config:
cg.add(var.set_min_auth_mode(config[CONF_MIN_AUTH_MODE]))
# The C++ initializers are DEFAULT_REBOOT_TIMEOUT, power save NONE and minimum
# auth WPA2; skip the setters when the config matches them.
if (reboot_timeout := config[CONF_REBOOT_TIMEOUT]) != cv.time_period(
DEFAULT_REBOOT_TIMEOUT
):
cg.add(var.set_reboot_timeout(reboot_timeout))
if (power_save_mode := config[CONF_POWER_SAVE_MODE]) != "NONE":
cg.add(var.set_power_save_mode(power_save_mode))
if (
min_auth_mode := config.get(CONF_MIN_AUTH_MODE)
) is not None and min_auth_mode != "WPA2":
cg.add(var.set_min_auth_mode(min_auth_mode))
fast_connect = config[CONF_FAST_CONNECT]
if fast_connect[CONF_ENABLED]:
cg.add_define("USE_WIFI_FAST_CONNECT")
+2 -2
View File
@@ -919,11 +919,11 @@ class WiFiComponent final : public Component {
float output_power_{NAN};
uint32_t action_started_;
uint32_t last_connected_{0};
uint32_t reboot_timeout_{};
uint32_t reboot_timeout_{900000}; // Keep in sync with DEFAULT_REBOOT_TIMEOUT in __init__.py
uint32_t roaming_last_check_{0};
uint32_t roaming_scan_end_{0}; // Timestamp when last roaming scan completed
#ifdef USE_WIFI_AP
uint32_t ap_timeout_{};
uint32_t ap_timeout_{90000}; // Keep in sync with DEFAULT_AP_TIMEOUT in __init__.py
#endif
// 1-byte enums and integers
@@ -0,0 +1,12 @@
---
esphome:
name: test
esp8266:
board: d1_mini
wifi:
ssid: test
password: testtest
ap:
ssid: fallback
@@ -0,0 +1,18 @@
---
esphome:
name: test
esp8266:
board: d1_mini
wifi:
networks:
- ssid: test
password: testtest
priority: 5
ap:
ssid: fallback
ap_timeout: 2min
reboot_timeout: 0s
power_save_mode: light
min_auth_mode: wpa
@@ -0,0 +1,18 @@
---
esphome:
name: test
esp8266:
board: d1_mini
wifi:
networks:
- ssid: test
password: testtest
priority: 0
ap:
ssid: fallback
ap_timeout: 90s
reboot_timeout: 15min
power_save_mode: none
min_auth_mode: wpa2
@@ -0,0 +1,39 @@
"""Tests that wifi codegen skips setters for default values."""
from collections.abc import Callable
from pathlib import Path
import pytest
@pytest.mark.parametrize("config_file", ["bare.yaml", "defaults.yaml"])
def test_default_values_are_not_emitted(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
config_file: str,
) -> None:
"""Priority 0, 90 s AP timeout, 15 min reboot, power save none, WPA2 are C++ defaults.
Both the schema defaults and the same values written explicitly take the skip path.
"""
main_cpp = generate_main(component_config_path(config_file))
assert "set_priority(" not in main_cpp
assert "set_ap_timeout(" not in main_cpp
assert "set_reboot_timeout(" not in main_cpp
assert "set_power_save_mode(" not in main_cpp
assert "set_min_auth_mode(" not in main_cpp
def test_custom_values_are_emitted(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""Non default values still reach the C++ setters."""
main_cpp = generate_main(component_config_path("custom.yaml"))
assert "set_priority(5);" in main_cpp
assert "set_ap_timeout(120000);" in main_cpp
assert "set_reboot_timeout(0);" in main_cpp
assert "set_power_save_mode(wifi::WIFI_POWER_SAVE_LIGHT);" in main_cpp
assert "set_min_auth_mode(wifi::WIFI_MIN_AUTH_MODE_WPA);" in main_cpp