diff --git a/esphome/core/defines.h b/esphome/core/defines.h index dc0ac3c1e8..7bc84a22dc 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -71,7 +71,7 @@ #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_CALLBACK -#define USE_OTA_VERSION 1 +#define USE_OTA_VERSION 2 #define USE_OUTPUT #define USE_POWER_SUPPLY #define USE_QR_CODE 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): diff --git a/requirements.txt b/requirements.txt index 1de6e3dd06..44e7669fdb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ platformio==6.1.16 # When updating platformio, also update Dockerfile esptool==4.7.0 click==8.1.7 esphome-dashboard==20250212.0 -aioesphomeapi==29.1.0 +aioesphomeapi==29.1.1 zeroconf==0.145.1 puremagic==1.27 ruamel.yaml==0.18.6 # dashboard_import