From 8103d9ae3c12664cdec27d742481cca28eee0796 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 19 Aug 2021 08:46:14 -0500 Subject: [PATCH] Add missing id to yeelights that were setup manually (#54855) --- homeassistant/components/yeelight/__init__.py | 50 +++++++++++-------- .../components/yeelight/config_flow.py | 6 ++- tests/components/yeelight/test_config_flow.py | 4 +- tests/components/yeelight/test_init.py | 22 ++++++++ 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/homeassistant/components/yeelight/__init__.py b/homeassistant/components/yeelight/__init__.py index 0ea4eb8e84f..d315c3b5860 100644 --- a/homeassistant/components/yeelight/__init__.py +++ b/homeassistant/components/yeelight/__init__.py @@ -221,35 +221,43 @@ async def _async_initialize( @callback -def _async_populate_entry_options(hass: HomeAssistant, entry: ConfigEntry) -> None: +def _async_normalize_config_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: """Move options from data for imported entries. Initialize options with default values for other entries. - """ - if entry.options: - return - hass.config_entries.async_update_entry( - entry, - data={CONF_HOST: entry.data.get(CONF_HOST), CONF_ID: entry.data.get(CONF_ID)}, - options={ - CONF_NAME: entry.data.get(CONF_NAME, ""), - CONF_MODEL: entry.data.get(CONF_MODEL, ""), - CONF_TRANSITION: entry.data.get(CONF_TRANSITION, DEFAULT_TRANSITION), - CONF_MODE_MUSIC: entry.data.get(CONF_MODE_MUSIC, DEFAULT_MODE_MUSIC), - CONF_SAVE_ON_CHANGE: entry.data.get( - CONF_SAVE_ON_CHANGE, DEFAULT_SAVE_ON_CHANGE - ), - CONF_NIGHTLIGHT_SWITCH: entry.data.get( - CONF_NIGHTLIGHT_SWITCH, DEFAULT_NIGHTLIGHT_SWITCH - ), - }, - ) + Copy the unique id to CONF_ID if it is missing + """ + if not entry.options: + hass.config_entries.async_update_entry( + entry, + data={ + CONF_HOST: entry.data.get(CONF_HOST), + CONF_ID: entry.data.get(CONF_ID, entry.unique_id), + }, + options={ + CONF_NAME: entry.data.get(CONF_NAME, ""), + CONF_MODEL: entry.data.get(CONF_MODEL, ""), + CONF_TRANSITION: entry.data.get(CONF_TRANSITION, DEFAULT_TRANSITION), + CONF_MODE_MUSIC: entry.data.get(CONF_MODE_MUSIC, DEFAULT_MODE_MUSIC), + CONF_SAVE_ON_CHANGE: entry.data.get( + CONF_SAVE_ON_CHANGE, DEFAULT_SAVE_ON_CHANGE + ), + CONF_NIGHTLIGHT_SWITCH: entry.data.get( + CONF_NIGHTLIGHT_SWITCH, DEFAULT_NIGHTLIGHT_SWITCH + ), + }, + ) + elif entry.unique_id and not entry.data.get(CONF_ID): + hass.config_entries.async_update_entry( + entry, + data={CONF_HOST: entry.data.get(CONF_HOST), CONF_ID: entry.unique_id}, + ) async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Yeelight from a config entry.""" - _async_populate_entry_options(hass, entry) + _async_normalize_config_entry(hass, entry) if entry.data.get(CONF_HOST): try: diff --git a/homeassistant/components/yeelight/config_flow.py b/homeassistant/components/yeelight/config_flow.py index d93f59535cf..651d41ff268 100644 --- a/homeassistant/components/yeelight/config_flow.py +++ b/homeassistant/components/yeelight/config_flow.py @@ -118,7 +118,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): else: self._abort_if_unique_id_configured() return self.async_create_entry( - title=f"{model} {self.unique_id}", data=user_input + title=f"{model} {self.unique_id}", + data={ + CONF_HOST: user_input[CONF_HOST], + CONF_ID: self.unique_id, + }, ) user_input = user_input or {} diff --git a/tests/components/yeelight/test_config_flow.py b/tests/components/yeelight/test_config_flow.py index 5bbfcc9283b..17902a08bfa 100644 --- a/tests/components/yeelight/test_config_flow.py +++ b/tests/components/yeelight/test_config_flow.py @@ -215,7 +215,7 @@ async def test_manual(hass: HomeAssistant): await hass.async_block_till_done() assert result4["type"] == "create_entry" assert result4["title"] == "color 0x000000000015243f" - assert result4["data"] == {CONF_HOST: IP_ADDRESS} + assert result4["data"] == {CONF_HOST: IP_ADDRESS, CONF_ID: "0x000000000015243f"} # Duplicate result = await hass.config_entries.flow.async_init( @@ -298,7 +298,7 @@ async def test_manual_no_capabilities(hass: HomeAssistant): result["flow_id"], {CONF_HOST: IP_ADDRESS} ) assert result["type"] == "create_entry" - assert result["data"] == {CONF_HOST: IP_ADDRESS} + assert result["data"] == {CONF_HOST: IP_ADDRESS, CONF_ID: None} async def test_discovered_by_homekit_and_dhcp(hass): diff --git a/tests/components/yeelight/test_init.py b/tests/components/yeelight/test_init.py index d7f4a05b436..68571fcce27 100644 --- a/tests/components/yeelight/test_init.py +++ b/tests/components/yeelight/test_init.py @@ -155,6 +155,9 @@ async def test_setup_import(hass: HomeAssistant): assert hass.states.get(f"binary_sensor.{name}_nightlight") is not None assert hass.states.get(f"light.{name}") is not None assert hass.states.get(f"light.{name}_nightlight") is not None + entry = hass.config_entries.async_entries(DOMAIN)[0] + assert entry.unique_id == "0x000000000015243f" + assert entry.data[CONF_ID] == "0x000000000015243f" async def test_unique_ids_device(hass: HomeAssistant): @@ -276,3 +279,22 @@ async def test_async_listen_error_has_host_without_id(hass: HomeAssistant): await hass.config_entries.async_setup(config_entry.entry_id) assert config_entry.state is ConfigEntryState.SETUP_RETRY + + +async def test_async_setup_with_missing_id(hass: HomeAssistant): + """Test that setting adds the missing CONF_ID from unique_id.""" + config_entry = MockConfigEntry( + domain=DOMAIN, + unique_id=ID, + data={CONF_HOST: "127.0.0.1"}, + options={CONF_NAME: "Test name"}, + ) + config_entry.add_to_hass(hass) + + with _patch_discovery(), _patch_discovery_timeout(), _patch_discovery_interval(), patch( + f"{MODULE}.AsyncBulb", return_value=_mocked_bulb(cannot_connect=True) + ): + await hass.config_entries.async_setup(config_entry.entry_id) + + assert config_entry.state is ConfigEntryState.LOADED + assert config_entry.data[CONF_ID] == ID