From 365f21b2091849f9e052b0200d220635c0a77ab0 Mon Sep 17 00:00:00 2001 From: Dan Sarginson Date: Tue, 1 Aug 2017 15:18:14 +0100 Subject: [PATCH] Honeywell fixes and improvements (#8756) * Honeywell fixes and improvements Give the Honeywell device a state ('On', 'Off', etc) that can be displayed to user and understood by other components. Previously this was always 'Unknown'. Update also raises a state_changed event when a new temperature is polled. These two together fix an issue (#8688) where Honeywell climate data couldn't be logged in InfluxDB. * Roll back some changes These were not necessary to achieve the result I wanted. * Renamed RoundThermostat's 'device' member for greater clarity Now called 'client' * Improve and simplify discovering thermostat mode Per code review, this is a rather neater way to discover the thermostat mode * Update tests for compatibility with new component The tests previously relied upon the update() method being called in the constructor. This is no longer the case. * Address formatting review comment Parens not necessary * This system mode is not certain to apply to domestic hot water Moved the mode lookup to only happen on update of radiator devices, since hot water devices seem to be treated differently and I can't test. --- homeassistant/components/climate/honeywell.py | 28 +++++++++++-------- tests/components/climate/test_honeywell.py | 2 ++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/climate/honeywell.py b/homeassistant/components/climate/honeywell.py index 65e30e3cb26..4ff87aa67ab 100644 --- a/homeassistant/components/climate/honeywell.py +++ b/homeassistant/components/climate/honeywell.py @@ -75,7 +75,8 @@ def _setup_round(username, password, config, add_devices): zones = evo_api.temperatures(force_refresh=True) for i, zone in enumerate(zones): add_devices( - [RoundThermostat(evo_api, zone['id'], i == 0, away_temp)] + [RoundThermostat(evo_api, zone['id'], i == 0, away_temp)], + True ) except socket.error: _LOGGER.error( @@ -115,9 +116,9 @@ def _setup_us(username, password, config, add_devices): class RoundThermostat(ClimateDevice): """Representation of a Honeywell Round Connected thermostat.""" - def __init__(self, device, zone_id, master, away_temp): + def __init__(self, client, zone_id, master, away_temp): """Initialize the thermostat.""" - self.device = device + self.client = client self._current_temperature = None self._target_temperature = None self._name = 'round connected' @@ -126,7 +127,6 @@ class RoundThermostat(ClimateDevice): self._is_dhw = False self._away_temp = away_temp self._away = False - self.update() @property def name(self): @@ -155,12 +155,12 @@ class RoundThermostat(ClimateDevice): temperature = kwargs.get(ATTR_TEMPERATURE) if temperature is None: return - self.device.set_temperature(self._name, temperature) + self.client.set_temperature(self._name, temperature) @property def current_operation(self: ClimateDevice) -> str: """Get the current operation of the system.""" - return getattr(self.device, ATTR_SYSTEM_MODE, None) + return getattr(self.client, ATTR_SYSTEM_MODE, None) @property def is_away_mode_on(self): @@ -169,8 +169,8 @@ class RoundThermostat(ClimateDevice): def set_operation_mode(self: ClimateDevice, operation_mode: str) -> None: """Set the HVAC mode for the thermostat.""" - if hasattr(self.device, ATTR_SYSTEM_MODE): - self.device.system_mode = operation_mode + if hasattr(self.client, ATTR_SYSTEM_MODE): + self.client.system_mode = operation_mode def turn_away_mode_on(self): """Turn away on. @@ -180,19 +180,19 @@ class RoundThermostat(ClimateDevice): it doesn't get overwritten when away mode is switched on. """ self._away = True - self.device.set_temperature(self._name, self._away_temp) + self.client.set_temperature(self._name, self._away_temp) def turn_away_mode_off(self): """Turn away off.""" self._away = False - self.device.cancel_temp_override(self._name) + self.client.cancel_temp_override(self._name) def update(self): """Get the latest date.""" try: # Only refresh if this is the "master" device, # others will pick up the cache - for val in self.device.temperatures(force_refresh=self._master): + for val in self.client.temperatures(force_refresh=self._master): if val['id'] == self._id: data = val @@ -210,6 +210,12 @@ class RoundThermostat(ClimateDevice): self._name = data['name'] self._is_dhw = False + # The underlying library doesn't expose the thermostat's mode + # but we can pull it out of the big dictionary of information. + device = self.client.devices[self._id] + self.client.system_mode = device[ + 'thermostat']['changeableValues']['mode'] + class HoneywellUSThermostat(ClimateDevice): """Representation of a Honeywell US Thermostat.""" diff --git a/tests/components/climate/test_honeywell.py b/tests/components/climate/test_honeywell.py index 3fcb6a1575c..b12c0c38f3a 100644 --- a/tests/components/climate/test_honeywell.py +++ b/tests/components/climate/test_honeywell.py @@ -275,8 +275,10 @@ class TestHoneywellRound(unittest.TestCase): self.device.temperatures.side_effect = fake_temperatures self.round1 = honeywell.RoundThermostat(self.device, '1', True, 16) + self.round1.update() self.round2 = honeywell.RoundThermostat(self.device, '2', False, 17) + self.round2.update() def test_attributes(self): """Test the attributes."""