mirror of
https://github.com/home-assistant/core.git
synced 2025-11-10 19:40:11 +00:00
Move first probe firmware to firmware progress in hardware flow (#152819)
This commit is contained in:
@@ -88,7 +88,7 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
self.addon_install_task: asyncio.Task | None = None
|
self.addon_install_task: asyncio.Task | None = None
|
||||||
self.addon_start_task: asyncio.Task | None = None
|
self.addon_start_task: asyncio.Task | None = None
|
||||||
self.addon_uninstall_task: asyncio.Task | None = None
|
self.addon_uninstall_task: asyncio.Task | None = None
|
||||||
self.firmware_install_task: asyncio.Task | None = None
|
self.firmware_install_task: asyncio.Task[None] | None = None
|
||||||
self.installing_firmware_name: str | None = None
|
self.installing_firmware_name: str | None = None
|
||||||
|
|
||||||
def _get_translation_placeholders(self) -> dict[str, str]:
|
def _get_translation_placeholders(self) -> dict[str, str]:
|
||||||
@@ -184,9 +184,58 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
step_id: str,
|
step_id: str,
|
||||||
next_step_id: str,
|
next_step_id: str,
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
|
"""Show progress dialog for installing firmware."""
|
||||||
|
if not self.firmware_install_task:
|
||||||
|
self.firmware_install_task = self.hass.async_create_task(
|
||||||
|
self._install_firmware(
|
||||||
|
fw_update_url,
|
||||||
|
fw_type,
|
||||||
|
firmware_name,
|
||||||
|
expected_installed_firmware_type,
|
||||||
|
),
|
||||||
|
f"Install {firmware_name} firmware",
|
||||||
|
)
|
||||||
|
if not self.firmware_install_task.done():
|
||||||
|
return self.async_show_progress(
|
||||||
|
step_id=step_id,
|
||||||
|
progress_action="install_firmware",
|
||||||
|
description_placeholders={
|
||||||
|
**self._get_translation_placeholders(),
|
||||||
|
"firmware_name": firmware_name,
|
||||||
|
},
|
||||||
|
progress_task=self.firmware_install_task,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self.firmware_install_task
|
||||||
|
except AbortFlow as err:
|
||||||
|
return self.async_show_progress_done(
|
||||||
|
next_step_id=err.reason,
|
||||||
|
)
|
||||||
|
except HomeAssistantError:
|
||||||
|
_LOGGER.exception("Failed to flash firmware")
|
||||||
|
return self.async_show_progress_done(next_step_id="firmware_install_failed")
|
||||||
|
finally:
|
||||||
|
self.firmware_install_task = None
|
||||||
|
|
||||||
|
return self.async_show_progress_done(next_step_id=next_step_id)
|
||||||
|
|
||||||
|
async def _install_firmware(
|
||||||
|
self,
|
||||||
|
fw_update_url: str,
|
||||||
|
fw_type: str,
|
||||||
|
firmware_name: str,
|
||||||
|
expected_installed_firmware_type: ApplicationType,
|
||||||
|
) -> None:
|
||||||
|
"""Install firmware."""
|
||||||
|
if not await self._probe_firmware_info():
|
||||||
|
raise AbortFlow(
|
||||||
|
reason="unsupported_firmware",
|
||||||
|
description_placeholders=self._get_translation_placeholders(),
|
||||||
|
)
|
||||||
|
|
||||||
assert self._device is not None
|
assert self._device is not None
|
||||||
|
|
||||||
if not self.firmware_install_task:
|
|
||||||
# Keep track of the firmware we're working with, for error messages
|
# Keep track of the firmware we're working with, for error messages
|
||||||
self.installing_firmware_name = firmware_name
|
self.installing_firmware_name = firmware_name
|
||||||
|
|
||||||
@@ -194,8 +243,7 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
# installed: upgrading to the latest release of the current firmware type
|
# installed: upgrading to the latest release of the current firmware type
|
||||||
# isn't strictly necessary for functionality.
|
# isn't strictly necessary for functionality.
|
||||||
firmware_install_required = self._probed_firmware_info is None or (
|
firmware_install_required = self._probed_firmware_info is None or (
|
||||||
self._probed_firmware_info.firmware_type
|
self._probed_firmware_info.firmware_type != expected_installed_firmware_type
|
||||||
!= expected_installed_firmware_type
|
|
||||||
)
|
)
|
||||||
|
|
||||||
session = async_get_clientsession(self.hass)
|
session = async_get_clientsession(self.hass)
|
||||||
@@ -206,21 +254,15 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
fw_manifest = next(
|
fw_manifest = next(
|
||||||
fw for fw in manifest.firmwares if fw.filename.startswith(fw_type)
|
fw for fw in manifest.firmwares if fw.filename.startswith(fw_type)
|
||||||
)
|
)
|
||||||
except (StopIteration, TimeoutError, ClientError, ManifestMissing):
|
except (StopIteration, TimeoutError, ClientError, ManifestMissing) as err:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning("Failed to fetch firmware update manifest", exc_info=True)
|
||||||
"Failed to fetch firmware update manifest", exc_info=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# Not having internet access should not prevent setup
|
# Not having internet access should not prevent setup
|
||||||
if not firmware_install_required:
|
if not firmware_install_required:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug("Skipping firmware upgrade due to index download failure")
|
||||||
"Skipping firmware upgrade due to index download failure"
|
return
|
||||||
)
|
|
||||||
return self.async_show_progress_done(next_step_id=next_step_id)
|
|
||||||
|
|
||||||
return self.async_show_progress_done(
|
raise AbortFlow(reason="firmware_download_failed") from err
|
||||||
next_step_id="firmware_download_failed"
|
|
||||||
)
|
|
||||||
|
|
||||||
if not firmware_install_required:
|
if not firmware_install_required:
|
||||||
assert self._probed_firmware_info is not None
|
assert self._probed_firmware_info is not None
|
||||||
@@ -236,27 +278,22 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
probed_fw_version,
|
probed_fw_version,
|
||||||
fw_version,
|
fw_version,
|
||||||
)
|
)
|
||||||
return self.async_show_progress_done(next_step_id=next_step_id)
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fw_data = await client.async_fetch_firmware(fw_manifest)
|
fw_data = await client.async_fetch_firmware(fw_manifest)
|
||||||
except (TimeoutError, ClientError, ValueError):
|
except (TimeoutError, ClientError, ValueError) as err:
|
||||||
_LOGGER.warning("Failed to fetch firmware update", exc_info=True)
|
_LOGGER.warning("Failed to fetch firmware update", exc_info=True)
|
||||||
|
|
||||||
# If we cannot download new firmware, we shouldn't block setup
|
# If we cannot download new firmware, we shouldn't block setup
|
||||||
if not firmware_install_required:
|
if not firmware_install_required:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug("Skipping firmware upgrade due to image download failure")
|
||||||
"Skipping firmware upgrade due to image download failure"
|
return
|
||||||
)
|
|
||||||
return self.async_show_progress_done(next_step_id=next_step_id)
|
|
||||||
|
|
||||||
# Otherwise, fail
|
# Otherwise, fail
|
||||||
return self.async_show_progress_done(
|
raise AbortFlow(reason="firmware_download_failed") from err
|
||||||
next_step_id="firmware_download_failed"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.firmware_install_task = self.hass.async_create_task(
|
await async_flash_silabs_firmware(
|
||||||
async_flash_silabs_firmware(
|
|
||||||
hass=self.hass,
|
hass=self.hass,
|
||||||
device=self._device,
|
device=self._device,
|
||||||
fw_data=fw_data,
|
fw_data=fw_data,
|
||||||
@@ -265,29 +302,8 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
progress_callback=lambda offset, total: self.async_update_progress(
|
progress_callback=lambda offset, total: self.async_update_progress(
|
||||||
offset / total
|
offset / total
|
||||||
),
|
),
|
||||||
),
|
|
||||||
f"Flash {firmware_name} firmware",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self.firmware_install_task.done():
|
|
||||||
return self.async_show_progress(
|
|
||||||
step_id=step_id,
|
|
||||||
progress_action="install_firmware",
|
|
||||||
description_placeholders={
|
|
||||||
**self._get_translation_placeholders(),
|
|
||||||
"firmware_name": firmware_name,
|
|
||||||
},
|
|
||||||
progress_task=self.firmware_install_task,
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
await self.firmware_install_task
|
|
||||||
except HomeAssistantError:
|
|
||||||
_LOGGER.exception("Failed to flash firmware")
|
|
||||||
return self.async_show_progress_done(next_step_id="firmware_install_failed")
|
|
||||||
|
|
||||||
return self.async_show_progress_done(next_step_id=next_step_id)
|
|
||||||
|
|
||||||
async def _configure_and_start_otbr_addon(self) -> None:
|
async def _configure_and_start_otbr_addon(self) -> None:
|
||||||
"""Configure and start the OTBR addon."""
|
"""Configure and start the OTBR addon."""
|
||||||
|
|
||||||
@@ -353,6 +369,15 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def async_step_unsupported_firmware(
|
||||||
|
self, user_input: dict[str, Any] | None = None
|
||||||
|
) -> ConfigFlowResult:
|
||||||
|
"""Abort when unsupported firmware is detected."""
|
||||||
|
return self.async_abort(
|
||||||
|
reason="unsupported_firmware",
|
||||||
|
description_placeholders=self._get_translation_placeholders(),
|
||||||
|
)
|
||||||
|
|
||||||
async def async_step_zigbee_installation_type(
|
async def async_step_zigbee_installation_type(
|
||||||
self, user_input: dict[str, Any] | None = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> ConfigFlowResult:
|
) -> ConfigFlowResult:
|
||||||
@@ -406,12 +431,6 @@ class BaseFirmwareInstallFlow(ConfigEntryBaseFlow, ABC):
|
|||||||
|
|
||||||
async def _async_continue_picked_firmware(self) -> ConfigFlowResult:
|
async def _async_continue_picked_firmware(self) -> ConfigFlowResult:
|
||||||
"""Continue to the picked firmware step."""
|
"""Continue to the picked firmware step."""
|
||||||
if not await self._probe_firmware_info():
|
|
||||||
return self.async_abort(
|
|
||||||
reason="unsupported_firmware",
|
|
||||||
description_placeholders=self._get_translation_placeholders(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if self._picked_firmware_type == PickedFirmwareType.ZIGBEE:
|
if self._picked_firmware_type == PickedFirmwareType.ZIGBEE:
|
||||||
return await self.async_step_install_zigbee_firmware()
|
return await self.async_step_install_zigbee_firmware()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user