From 1574cf62566f6ae63f0209a28b85f2b3551226c2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 25 Apr 2026 07:52:50 -0500 Subject: [PATCH 1/2] [dashboard] Add --no-states support to logs WebSocket handler EsphomeLogsHandler.build_command now appends --no-states to the spawned `esphome logs` argv when the WebSocket spawn message includes `no_states: true`. This lets the dashboard frontend suppress entity-state log lines for OTA log sessions without requiring users to drop to the CLI. Adds three unit tests covering the truthy, missing, and explicit-False cases. --- esphome/dashboard/web_server.py | 5 ++- tests/dashboard/test_web_server.py | 58 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index b8e17244e5..648991ab83 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -437,7 +437,10 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket): class EsphomeLogsHandler(EsphomePortCommandWebSocket): async def build_command(self, json_message: dict[str, Any]) -> list[str]: """Build the command to run.""" - return await self.build_device_command(["logs"], json_message) + cmd = await self.build_device_command(["logs"], json_message) + if json_message.get("no_states"): + cmd.append("--no-states") + return cmd class EsphomeRenameHandler(EsphomeCommandWebSocket): diff --git a/tests/dashboard/test_web_server.py b/tests/dashboard/test_web_server.py index daff384515..1a62cfda90 100644 --- a/tests/dashboard/test_web_server.py +++ b/tests/dashboard/test_web_server.py @@ -1744,6 +1744,64 @@ def test_proc_on_exit_skips_when_already_closed() -> None: handler.close.assert_not_called() +@pytest.mark.asyncio +async def test_esphome_logs_handler_appends_no_states_when_set() -> None: + """Test --no-states is appended when no_states is truthy in the message.""" + handler = Mock(spec=web_server.EsphomeLogsHandler) + handler.build_device_command = AsyncMock( + return_value=["esphome", "logs", "device.yaml", "--device", "OTA"] + ) + + json_message = { + "configuration": "device.yaml", + "port": "OTA", + "no_states": True, + } + cmd = await web_server.EsphomeLogsHandler.build_command(handler, json_message) + + assert cmd == [ + "esphome", + "logs", + "device.yaml", + "--device", + "OTA", + "--no-states", + ] + handler.build_device_command.assert_awaited_once_with(["logs"], json_message) + + +@pytest.mark.asyncio +async def test_esphome_logs_handler_omits_no_states_when_missing() -> None: + """Test --no-states is not added when no_states is absent from the message.""" + handler = Mock(spec=web_server.EsphomeLogsHandler) + handler.build_device_command = AsyncMock( + return_value=["esphome", "logs", "device.yaml", "--device", "OTA"] + ) + + cmd = await web_server.EsphomeLogsHandler.build_command( + handler, {"configuration": "device.yaml", "port": "OTA"} + ) + + assert "--no-states" not in cmd + assert cmd == ["esphome", "logs", "device.yaml", "--device", "OTA"] + + +@pytest.mark.asyncio +async def test_esphome_logs_handler_omits_no_states_when_false() -> None: + """Test --no-states is not added when no_states is explicitly False.""" + handler = Mock(spec=web_server.EsphomeLogsHandler) + handler.build_device_command = AsyncMock( + return_value=["esphome", "logs", "device.yaml", "--device", "OTA"] + ) + + cmd = await web_server.EsphomeLogsHandler.build_command( + handler, + {"configuration": "device.yaml", "port": "OTA", "no_states": False}, + ) + + assert "--no-states" not in cmd + + def _make_auth_handler(auth_header: str | None = None) -> Mock: """Create a mock handler with the given Authorization header.""" handler = Mock() From 1b059f7fb294945a6745a47e4d435a79f99718e3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 25 Apr 2026 08:07:55 -0500 Subject: [PATCH 2/2] Log post-append cmd in EsphomeLogsHandler so debug shows --no-states --- esphome/dashboard/web_server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 648991ab83..d67245967c 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -440,6 +440,7 @@ class EsphomeLogsHandler(EsphomePortCommandWebSocket): cmd = await self.build_device_command(["logs"], json_message) if json_message.get("no_states"): cmd.append("--no-states") + _LOGGER.debug("Built command: %s", cmd) return cmd