diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index b8562aaccb..f78f17b093 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -33,6 +33,7 @@ import tornado.process import tornado.queues import tornado.web import tornado.websocket +import voluptuous as vol import yaml from yaml.nodes import Node @@ -52,7 +53,6 @@ from .util.text import friendly_name_slugify if TYPE_CHECKING: from requests import Response - _LOGGER = logging.getLogger(__name__) ENV_DEV = "ESPHOME_DASHBOARD_DEV" @@ -592,16 +592,39 @@ class IgnoreDeviceRequestHandler(BaseHandler): class DownloadListRequestHandler(BaseHandler): @authenticated @bind_config - def get(self, configuration: str | None = None) -> None: + async def get(self, configuration: str | None = None) -> None: + loop = asyncio.get_running_loop() + try: + downloads_json = await loop.run_in_executor(None, self._get, configuration) + except vol.Invalid: + self.send_error(404) + return + if downloads_json is None: + self.send_error(404) + return + self.set_status(200) + self.set_header("content-type", "application/json") + self.write(downloads_json) + self.finish() + + def _get(self, configuration: str | None = None) -> dict[str, Any] | None: storage_path = ext_storage_path(configuration) storage_json = StorageJSON.load(storage_path) if storage_json is None: - self.send_error(404) - return + return None + + config = yaml_util.load_yaml(settings.rel_path(configuration)) + + if const.CONF_EXTERNAL_COMPONENTS in config: + from esphome.components.external_components import ( + do_external_components_pass, + ) + + do_external_components_pass(config) from esphome.components.esp32 import VARIANTS as ESP32_VARIANTS - downloads = [] + downloads: list[dict[str, Any]] = [] platform: str = storage_json.target_platform.lower() if platform.upper() in ESP32_VARIANTS: @@ -615,12 +638,7 @@ class DownloadListRequestHandler(BaseHandler): except AttributeError as exc: raise ValueError(f"Unknown platform {platform}") from exc downloads = get_download_types(storage_json) - - self.set_status(200) - self.set_header("content-type", "application/json") - self.write(json.dumps(downloads)) - self.finish() - return + return json.dumps(downloads) class DownloadBinaryRequestHandler(BaseHandler):