diff --git a/homeassistant/components/esphome/__init__.py b/homeassistant/components/esphome/__init__.py index 2a885ed90ec..07b6d3071f6 100644 --- a/homeassistant/components/esphome/__init__.py +++ b/homeassistant/components/esphome/__init__.py @@ -333,6 +333,10 @@ async def async_setup_entry( # noqa: C901 if entry_data.device_info is not None and entry_data.device_info.name: cli.expected_name = entry_data.device_info.name reconnect_logic.name = entry_data.device_info.name + if entry.unique_id is None: + hass.config_entries.async_update_entry( + entry, unique_id=entry_data.device_info.name + ) await reconnect_logic.start() entry_data.cleanup_callbacks.append(reconnect_logic.stop_callback) diff --git a/homeassistant/components/esphome/config_flow.py b/homeassistant/components/esphome/config_flow.py index 9fd12634e43..ea64fb7fb7f 100644 --- a/homeassistant/components/esphome/config_flow.py +++ b/homeassistant/components/esphome/config_flow.py @@ -331,6 +331,8 @@ class EsphomeFlowHandler(ConfigFlow, domain=DOMAIN): await cli.disconnect(force=True) self._name = self._device_info.name + await self.async_set_unique_id(self._name, raise_on_progress=False) + self._abort_if_unique_id_configured(updates={CONF_HOST: self._host}) return None diff --git a/tests/components/esphome/test_config_flow.py b/tests/components/esphome/test_config_flow.py index 43e2f916082..a4d1f416868 100644 --- a/tests/components/esphome/test_config_flow.py +++ b/tests/components/esphome/test_config_flow.py @@ -81,6 +81,7 @@ async def test_user_connection_works(hass, mock_client, mock_zeroconf): CONF_NOISE_PSK: "", } assert result["title"] == "test" + assert result["result"].unique_id == "test" assert len(mock_client.connect.mock_calls) == 1 assert len(mock_client.device_info.mock_calls) == 1 @@ -91,6 +92,35 @@ async def test_user_connection_works(hass, mock_client, mock_zeroconf): assert mock_client.noise_psk is None +async def test_user_connection_updates_host(hass, mock_client, mock_zeroconf): + """Test setup up the same name updates the host.""" + entry = MockConfigEntry( + domain=DOMAIN, + data={CONF_HOST: "test.local", CONF_PORT: 6053, CONF_PASSWORD: ""}, + unique_id="test", + ) + entry.add_to_hass(hass) + result = await hass.config_entries.flow.async_init( + "esphome", + context={"source": config_entries.SOURCE_USER}, + data=None, + ) + + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "user" + + mock_client.device_info = AsyncMock(return_value=MockDeviceInfo(False, "test")) + + result = await hass.config_entries.flow.async_init( + "esphome", + context={"source": config_entries.SOURCE_USER}, + data={CONF_HOST: "127.0.0.1", CONF_PORT: 80}, + ) + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert entry.data[CONF_HOST] == "127.0.0.1" + + async def test_user_resolve_error(hass, mock_client, mock_zeroconf): """Test user step with IP resolve error."""