Skip to content

Commit 4419c23

Browse files
authored
Add ZHA migration retry steps for unplugged adapters (#155537)
1 parent 1731a25 commit 4419c23

File tree

3 files changed

+369
-1
lines changed

3 files changed

+369
-1
lines changed

homeassistant/components/zha/config_flow.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,63 @@ async def async_step_maybe_reset_old_radio(
487487
temp_radio_mgr.device_settings = config_entry.data[CONF_DEVICE]
488488
temp_radio_mgr.radio_type = RadioType[config_entry.data[CONF_RADIO_TYPE]]
489489

490-
await temp_radio_mgr.async_reset_adapter()
490+
try:
491+
await temp_radio_mgr.async_reset_adapter()
492+
except HomeAssistantError:
493+
# Old adapter not found or cannot connect, show prompt to plug back in
494+
return await self.async_step_plug_in_old_radio()
491495

492496
return await self.async_step_maybe_confirm_ezsp_restore()
493497

498+
async def async_step_plug_in_old_radio(
499+
self, user_input: dict[str, Any] | None = None
500+
) -> ConfigFlowResult:
501+
"""Prompt user to plug in the old radio if connection fails."""
502+
config_entries = self.hass.config_entries.async_entries(
503+
DOMAIN, include_ignore=False
504+
)
505+
506+
# Unless the user removes the config entry whilst we try to reset the old radio
507+
# for a few seconds and then also unplugs it, we will basically never hit this
508+
if not config_entries:
509+
return await self.async_step_maybe_confirm_ezsp_restore()
510+
511+
config_entry = config_entries[0]
512+
old_device_path = config_entry.data[CONF_DEVICE][CONF_DEVICE_PATH]
513+
514+
return self.async_show_menu(
515+
step_id="plug_in_old_radio",
516+
menu_options=["retry_old_radio", "skip_reset_old_radio"],
517+
description_placeholders={"device_path": old_device_path},
518+
)
519+
520+
async def async_step_retry_old_radio(
521+
self, user_input: dict[str, Any] | None = None
522+
) -> ConfigFlowResult:
523+
"""Retry connecting to the old radio."""
524+
return await self.async_step_maybe_reset_old_radio()
525+
526+
async def async_step_skip_reset_old_radio(
527+
self, user_input: dict[str, Any] | None = None
528+
) -> ConfigFlowResult:
529+
"""Skip resetting the old radio and continue with migration."""
530+
return await self.async_step_maybe_confirm_ezsp_restore()
531+
532+
async def async_step_plug_in_new_radio(
533+
self, user_input: dict[str, Any] | None = None
534+
) -> ConfigFlowResult:
535+
"""Prompt user to plug in the new radio if connection fails."""
536+
if user_input is not None:
537+
# User confirmed, retry now
538+
return await self.async_step_maybe_confirm_ezsp_restore()
539+
540+
assert self._radio_mgr.device_path is not None
541+
542+
return self.async_show_form(
543+
step_id="plug_in_new_radio",
544+
description_placeholders={"device_path": self._radio_mgr.device_path},
545+
)
546+
494547
async def async_step_migration_strategy_advanced(
495548
self, user_input: dict[str, Any] | None = None
496549
) -> ConfigFlowResult:
@@ -647,6 +700,9 @@ async def async_step_maybe_confirm_ezsp_restore(
647700
# On confirmation, overwrite destructively
648701
try:
649702
await self._radio_mgr.restore_backup(overwrite_ieee=True)
703+
except HomeAssistantError:
704+
# User unplugged the new adapter, allow retry
705+
return await self.async_step_plug_in_new_radio()
650706
except CannotWriteNetworkSettings as exc:
651707
return self.async_abort(
652708
reason="cannot_restore_backup",
@@ -664,6 +720,9 @@ async def async_step_maybe_confirm_ezsp_restore(
664720
except DestructiveWriteNetworkSettings:
665721
# Restore cannot happen automatically, we need to ask for permission
666722
pass
723+
except HomeAssistantError:
724+
# User unplugged the new adapter, allow retry
725+
return await self.async_step_plug_in_new_radio()
667726
except CannotWriteNetworkSettings as exc:
668727
return self.async_abort(
669728
reason="cannot_restore_backup",

homeassistant/components/zha/strings.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,22 @@
111111
"description": "A backup was created earlier and your old adapter is being reset as part of the migration.",
112112
"title": "Resetting old adapter"
113113
},
114+
"plug_in_new_radio": {
115+
"description": "Your new adapter at `{device_path}` was not found.\nPlease plug it in and click Submit to continue.",
116+
"title": "New adapter not found"
117+
},
118+
"plug_in_old_radio": {
119+
"description": "Your old adapter at `{device_path}` was not found. You can retry after plugging it back in, or skip resetting the old adapter.\n\n**Warning:** If you skip resetting the old adapter, ensure it remains permanently disconnected. Plugging it back in later will cause network issues.",
120+
"menu_option_descriptions": {
121+
"retry_old_radio": "Retry connecting to the old adapter to reset it as part of the migration.",
122+
"skip_reset_old_radio": "Skip resetting the old adapter and continue with the migration."
123+
},
124+
"menu_options": {
125+
"retry_old_radio": "Retry",
126+
"skip_reset_old_radio": "Skip reset"
127+
},
128+
"title": "Old adapter not found"
129+
},
114130
"upload_manual_backup": {
115131
"data": {
116132
"uploaded_backup_file": "Upload a file"
@@ -1945,6 +1961,22 @@
19451961
"description": "[%key:component::zha::config::step::maybe_confirm_ezsp_restore::description%]",
19461962
"title": "[%key:component::zha::config::step::maybe_confirm_ezsp_restore::title%]"
19471963
},
1964+
"plug_in_new_radio": {
1965+
"description": "[%key:component::zha::config::step::plug_in_new_radio::description%]",
1966+
"title": "[%key:component::zha::config::step::plug_in_new_radio::title%]"
1967+
},
1968+
"plug_in_old_radio": {
1969+
"description": "[%key:component::zha::config::step::plug_in_old_radio::description%]",
1970+
"menu_option_descriptions": {
1971+
"retry_old_radio": "[%key:component::zha::config::step::plug_in_old_radio::menu_option_descriptions::retry_old_radio%]",
1972+
"skip_reset_old_radio": "[%key:component::zha::config::step::plug_in_old_radio::menu_option_descriptions::skip_reset_old_radio%]"
1973+
},
1974+
"menu_options": {
1975+
"retry_old_radio": "[%key:component::zha::config::step::plug_in_old_radio::menu_options::retry_old_radio%]",
1976+
"skip_reset_old_radio": "[%key:component::zha::config::step::plug_in_old_radio::menu_options::skip_reset_old_radio%]"
1977+
},
1978+
"title": "[%key:component::zha::config::step::plug_in_old_radio::title%]"
1979+
},
19481980
"prompt_migrate_or_reconfigure": {
19491981
"description": "Are you migrating to a new adapter or re-configuring the current adapter?",
19501982
"menu_option_descriptions": {

0 commit comments

Comments
 (0)