mirror of
https://github.com/esphome/esphome.git
synced 2026-10-08 03:54:03 +00:00
Warn about a non default port on a fallback AP with local: true as well
This commit is contained in:
@@ -408,9 +408,28 @@ def _final_validate_ap_mode(config: ConfigType) -> None:
|
||||
"web_server will act as a captive portal while the %saccess point is active.",
|
||||
"" if ap_only else "fallback ",
|
||||
)
|
||||
if not ap_only:
|
||||
return
|
||||
if not local:
|
||||
# An embedded interface on an AP (AP only, or a fallback with local: true) that is not
|
||||
# on port 80 cannot be a captive portal; say so, unless captive_portal has that role.
|
||||
if (
|
||||
local
|
||||
and config[CONF_PORT] != 80
|
||||
and wifi_config is not None
|
||||
and CONF_AP in wifi_config
|
||||
and "captive_portal" not in full_config
|
||||
):
|
||||
ap_ip = "192.168.4.1"
|
||||
if (manual_ip := wifi_config[CONF_AP].get(CONF_MANUAL_IP)) is not None:
|
||||
ap_ip = str(manual_ip[CONF_STATIC_IP])
|
||||
_LOGGER.warning(
|
||||
"web_server uses port %d, so the interface cannot open automatically on the "
|
||||
"%saccess point (captive portal detection only works on port 80); open "
|
||||
"http://%s:%d/ manually, or remove 'port:' to use 80.",
|
||||
config[CONF_PORT],
|
||||
"" if ap_only else "fallback ",
|
||||
ap_ip,
|
||||
config[CONF_PORT],
|
||||
)
|
||||
if ap_only and not local:
|
||||
_LOGGER.warning(
|
||||
"WiFi is AP only and the web_server interface is loaded from the internet, "
|
||||
"which browsers on the access point usually cannot reach; the page stays "
|
||||
@@ -419,18 +438,6 @@ def _final_validate_ap_mode(config: ConfigType) -> None:
|
||||
if config.get(CONF_LOCAL) is False
|
||||
else "Migrate to version 2 or 3",
|
||||
)
|
||||
elif config[CONF_PORT] != 80:
|
||||
ap_ip = "192.168.4.1"
|
||||
if (manual_ip := wifi_config[CONF_AP].get(CONF_MANUAL_IP)) is not None:
|
||||
ap_ip = str(manual_ip[CONF_STATIC_IP])
|
||||
_LOGGER.warning(
|
||||
"WiFi is AP only and web_server uses port %d. The interface cannot open "
|
||||
"automatically on the access point (captive portal detection only works on "
|
||||
"port 80); open http://%s:%d/ manually, or remove 'port:' to use 80.",
|
||||
config[CONF_PORT],
|
||||
ap_ip,
|
||||
config[CONF_PORT],
|
||||
)
|
||||
|
||||
|
||||
def _final_validate(config: ConfigType) -> None:
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace esphome::web_server_base {
|
||||
// The server object only exists while running, so an idle owner (AP not up) pays one pointer.
|
||||
class CaptiveDNS {
|
||||
public:
|
||||
/// Returns false when the DNS server could not start; nothing is kept, so a later start retries.
|
||||
/// Returns false when the DNS server could not start; nothing is kept, so is_running() stays false.
|
||||
bool start(const network::IPAddress &ip) {
|
||||
if (this->dns_server_ != nullptr)
|
||||
return true;
|
||||
|
||||
@@ -95,18 +95,40 @@ def test_final_validate_ap_mode_warns_for_hosted_page(
|
||||
assert ("stays blank" in caplog.text) is expect_warning
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("web_server_config", "wifi_config", "expected"),
|
||||
[
|
||||
# AP only: local is implied, so the port alone blocks captive mode.
|
||||
({CONF_VERSION: 2, CONF_PORT: 8080}, AP_ONLY, "on the access point"),
|
||||
# Fallback AP with local: true opted into captive mode; say why it is skipped.
|
||||
(
|
||||
{CONF_VERSION: 2, CONF_PORT: 8080, CONF_LOCAL: True},
|
||||
AP_FALLBACK,
|
||||
"on the fallback access point",
|
||||
),
|
||||
# Fallback AP without local: hosted page, nothing was promised.
|
||||
({CONF_VERSION: 2, CONF_PORT: 8080}, AP_FALLBACK, None),
|
||||
],
|
||||
)
|
||||
def test_final_validate_ap_mode_warns_for_non_default_port(
|
||||
web_server_config: dict,
|
||||
wifi_config: dict,
|
||||
expected: str | None,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Captive portal detection needs port 80; other ports get a hint, not captive mode."""
|
||||
config = {CONF_VERSION: 2, CONF_PORT: 8080}
|
||||
token = fv.full_config.set({"web_server": config, CONF_WIFI: AP_ONLY})
|
||||
token = fv.full_config.set(
|
||||
{"web_server": web_server_config, CONF_WIFI: wifi_config}
|
||||
)
|
||||
try:
|
||||
with caplog.at_level(logging.WARNING):
|
||||
_final_validate_ap_mode(config)
|
||||
_final_validate_ap_mode(web_server_config)
|
||||
finally:
|
||||
fv.full_config.reset(token)
|
||||
assert "cannot open automatically" in caplog.text
|
||||
if expected is None:
|
||||
assert "cannot open automatically" not in caplog.text
|
||||
return
|
||||
assert expected in caplog.text
|
||||
assert "http://192.168.4.1:8080/" in caplog.text
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user