From ad548a5c5a5450223d203bb5f87685785b880324 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 25 Jul 2019 16:06:11 -0700 Subject: [PATCH 1/5] Expose comfort presets as HA presets --- homeassistant/components/ecobee/climate.py | 49 ++++++++++------------ tests/components/ecobee/test_climate.py | 14 ------- 2 files changed, 21 insertions(+), 42 deletions(-) diff --git a/homeassistant/components/ecobee/climate.py b/homeassistant/components/ecobee/climate.py index 6520a3aadba16a..d520002e963c0e 100644 --- a/homeassistant/components/ecobee/climate.py +++ b/homeassistant/components/ecobee/climate.py @@ -88,16 +88,6 @@ PRESET_HOLD_INDEFINITE: "indefinite", } -PRESET_MODES = [ - PRESET_NONE, - PRESET_AWAY, - PRESET_TEMPERATURE, - PRESET_HOME, - PRESET_SLEEP, - PRESET_HOLD_NEXT_TRANSITION, - PRESET_HOLD_INDEFINITE, -] - SERVICE_SET_FAN_MIN_ON_TIME = "ecobee_set_fan_min_on_time" SERVICE_RESUME_PROGRAM = "ecobee_resume_program" @@ -199,7 +189,6 @@ def __init__(self, data, thermostat_index, hold_temp): self._name = self.thermostat["name"] self.hold_temp = hold_temp self.vacation = None - self._climate_list = self.climate_list self._operation_list = [] if self.thermostat["settings"]["heatStages"]: @@ -210,6 +199,11 @@ def __init__(self, data, thermostat_index, hold_temp): self._operation_list.insert(0, HVAC_MODE_AUTO) self._operation_list.append(HVAC_MODE_OFF) + self._preset_modes = [PRESET_NONE] + self._preset_modes.extend( + [comfort["name"] for comfort in self.thermostat["program"]["climates"]] + ) + self._fan_modes = [FAN_AUTO, FAN_ON] self.update_without_throttle = False @@ -324,14 +318,6 @@ def hvac_modes(self): """Return the operation modes list.""" return self._operation_list - @property - def climate_mode(self): - """Return current mode, as the user-visible name.""" - cur = self.thermostat["program"]["currentClimateRef"] - climates = self.thermostat["program"]["climates"] - current = list(filter(lambda x: x["climateRef"] == cur, climates)) - return current[0]["name"] - @property def current_humidity(self) -> Optional[int]: """Return the current humidity.""" @@ -373,9 +359,7 @@ def device_state_attributes(self): status = self.thermostat["equipmentStatus"] return { "fan": self.fan, - "climate_mode": self.climate_mode, "equipment_running": status, - "climate_list": self.climate_list, "fan_min_on_time": self.thermostat["settings"]["fanMinOnTime"], } @@ -413,6 +397,21 @@ def set_preset_mode(self, preset_mode): elif preset_mode == PRESET_NONE: self.data.ecobee.resume_program(self.thermostat_index) + elif preset_mode in self.preset_modes: + climate_ref = None + + for comfort in self.thermostat["program"]["climates"]: + if comfort["name"] == preset_mode: + climate_ref = comfort["climateRef"] + break + + if climate_ref is None: + self.data.ecobee.set_climate_hold( + self.thermostat_index, climate_ref, self.hold_preference() + ) + else: + _LOGGER.warning("Received unknown preset mode: %s", preset_mode) + else: self.data.ecobee.set_climate_hold( self.thermostat_index, preset_mode, self.hold_preference() @@ -421,7 +420,7 @@ def set_preset_mode(self, preset_mode): @property def preset_modes(self): """Return available preset modes.""" - return PRESET_MODES + return self._preset_modes def set_auto_temp_hold(self, heat_temp, cool_temp): """Set temperature hold in auto mode.""" @@ -543,9 +542,3 @@ def hold_preference(self): # supported; note that this should not include 'indefinite' # as an indefinite away hold is interpreted as away_mode return "nextTransition" - - @property - def climate_list(self): - """Return the list of climates currently available.""" - climates = self.thermostat["program"]["climates"] - return list(map((lambda x: x["name"]), climates)) diff --git a/tests/components/ecobee/test_climate.py b/tests/components/ecobee/test_climate.py index fa3f84b4b122b6..24938e526213cc 100644 --- a/tests/components/ecobee/test_climate.py +++ b/tests/components/ecobee/test_climate.py @@ -130,44 +130,34 @@ def test_device_state_attributes(self): """Test device state attributes property.""" self.ecobee["equipmentStatus"] = "heatPump2" assert { - "climate_list": ["Climate1", "Climate2"], "fan": "off", "fan_min_on_time": 10, - "climate_mode": "Climate1", "equipment_running": "heatPump2", } == self.thermostat.device_state_attributes self.ecobee["equipmentStatus"] = "auxHeat2" assert { - "climate_list": ["Climate1", "Climate2"], "fan": "off", "fan_min_on_time": 10, - "climate_mode": "Climate1", "equipment_running": "auxHeat2", } == self.thermostat.device_state_attributes self.ecobee["equipmentStatus"] = "compCool1" assert { - "climate_list": ["Climate1", "Climate2"], "fan": "off", "fan_min_on_time": 10, - "climate_mode": "Climate1", "equipment_running": "compCool1", } == self.thermostat.device_state_attributes self.ecobee["equipmentStatus"] = "" assert { - "climate_list": ["Climate1", "Climate2"], "fan": "off", "fan_min_on_time": 10, - "climate_mode": "Climate1", "equipment_running": "", } == self.thermostat.device_state_attributes self.ecobee["equipmentStatus"] = "Unknown" assert { - "climate_list": ["Climate1", "Climate2"], "fan": "off", "fan_min_on_time": 10, - "climate_mode": "Climate1", "equipment_running": "Unknown", } == self.thermostat.device_state_attributes @@ -267,10 +257,6 @@ def test_hold_preference(self): self.ecobee["settings"]["holdAction"] = action assert "nextTransition" == self.thermostat.hold_preference() - def test_climate_list(self): - """Test climate list property.""" - assert ["Climate1", "Climate2"] == self.thermostat.climate_list - def test_set_fan_mode_on(self): """Test set fan mode to on.""" self.data.reset_mock() From b7a7f65c54195ba8732d33abe8e9fd989f7f0902 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 31 Jul 2019 17:08:14 -0700 Subject: [PATCH 2/5] Fix bugs --- homeassistant/components/ecobee/climate.py | 29 ++++++++-------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/ecobee/climate.py b/homeassistant/components/ecobee/climate.py index d520002e963c0e..321cd0f450154c 100644 --- a/homeassistant/components/ecobee/climate.py +++ b/homeassistant/components/ecobee/climate.py @@ -199,11 +199,10 @@ def __init__(self, data, thermostat_index, hold_temp): self._operation_list.insert(0, HVAC_MODE_AUTO) self._operation_list.append(HVAC_MODE_OFF) - self._preset_modes = [PRESET_NONE] - self._preset_modes.extend( - [comfort["name"] for comfort in self.thermostat["program"]["climates"]] - ) - + self._preset_modes = { + comfort["climateRef"]: comfort["name"] + for comfort in self.thermostat["program"]["climates"] + } self._fan_modes = [FAN_AUTO, FAN_ON] self.update_without_throttle = False @@ -288,17 +287,11 @@ def preset_mode(self): continue if event["type"] == "hold": - if event["holdClimateRef"] == "away": - if int(event["endDate"][0:4]) - int(event["startDate"][0:4]) <= 1: - # A temporary hold from away climate is a hold - return PRESET_AWAY - # A permanent hold from away climate - return PRESET_AWAY - if event["holdClimateRef"] != "": - # Any other hold based on climate - return event["holdClimateRef"] - # Any hold not based on a climate is a temp hold - return PRESET_TEMPERATURE + if event["holdClimateRef"] in self._preset_modes: + return self._preset_modes[event["holdClimateRef"]] + else: + # Any hold not based on a climate is a temp hold + return PRESET_TEMPERATURE if event["type"].startswith("auto"): # All auto modes are treated as holds return event["type"][4:].lower() @@ -405,7 +398,7 @@ def set_preset_mode(self, preset_mode): climate_ref = comfort["climateRef"] break - if climate_ref is None: + if climate_ref is not None: self.data.ecobee.set_climate_hold( self.thermostat_index, climate_ref, self.hold_preference() ) @@ -420,7 +413,7 @@ def set_preset_mode(self, preset_mode): @property def preset_modes(self): """Return available preset modes.""" - return self._preset_modes + return list(self._preset_modes.values()) def set_auto_temp_hold(self, heat_temp, cool_temp): """Set temperature hold in auto mode.""" From e9ae089f8906dc37e43851c486317b0dfe4a415b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 1 Aug 2019 08:53:12 -0700 Subject: [PATCH 3/5] Handle unavailable --- homeassistant/components/ecobee/climate.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/homeassistant/components/ecobee/climate.py b/homeassistant/components/ecobee/climate.py index 321cd0f450154c..c2a4015884f98b 100644 --- a/homeassistant/components/ecobee/climate.py +++ b/homeassistant/components/ecobee/climate.py @@ -216,6 +216,11 @@ def update(self): self.thermostat = self.data.ecobee.get_thermostat(self.thermostat_index) + @property + def available(self): + """Return if device is available.""" + return self.thermostat["runtime"]["connected"] + @property def supported_features(self): """Return the list of supported features.""" From deca320f3f5d15399434524509e5669272058813 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 1 Aug 2019 08:59:01 -0700 Subject: [PATCH 4/5] log level debug on update --- homeassistant/components/ecobee/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/ecobee/__init__.py b/homeassistant/components/ecobee/__init__.py index e69884af59f52c..cb8b7436b51089 100644 --- a/homeassistant/components/ecobee/__init__.py +++ b/homeassistant/components/ecobee/__init__.py @@ -97,7 +97,7 @@ def __init__(self, config_file): def update(self): """Get the latest data from pyecobee.""" self.ecobee.update() - _LOGGER.info("Ecobee data updated successfully") + _LOGGER.debug("Ecobee data updated successfully") def setup(hass, config): From 2c07eba3c9d01846fbc722677af0efa5dce620ae Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 1 Aug 2019 11:51:46 -0700 Subject: [PATCH 5/5] Lint --- homeassistant/components/ecobee/climate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ecobee/climate.py b/homeassistant/components/ecobee/climate.py index c2a4015884f98b..d9af0f93e115ea 100644 --- a/homeassistant/components/ecobee/climate.py +++ b/homeassistant/components/ecobee/climate.py @@ -294,9 +294,9 @@ def preset_mode(self): if event["type"] == "hold": if event["holdClimateRef"] in self._preset_modes: return self._preset_modes[event["holdClimateRef"]] - else: - # Any hold not based on a climate is a temp hold - return PRESET_TEMPERATURE + + # Any hold not based on a climate is a temp hold + return PRESET_TEMPERATURE if event["type"].startswith("auto"): # All auto modes are treated as holds return event["type"][4:].lower()