Z-Wave to support migrating from USB to socket with same home ID (#153522)

This commit is contained in:
Paulus Schoutsen
2025-10-03 10:46:12 -04:00
committed by GitHub
parent 4ff5462cc4
commit d595ec8a07
2 changed files with 130 additions and 3 deletions

View File

@@ -918,7 +918,7 @@ class ZWaveJSConfigFlow(ConfigFlow, domain=DOMAIN):
discovery_info = await self._async_get_addon_discovery_info()
self.ws_address = f"ws://{discovery_info['host']}:{discovery_info['port']}"
if not self.unique_id or self.source in (SOURCE_USB, SOURCE_ESPHOME):
if not self.unique_id or self.source == SOURCE_USB:
if not self.version_info:
try:
self.version_info = await async_get_version_info(
@@ -942,7 +942,12 @@ class ZWaveJSConfigFlow(ConfigFlow, domain=DOMAIN):
CONF_S2_UNAUTHENTICATED_KEY: self.s2_unauthenticated_key,
CONF_LR_S2_ACCESS_CONTROL_KEY: self.lr_s2_access_control_key,
CONF_LR_S2_AUTHENTICATED_KEY: self.lr_s2_authenticated_key,
}
},
error=(
"migration_successful"
if self.source in (SOURCE_USB, SOURCE_ESPHOME)
else "already_configured"
),
)
return self._async_create_entry_from_vars()
@@ -1490,6 +1495,8 @@ class ZWaveJSConfigFlow(ConfigFlow, domain=DOMAIN):
)
# Only update existing entries that are configured via sockets
and existing_entry.data.get(CONF_SOCKET_PATH)
# And use the add-on
and existing_entry.data.get(CONF_USE_ADDON)
):
await self._async_set_addon_config(
{CONF_ADDON_SOCKET: discovery_info.socket_path}
@@ -1498,6 +1505,11 @@ class ZWaveJSConfigFlow(ConfigFlow, domain=DOMAIN):
self.hass.config_entries.async_schedule_reload(existing_entry.entry_id)
return self.async_abort(reason="already_configured")
# We are not aborting if home ID configured here, we just want to make sure that it's set
# We will update a USB based config entry automatically in `async_step_finish_addon_setup_user`
await self.async_set_unique_id(
str(discovery_info.zwave_home_id), raise_on_progress=False
)
self.socket_path = discovery_info.socket_path
self.context["title_placeholders"] = {
CONF_NAME: f"{discovery_info.name} via ESPHome"

View File

@@ -1303,7 +1303,11 @@ async def test_esphome_discovery_already_configured(
entry = MockConfigEntry(
entry_id="mock-entry-id",
domain=DOMAIN,
data={CONF_SOCKET_PATH: "esphome://existing-device:6053"},
data={
CONF_SOCKET_PATH: "esphome://existing-device:6053",
"use_addon": True,
"integration_created_addon": True,
},
title=TITLE,
unique_id="1234",
)
@@ -1333,6 +1337,117 @@ async def test_esphome_discovery_already_configured(
)
@pytest.mark.usefixtures("supervisor", "addon_not_installed", "addon_info")
async def test_esphome_discovery_usb_same_home_id(
hass: HomeAssistant,
install_addon: AsyncMock,
set_addon_options: AsyncMock,
start_addon: AsyncMock,
) -> None:
"""Test ESPHome discovery works if USB stick with same home ID is configured."""
entry = MockConfigEntry(
entry_id="mock-entry-id",
domain=DOMAIN,
data={
CONF_USB_PATH: "/dev/ttyUSB0",
"use_addon": True,
"integration_created_addon": True,
},
title=TITLE,
unique_id="1234",
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ESPHOME},
data=ESPHOME_DISCOVERY_INFO,
)
assert result["type"] is FlowResultType.MENU
assert result["step_id"] == "installation_type"
assert result["menu_options"] == ["intent_recommended", "intent_custom"]
result = await hass.config_entries.flow.async_configure(
result["flow_id"], {"next_step_id": "intent_custom"}
)
assert result["step_id"] == "install_addon"
assert result["type"] is FlowResultType.SHOW_PROGRESS
# Make sure the flow continues when the progress task is done.
await hass.async_block_till_done()
result = await hass.config_entries.flow.async_configure(result["flow_id"])
assert install_addon.call_args == call("core_zwave_js")
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "network_type"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"network_type": "existing",
},
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "configure_security_keys"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
"s0_legacy_key": "new123",
"s2_access_control_key": "new456",
"s2_authenticated_key": "new789",
"s2_unauthenticated_key": "new987",
"lr_s2_access_control_key": "new654",
"lr_s2_authenticated_key": "new321",
},
)
assert set_addon_options.call_args == call(
"core_zwave_js",
AddonsOptions(
config={
"socket": "esphome://192.168.1.100:6053",
"s0_legacy_key": "new123",
"s2_access_control_key": "new456",
"s2_authenticated_key": "new789",
"s2_unauthenticated_key": "new987",
"lr_s2_access_control_key": "new654",
"lr_s2_authenticated_key": "new321",
}
),
)
assert result["type"] is FlowResultType.SHOW_PROGRESS
assert result["step_id"] == "start_addon"
await hass.async_block_till_done()
result = await hass.config_entries.flow.async_configure(result["flow_id"])
await hass.async_block_till_done()
assert start_addon.call_args == call("core_zwave_js")
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "migration_successful"
assert entry.data == {
"url": "ws://host1:3001",
"usb_path": None,
"socket_path": "esphome://192.168.1.100:6053",
"s0_legacy_key": "new123",
"s2_access_control_key": "new456",
"s2_authenticated_key": "new789",
"s2_unauthenticated_key": "new987",
"lr_s2_access_control_key": "new654",
"lr_s2_authenticated_key": "new321",
"use_addon": True,
"integration_created_addon": True,
}
@pytest.mark.usefixtures("supervisor", "addon_installed")
async def test_discovery_addon_not_running(
hass: HomeAssistant,