[core] Add esphome logs over web_server HTTP SSE

Stream device logs over the web_server /events Server-Sent Events feed so
'esphome logs' works on devices that have web_server: but no api:. This is
the logging counterpart to web_server OTA. Priority stays API, then MQTT,
then web_server. Reconnects automatically when the stream drops.

Factor the resolve-to-URLs step and the web_server port/auth lookup shared
with web_server OTA into a new web_server_helpers module (resolve_web_server_urls
and get_web_server_connection), with helpers.format_ip_url for IPv4/IPv6 URL
formatting, and broaden the missing-transport log error to suggest web_server:
alongside api:/MQTT/USB.
This commit is contained in:
J. Nick Koston
2026-06-21 10:50:49 -05:00
parent c826293efc
commit a97f9e7cda
10 changed files with 919 additions and 41 deletions
+17 -1
View File
@@ -14,7 +14,7 @@ import pytest
from esphome import helpers
from esphome.address_cache import AddressCache
from esphome.core import CORE, EsphomeError
from esphome.helpers import ProgressBar
from esphome.helpers import ProgressBar, format_ip_url
@pytest.mark.parametrize(
@@ -151,6 +151,22 @@ def test_is_ip_address__invalid(host):
assert actual is False
@pytest.mark.parametrize(
("family", "sockaddr", "expected"),
(
(socket.AF_INET, ("192.168.1.5", 80), "http://192.168.1.5:80/events"),
(socket.AF_INET6, ("2001:db8::1", 80, 0, 0), "http://[2001:db8::1]:80/events"),
(
socket.AF_INET6,
("fe80::1", 8080, 0, 7),
"http://[fe80::1%257]:8080/events",
),
),
)
def test_format_ip_url(family, sockaddr, expected):
assert format_ip_url(family, sockaddr, sockaddr[1], "/events") == expected
@settings(deadline=None)
@given(value=ip_addresses(v=4).map(str))
def test_is_ip_address__valid(value):