diff --git a/homeassistant/components/yeelight/__init__.py b/homeassistant/components/yeelight/__init__.py index 2bdde2113a4..cee6cb7b9e1 100644 --- a/homeassistant/components/yeelight/__init__.py +++ b/homeassistant/components/yeelight/__init__.py @@ -196,7 +196,6 @@ async def _async_initialize( entry_data = hass.data[DOMAIN][DATA_CONFIG_ENTRIES][entry.entry_id] = { DATA_PLATFORMS_LOADED: False } - entry.async_on_unload(entry.add_update_listener(_async_update_listener)) @callback def _async_load_platforms(): @@ -212,6 +211,15 @@ async def _async_initialize( await device.async_setup() entry_data[DATA_DEVICE] = device + if ( + device.capabilities + and entry.options.get(CONF_MODEL) != device.capabilities["model"] + ): + hass.config_entries.async_update_entry( + entry, options={**entry.options, CONF_MODEL: device.capabilities["model"]} + ) + + entry.async_on_unload(entry.add_update_listener(_async_update_listener)) entry.async_on_unload( async_dispatcher_connect( hass, DEVICE_INITIALIZED.format(host), _async_load_platforms @@ -540,7 +548,7 @@ class YeelightDevice: self._config = config self._host = host self._bulb_device = bulb - self._capabilities = {} + self.capabilities = {} self._device_type = None self._available = False self._initialized = False @@ -574,12 +582,12 @@ class YeelightDevice: @property def model(self): """Return configured/autodetected device model.""" - return self._bulb_device.model or self._capabilities.get("model") + return self._bulb_device.model or self.capabilities.get("model") @property def fw_version(self): """Return the firmware version.""" - return self._capabilities.get("fw_ver") + return self.capabilities.get("fw_ver") @property def is_nightlight_supported(self) -> bool: @@ -674,13 +682,13 @@ class YeelightDevice: async def async_setup(self): """Fetch capabilities and setup name if available.""" scanner = YeelightScanner.async_get(self._hass) - self._capabilities = await scanner.async_get_capabilities(self._host) or {} + self.capabilities = await scanner.async_get_capabilities(self._host) or {} if name := self._config.get(CONF_NAME): # Override default name when name is set in config self._name = name - elif self._capabilities: + elif self.capabilities: # Generate name from model and id when capabilities is available - self._name = _async_unique_name(self._capabilities) + self._name = _async_unique_name(self.capabilities) else: self._name = self._host # Default name is host diff --git a/homeassistant/components/yeelight/config_flow.py b/homeassistant/components/yeelight/config_flow.py index 268a0e9cea2..73bbcdcfe5f 100644 --- a/homeassistant/components/yeelight/config_flow.py +++ b/homeassistant/components/yeelight/config_flow.py @@ -96,7 +96,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): if user_input is not None: return self.async_create_entry( title=async_format_model_id(self._discovered_model, self.unique_id), - data={CONF_ID: self.unique_id, CONF_HOST: self._discovered_ip}, + data={ + CONF_ID: self.unique_id, + CONF_HOST: self._discovered_ip, + CONF_MODEL: self._discovered_model, + }, ) self._set_confirm_only() @@ -129,6 +133,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): data={ CONF_HOST: user_input[CONF_HOST], CONF_ID: self.unique_id, + CONF_MODEL: model, }, ) @@ -151,7 +156,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): host = urlparse(capabilities["location"]).hostname return self.async_create_entry( title=_async_unique_name(capabilities), - data={CONF_ID: unique_id, CONF_HOST: host}, + data={ + CONF_ID: unique_id, + CONF_HOST: host, + CONF_MODEL: capabilities["model"], + }, ) configured_devices = { diff --git a/tests/components/yeelight/test_config_flow.py b/tests/components/yeelight/test_config_flow.py index bde8a18ae55..6bc3ba68275 100644 --- a/tests/components/yeelight/test_config_flow.py +++ b/tests/components/yeelight/test_config_flow.py @@ -19,7 +19,7 @@ from homeassistant.components.yeelight import ( DOMAIN, NIGHTLIGHT_SWITCH_TYPE_LIGHT, ) -from homeassistant.components.yeelight.config_flow import CannotConnect +from homeassistant.components.yeelight.config_flow import MODEL_UNKNOWN, CannotConnect from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_ID, CONF_NAME from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import RESULT_TYPE_ABORT, RESULT_TYPE_FORM @@ -28,6 +28,7 @@ from . import ( CAPABILITIES, ID, IP_ADDRESS, + MODEL, MODULE, MODULE_CONFIG_FLOW, NAME, @@ -87,7 +88,7 @@ async def test_discovery(hass: HomeAssistant): ) assert result3["type"] == "create_entry" assert result3["title"] == UNIQUE_FRIENDLY_NAME - assert result3["data"] == {CONF_ID: ID, CONF_HOST: IP_ADDRESS} + assert result3["data"] == {CONF_ID: ID, CONF_HOST: IP_ADDRESS, CONF_MODEL: MODEL} await hass.async_block_till_done() mock_setup.assert_called_once() mock_setup_entry.assert_called_once() @@ -160,7 +161,11 @@ async def test_discovery_with_existing_device_present(hass: HomeAssistant): ) assert result3["type"] == "create_entry" assert result3["title"] == UNIQUE_FRIENDLY_NAME - assert result3["data"] == {CONF_ID: ID, CONF_HOST: IP_ADDRESS} + assert result3["data"] == { + CONF_ID: ID, + CONF_HOST: IP_ADDRESS, + CONF_MODEL: MODEL, + } await hass.async_block_till_done() await hass.async_block_till_done() @@ -300,7 +305,11 @@ async def test_manual(hass: HomeAssistant): await hass.async_block_till_done() assert result4["type"] == "create_entry" assert result4["title"] == "Color 0x15243f" - assert result4["data"] == {CONF_HOST: IP_ADDRESS, CONF_ID: "0x000000000015243f"} + assert result4["data"] == { + CONF_HOST: IP_ADDRESS, + CONF_ID: "0x000000000015243f", + CONF_MODEL: MODEL, + } # Duplicate result = await hass.config_entries.flow.async_init( @@ -333,7 +342,7 @@ async def test_options(hass: HomeAssistant): config = { CONF_NAME: NAME, - CONF_MODEL: "", + CONF_MODEL: MODEL, CONF_TRANSITION: DEFAULT_TRANSITION, CONF_MODE_MUSIC: DEFAULT_MODE_MUSIC, CONF_SAVE_ON_CHANGE: DEFAULT_SAVE_ON_CHANGE, @@ -383,7 +392,11 @@ 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, CONF_ID: None} + assert result["data"] == { + CONF_HOST: IP_ADDRESS, + CONF_ID: None, + CONF_MODEL: MODEL_UNKNOWN, + } async def test_discovered_by_homekit_and_dhcp(hass): @@ -480,7 +493,11 @@ async def test_discovered_by_dhcp_or_homekit(hass, source, data): await hass.async_block_till_done() assert result2["type"] == "create_entry" - assert result2["data"] == {CONF_HOST: IP_ADDRESS, CONF_ID: "0x000000000015243f"} + assert result2["data"] == { + CONF_HOST: IP_ADDRESS, + CONF_ID: "0x000000000015243f", + CONF_MODEL: MODEL, + } assert mock_async_setup.called assert mock_async_setup_entry.called @@ -540,7 +557,11 @@ async def test_discovered_ssdp(hass): await hass.async_block_till_done() assert result2["type"] == "create_entry" - assert result2["data"] == {CONF_HOST: IP_ADDRESS, CONF_ID: "0x000000000015243f"} + assert result2["data"] == { + CONF_HOST: IP_ADDRESS, + CONF_ID: "0x000000000015243f", + CONF_MODEL: MODEL, + } assert mock_async_setup.called assert mock_async_setup_entry.called diff --git a/tests/components/yeelight/test_init.py b/tests/components/yeelight/test_init.py index 84c87b7f1dc..4414909d8e0 100644 --- a/tests/components/yeelight/test_init.py +++ b/tests/components/yeelight/test_init.py @@ -5,6 +5,7 @@ from unittest.mock import AsyncMock, patch from yeelight import BulbException, BulbType from homeassistant.components.yeelight import ( + CONF_MODEL, CONF_NIGHTLIGHT_SWITCH, CONF_NIGHTLIGHT_SWITCH_TYPE, DATA_CONFIG_ENTRIES, @@ -35,6 +36,7 @@ from . import ( FAIL_TO_BIND_IP, ID, IP_ADDRESS, + MODEL, MODULE, SHORT_ID, _mocked_bulb, @@ -360,6 +362,7 @@ async def test_async_listen_error_late_discovery(hass, caplog): assert "Failed to connect to bulb at" not in caplog.text assert config_entry.state is ConfigEntryState.LOADED + assert config_entry.options[CONF_MODEL] == MODEL async def test_async_listen_error_has_host_with_id(hass: HomeAssistant):