Skip to content

Commit 20f5d85

Browse files
authored
Await firmware installation task when flashing ZBT-1/Yellow firmware (home-assistant#147824)
1 parent 88feb51 commit 20f5d85

File tree

5 files changed

+57
-23
lines changed

5 files changed

+57
-23
lines changed

homeassistant/components/homeassistant_hardware/firmware_config_flow.py

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
)
2828
from homeassistant.core import callback
2929
from homeassistant.data_entry_flow import AbortFlow
30+
from homeassistant.exceptions import HomeAssistantError
3031
from homeassistant.helpers.aiohttp_client import async_get_clientsession
3132
from homeassistant.helpers.hassio import is_hassio
3233

@@ -67,6 +68,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
6768
self.addon_start_task: asyncio.Task | None = None
6869
self.addon_uninstall_task: asyncio.Task | None = None
6970
self.firmware_install_task: asyncio.Task | None = None
71+
self.installing_firmware_name: str | None = None
7072

7173
def _get_translation_placeholders(self) -> dict[str, str]:
7274
"""Shared translation placeholders."""
@@ -152,8 +154,12 @@ async def _install_firmware_step(
152154
assert self._device is not None
153155

154156
if not self.firmware_install_task:
155-
# We 100% need to install new firmware only if the wrong firmware is
156-
# currently installed
157+
# Keep track of the firmware we're working with, for error messages
158+
self.installing_firmware_name = firmware_name
159+
160+
# Installing new firmware is only truly required if the wrong type is
161+
# installed: upgrading to the latest release of the current firmware type
162+
# isn't strictly necessary for functionality.
157163
firmware_install_required = self._probed_firmware_info is None or (
158164
self._probed_firmware_info.firmware_type
159165
!= expected_installed_firmware_type
@@ -167,7 +173,7 @@ async def _install_firmware_step(
167173
fw_manifest = next(
168174
fw for fw in manifest.firmwares if fw.filename.startswith(fw_type)
169175
)
170-
except (StopIteration, TimeoutError, ClientError, ManifestMissing) as err:
176+
except (StopIteration, TimeoutError, ClientError, ManifestMissing):
171177
_LOGGER.warning(
172178
"Failed to fetch firmware update manifest", exc_info=True
173179
)
@@ -179,13 +185,9 @@ async def _install_firmware_step(
179185
)
180186
return self.async_show_progress_done(next_step_id=next_step_id)
181187

182-
raise AbortFlow(
183-
"fw_download_failed",
184-
description_placeholders={
185-
**self._get_translation_placeholders(),
186-
"firmware_name": firmware_name,
187-
},
188-
) from err
188+
return self.async_show_progress_done(
189+
next_step_id="firmware_download_failed"
190+
)
189191

190192
if not firmware_install_required:
191193
assert self._probed_firmware_info is not None
@@ -205,7 +207,7 @@ async def _install_firmware_step(
205207

206208
try:
207209
fw_data = await client.async_fetch_firmware(fw_manifest)
208-
except (TimeoutError, ClientError, ValueError) as err:
210+
except (TimeoutError, ClientError, ValueError):
209211
_LOGGER.warning("Failed to fetch firmware update", exc_info=True)
210212

211213
# If we cannot download new firmware, we shouldn't block setup
@@ -216,13 +218,9 @@ async def _install_firmware_step(
216218
return self.async_show_progress_done(next_step_id=next_step_id)
217219

218220
# Otherwise, fail
219-
raise AbortFlow(
220-
"fw_download_failed",
221-
description_placeholders={
222-
**self._get_translation_placeholders(),
223-
"firmware_name": firmware_name,
224-
},
225-
) from err
221+
return self.async_show_progress_done(
222+
next_step_id="firmware_download_failed"
223+
)
226224

227225
self.firmware_install_task = self.hass.async_create_task(
228226
async_flash_silabs_firmware(
@@ -249,8 +247,40 @@ async def _install_firmware_step(
249247
progress_task=self.firmware_install_task,
250248
)
251249

250+
try:
251+
await self.firmware_install_task
252+
except HomeAssistantError:
253+
_LOGGER.exception("Failed to flash firmware")
254+
return self.async_show_progress_done(next_step_id="firmware_install_failed")
255+
252256
return self.async_show_progress_done(next_step_id=next_step_id)
253257

258+
async def async_step_firmware_download_failed(
259+
self, user_input: dict[str, Any] | None = None
260+
) -> ConfigFlowResult:
261+
"""Abort when firmware download failed."""
262+
assert self.installing_firmware_name is not None
263+
return self.async_abort(
264+
reason="fw_download_failed",
265+
description_placeholders={
266+
**self._get_translation_placeholders(),
267+
"firmware_name": self.installing_firmware_name,
268+
},
269+
)
270+
271+
async def async_step_firmware_install_failed(
272+
self, user_input: dict[str, Any] | None = None
273+
) -> ConfigFlowResult:
274+
"""Abort when firmware install failed."""
275+
assert self.installing_firmware_name is not None
276+
return self.async_abort(
277+
reason="fw_install_failed",
278+
description_placeholders={
279+
**self._get_translation_placeholders(),
280+
"firmware_name": self.installing_firmware_name,
281+
},
282+
)
283+
254284
async def async_step_pick_firmware_zigbee(
255285
self, user_input: dict[str, Any] | None = None
256286
) -> ConfigFlowResult:

homeassistant/components/homeassistant_hardware/strings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
"zha_still_using_stick": "This {model} is in use by the Zigbee Home Automation integration. Please migrate your Zigbee network to another adapter or delete the integration and try again.",
3838
"otbr_still_using_stick": "This {model} is in use by the OpenThread Border Router add-on. If you use the Thread network, make sure you have alternative border routers. Uninstall the add-on and try again.",
3939
"unsupported_firmware": "The radio firmware on your {model} could not be determined. Make sure that no other integration or add-on is currently trying to communicate with the device. If you are running Home Assistant OS in a virtual machine or in Docker, please make sure that permissions are set correctly for the device.",
40-
"fw_download_failed": "{firmware_name} firmware for your {model} failed to download. Make sure Home Assistant has internet access and try again."
40+
"fw_download_failed": "{firmware_name} firmware for your {model} failed to download. Make sure Home Assistant has internet access and try again.",
41+
"fw_install_failed": "{firmware_name} firmware failed to install, check Home Assistant logs for more information."
4142
},
4243
"progress": {
4344
"install_firmware": "Please wait while {firmware_name} firmware is installed to your {model}, this will take a few minutes. Do not make any changes to your hardware or software until this finishes."

homeassistant/components/homeassistant_sky_connect/strings.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@
9393
"zha_still_using_stick": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::zha_still_using_stick%]",
9494
"otbr_still_using_stick": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::otbr_still_using_stick%]",
9595
"unsupported_firmware": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::unsupported_firmware%]",
96-
"fw_download_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_download_failed%]"
96+
"fw_download_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_download_failed%]",
97+
"fw_install_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_install_failed%]"
9798
},
9899
"progress": {
99100
"install_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::progress::install_addon%]",
@@ -147,7 +148,8 @@
147148
"zha_still_using_stick": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::zha_still_using_stick%]",
148149
"otbr_still_using_stick": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::otbr_still_using_stick%]",
149150
"unsupported_firmware": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::unsupported_firmware%]",
150-
"fw_download_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_download_failed%]"
151+
"fw_download_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_download_failed%]",
152+
"fw_install_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_install_failed%]"
151153
},
152154
"progress": {
153155
"install_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::progress::install_addon%]",

homeassistant/components/homeassistant_yellow/strings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@
118118
"zha_still_using_stick": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::zha_still_using_stick%]",
119119
"otbr_still_using_stick": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::otbr_still_using_stick%]",
120120
"unsupported_firmware": "The radio firmware on your {model} could not be determined. Make sure that no other integration or add-on is currently trying to communicate with the device.",
121-
"fw_download_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_download_failed%]"
121+
"fw_download_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_download_failed%]",
122+
"fw_install_failed": "[%key:component::homeassistant_hardware::firmware_picker::options::abort::fw_install_failed%]"
122123
},
123124
"progress": {
124125
"install_addon": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::progress::install_addon%]",

tests/components/homeassistant_hardware/test_config_flow_failures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ async def test_config_flow_thread_confirmation_fails(hass: HomeAssistant) -> Non
339339
)
340340

341341
assert pick_thread_progress_result["type"] is FlowResultType.ABORT
342-
assert pick_thread_progress_result["reason"] == "unsupported_firmware"
342+
assert pick_thread_progress_result["reason"] == "fw_install_failed"
343343

344344

345345
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)