diff --git a/homeassistant/components/honeywell/__init__.py b/homeassistant/components/honeywell/__init__.py index 48f2802e89f..29f0dbb8392 100644 --- a/homeassistant/components/honeywell/__init__.py +++ b/homeassistant/components/honeywell/__init__.py @@ -41,7 +41,7 @@ async def async_setup_entry(hass, config): _LOGGER.debug("No devices found") return False - data = HoneywellService(hass, client, username, password, devices[0]) + data = HoneywellData(hass, client, username, password, devices) await data.update() hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][config.entry_id] = data @@ -65,16 +65,16 @@ def get_somecomfort_client(username, password): ) from ex -class HoneywellService: +class HoneywellData: """Get the latest data and update.""" - def __init__(self, hass, client, username, password, device): + def __init__(self, hass, client, username, password, devices): """Initialize the data object.""" self._hass = hass self._client = client self._username = username self._password = password - self.device = device + self.devices = devices async def _retry(self) -> bool: """Recreate a new somecomfort client. @@ -93,23 +93,27 @@ class HoneywellService: device for location in self._client.locations_by_id.values() for device in location.devices_by_id.values() - if device.name == self.device.name ] - if len(devices) != 1: - _LOGGER.error("Failed to find device %s", self.device.name) + if len(devices) == 0: + _LOGGER.error("Failed to find any devices") return False - self.device = devices[0] + self.devices = devices return True + def _refresh_devices(self): + """Refresh each enabled device.""" + for device in self.devices: + device.refresh() + @Throttle(MIN_TIME_BETWEEN_UPDATES) async def update(self) -> None: """Update the state.""" retries = 3 while retries > 0: try: - await self._hass.async_add_executor_job(self.device.refresh) + await self._hass.async_add_executor_job(self._refresh_devices) break except ( somecomfort.client.APIRateLimited, @@ -126,7 +130,3 @@ class HoneywellService: raise exp _LOGGER.error("SomeComfort update failed, Retrying - Error: %s", exp) - - _LOGGER.debug( - "latestData = %s ", self.device._data # pylint: disable=protected-access - ) diff --git a/homeassistant/components/honeywell/climate.py b/homeassistant/components/honeywell/climate.py index 36fe16aeaa2..230aa8ec424 100644 --- a/homeassistant/components/honeywell/climate.py +++ b/homeassistant/components/honeywell/climate.py @@ -41,7 +41,6 @@ from homeassistant.const import ( TEMP_FAHRENHEIT, ) import homeassistant.helpers.config_validation as cv -import homeassistant.helpers.device_registry as dr from .const import ( _LOGGER, @@ -116,7 +115,12 @@ async def async_setup_entry(hass, config, async_add_entities, discovery_info=Non data = hass.data[DOMAIN][config.entry_id] - async_add_entities([HoneywellUSThermostat(data, cool_away_temp, heat_away_temp)]) + async_add_entities( + [ + HoneywellUSThermostat(data, device, cool_away_temp, heat_away_temp) + for device in data.devices + ] + ) async def async_setup_platform(hass, config, add_entities, discovery_info=None): @@ -142,25 +146,24 @@ async def async_setup_platform(hass, config, add_entities, discovery_info=None): class HoneywellUSThermostat(ClimateEntity): """Representation of a Honeywell US Thermostat.""" - def __init__(self, data, cool_away_temp, heat_away_temp): + def __init__(self, data, device, cool_away_temp, heat_away_temp): """Initialize the thermostat.""" self._data = data + self._device = device self._cool_away_temp = cool_away_temp self._heat_away_temp = heat_away_temp self._away = False - self._attr_unique_id = dr.format_mac(data.device.mac_address) - self._attr_name = data.device.name + self._attr_unique_id = device.deviceid + self._attr_name = device.name self._attr_temperature_unit = ( - TEMP_CELSIUS if data.device.temperature_unit == "C" else TEMP_FAHRENHEIT + TEMP_CELSIUS if device.temperature_unit == "C" else TEMP_FAHRENHEIT ) self._attr_preset_modes = [PRESET_NONE, PRESET_AWAY] - self._attr_is_aux_heat = data.device.system_mode == "emheat" + self._attr_is_aux_heat = device.system_mode == "emheat" # not all honeywell HVACs support all modes - mappings = [ - v for k, v in HVAC_MODE_TO_HW_MODE.items() if data.device.raw_ui_data[k] - ] + mappings = [v for k, v in HVAC_MODE_TO_HW_MODE.items() if device.raw_ui_data[k]] self._hvac_mode_map = {k: v for d in mappings for k, v in d.items()} self._attr_hvac_modes = list(self._hvac_mode_map) @@ -170,28 +173,23 @@ class HoneywellUSThermostat(ClimateEntity): | SUPPORT_TARGET_TEMPERATURE_RANGE ) - if data.device._data["canControlHumidification"]: + if device._data["canControlHumidification"]: self._attr_supported_features |= SUPPORT_TARGET_HUMIDITY - if data.device.raw_ui_data["SwitchEmergencyHeatAllowed"]: + if device.raw_ui_data["SwitchEmergencyHeatAllowed"]: self._attr_supported_features |= SUPPORT_AUX_HEAT - if not data.device._data["hasFan"]: + if not device._data["hasFan"]: return # not all honeywell fans support all modes - mappings = [v for k, v in FAN_MODE_TO_HW.items() if data.device.raw_fan_data[k]] + mappings = [v for k, v in FAN_MODE_TO_HW.items() if device.raw_fan_data[k]] self._fan_mode_map = {k: v for d in mappings for k, v in d.items()} self._attr_fan_modes = list(self._fan_mode_map) self._attr_supported_features |= SUPPORT_FAN_MODE - @property - def _device(self): - """Shortcut to access the device.""" - return self._data.device - @property def extra_state_attributes(self) -> dict[str, Any]: """Return the device specific state attributes.""" diff --git a/tests/components/honeywell/conftest.py b/tests/components/honeywell/conftest.py index 05e3631e08d..ff5ec57e27c 100644 --- a/tests/components/honeywell/conftest.py +++ b/tests/components/honeywell/conftest.py @@ -31,7 +31,7 @@ def config_entry(config_data): def device(): """Mock a somecomfort.Device.""" mock_device = create_autospec(somecomfort.Device, instance=True) - mock_device.deviceid.return_value = "device1" + mock_device.deviceid = 1234567 mock_device._data = { "canControlHumidification": False, "hasFan": False, @@ -43,6 +43,22 @@ def device(): return mock_device +@pytest.fixture +def another_device(): + """Mock a somecomfort.Device.""" + mock_device = create_autospec(somecomfort.Device, instance=True) + mock_device.deviceid = 7654321 + mock_device._data = { + "canControlHumidification": False, + "hasFan": False, + } + mock_device.system_mode = "off" + mock_device.name = "device2" + mock_device.current_temperature = 20 + mock_device.mac_address = "macaddress1" + return mock_device + + @pytest.fixture def location(device): """Mock a somecomfort.Location.""" diff --git a/tests/components/honeywell/test_init.py b/tests/components/honeywell/test_init.py index d0bdb5ccf2d..7cc6b64cd63 100644 --- a/tests/components/honeywell/test_init.py +++ b/tests/components/honeywell/test_init.py @@ -1,8 +1,27 @@ """Test honeywell setup process.""" +from homeassistant.config_entries import ConfigEntryState +from homeassistant.core import HomeAssistant -async def test_setup_entry(hass, config_entry): +from tests.common import MockConfigEntry + + +async def test_setup_entry(hass: HomeAssistant, config_entry: MockConfigEntry): """Initialize the config entry.""" 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 + + +async def test_setup_multiple_thermostats( + hass: HomeAssistant, config_entry: MockConfigEntry, location, another_device +) -> None: + """Test that the config form is shown.""" + location.devices_by_id[another_device.deviceid] = another_device + 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() == 2