diff --git a/homeassistant/components/honeywell/__init__.py b/homeassistant/components/honeywell/__init__.py index 485562f8b5d..4f3f27360f8 100644 --- a/homeassistant/components/honeywell/__init__.py +++ b/homeassistant/components/honeywell/__init__.py @@ -30,14 +30,13 @@ async def async_setup_entry(hass, config): loc_id = config.data.get(CONF_LOC_ID) dev_id = config.data.get(CONF_DEV_ID) - devices = [] + devices = {} for location in client.locations_by_id.values(): - for device in location.devices_by_id.values(): - if (not loc_id or location.locationid == loc_id) and ( - not dev_id or device.deviceid == dev_id - ): - devices.append(device) + if not loc_id or location.locationid == loc_id: + for device in location.devices_by_id.values(): + if not dev_id or device.deviceid == dev_id: + devices[device.deviceid] = device if len(devices) == 0: _LOGGER.debug("No devices found") @@ -107,23 +106,30 @@ class HoneywellData: if self._client is None: return False - devices = [ + refreshed_devices = [ device for location in self._client.locations_by_id.values() for device in location.devices_by_id.values() ] - if len(devices) == 0: - _LOGGER.error("Failed to find any devices") + if len(refreshed_devices) == 0: + _LOGGER.error("Failed to find any devices after retry") return False - self.devices = devices + for updated_device in refreshed_devices: + if updated_device.deviceid in self.devices: + self.devices[updated_device.deviceid] = updated_device + else: + _LOGGER.info( + "New device with ID %s detected, reload the honeywell integration if you want to access it in Home Assistant" + ) + await self._hass.config_entries.async_reload(self._config.entry_id) return True async def _refresh_devices(self): """Refresh each enabled device.""" - for device in self.devices: + for device in self.devices.values(): await self._hass.async_add_executor_job(device.refresh) await asyncio.sleep(UPDATE_LOOP_SLEEP_TIME) @@ -143,11 +149,16 @@ class HoneywellData: ) as exp: retries -= 1 if retries == 0: + _LOGGER.error( + "Ran out of retry attempts (3 attempts allocated). Error: %s", + exp, + ) raise exp result = await self._retry() if not result: + _LOGGER.error("Retry result was empty. Error: %s", exp) raise exp - _LOGGER.error("SomeComfort update failed, Retrying - Error: %s", exp) + _LOGGER.info("SomeComfort update failed, retrying. Error: %s", exp) diff --git a/homeassistant/components/honeywell/climate.py b/homeassistant/components/honeywell/climate.py index d2766515595..6c686e92b8e 100644 --- a/homeassistant/components/honeywell/climate.py +++ b/homeassistant/components/honeywell/climate.py @@ -122,7 +122,7 @@ async def async_setup_entry(hass, config, async_add_entities, discovery_info=Non async_add_entities( [ HoneywellUSThermostat(data, device, cool_away_temp, heat_away_temp) - for device in data.devices + for device in data.devices.values() ] ) diff --git a/tests/components/honeywell/test_init.py b/tests/components/honeywell/test_init.py index 619d770c59e..49917aae151 100644 --- a/tests/components/honeywell/test_init.py +++ b/tests/components/honeywell/test_init.py @@ -1,6 +1,8 @@ """Test honeywell setup process.""" -from unittest.mock import patch +from unittest.mock import create_autospec, patch + +import somecomfort from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant @@ -29,3 +31,20 @@ async def test_setup_multiple_thermostats( await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.LOADED assert hass.states.async_entity_ids_count() == 2 + + +@patch("homeassistant.components.honeywell.UPDATE_LOOP_SLEEP_TIME", 0) +async def test_setup_multiple_thermostats_with_same_deviceid( + hass: HomeAssistant, caplog, config_entry: MockConfigEntry, device, client +) -> None: + """Test Honeywell TCC API returning duplicate device IDs.""" + mock_location2 = create_autospec(somecomfort.Location, instance=True) + mock_location2.locationid.return_value = "location2" + mock_location2.devices_by_id = {device.deviceid: device} + client.locations_by_id["location2"] = mock_location2 + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + assert config_entry.state is ConfigEntryState.LOADED + assert hass.states.async_entity_ids_count() == 1 + assert "Platform honeywell does not generate unique IDs" not in caplog.text