From 01430262cd965405f2a063d2f3c227e20eaa73dc Mon Sep 17 00:00:00 2001 From: Matthias Alphart Date: Sun, 21 Jul 2019 02:57:38 +0200 Subject: [PATCH 01/17] temporary patch to fix KNX climate devices (#25356) This is a temporary patch for knx climate devices. It should be reverted when #24738 is merged to release. It should fix https://github.com/home-assistant/home-assistant/issues/25247 for 0.96 --- homeassistant/components/knx/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/knx/climate.py b/homeassistant/components/knx/climate.py index 4b5998016e1..d9b7ba58ab2 100644 --- a/homeassistant/components/knx/climate.py +++ b/homeassistant/components/knx/climate.py @@ -219,7 +219,7 @@ class KNXClimate(ClimateDevice): @property def target_temperature_step(self): """Return the supported step of target temperature.""" - return self.device.temperature_step + return self.device.setpoint_shift_step @property def target_temperature(self): From 9c51650ea3211b601429589d88b970e589268363 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 20 Jul 2019 18:01:18 -0700 Subject: [PATCH 02/17] Updated frontend to 20190720.0 --- homeassistant/components/frontend/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index 288e11bdca9..f28797968bc 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -3,7 +3,7 @@ "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/components/frontend", "requirements": [ - "home-assistant-frontend==20190719.0" + "home-assistant-frontend==20190720.0" ], "dependencies": [ "api", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 883937d94ea..bfbf5159e9b 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -10,7 +10,7 @@ certifi>=2019.6.16 cryptography==2.7 distro==1.4.0 hass-nabucasa==0.15 -home-assistant-frontend==20190719.0 +home-assistant-frontend==20190720.0 importlib-metadata==0.18 jinja2>=2.10.1 netdisco==2.6.0 diff --git a/requirements_all.txt b/requirements_all.txt index 1883fbd72f3..0084944a25a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -610,7 +610,7 @@ hole==0.3.0 holidays==0.9.10 # homeassistant.components.frontend -home-assistant-frontend==20190719.0 +home-assistant-frontend==20190720.0 # homeassistant.components.zwave homeassistant-pyozw==0.1.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 68f6efb33ae..3822c4aff2d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -165,7 +165,7 @@ hdate==0.8.8 holidays==0.9.10 # homeassistant.components.frontend -home-assistant-frontend==20190719.0 +home-assistant-frontend==20190720.0 # homeassistant.components.homekit_controller homekit[IP]==0.14.0 From 615af773e5c101db0f6c2da427d81e730013286e Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 21 Jul 2019 09:56:04 -0700 Subject: [PATCH 03/17] Updated frontend to 20190721.0 --- homeassistant/components/frontend/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index f28797968bc..9f3f4cbc1c4 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -3,7 +3,7 @@ "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/components/frontend", "requirements": [ - "home-assistant-frontend==20190720.0" + "home-assistant-frontend==20190721.0" ], "dependencies": [ "api", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index bfbf5159e9b..0c4120a4c38 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -10,7 +10,7 @@ certifi>=2019.6.16 cryptography==2.7 distro==1.4.0 hass-nabucasa==0.15 -home-assistant-frontend==20190720.0 +home-assistant-frontend==20190721.0 importlib-metadata==0.18 jinja2>=2.10.1 netdisco==2.6.0 diff --git a/requirements_all.txt b/requirements_all.txt index 0084944a25a..d519f700cb9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -610,7 +610,7 @@ hole==0.3.0 holidays==0.9.10 # homeassistant.components.frontend -home-assistant-frontend==20190720.0 +home-assistant-frontend==20190721.0 # homeassistant.components.zwave homeassistant-pyozw==0.1.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3822c4aff2d..771fe60ab5e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -165,7 +165,7 @@ hdate==0.8.8 holidays==0.9.10 # homeassistant.components.frontend -home-assistant-frontend==20190720.0 +home-assistant-frontend==20190721.0 # homeassistant.components.homekit_controller homekit[IP]==0.14.0 From ec302912a327141a944adcdabf591c1e1afe2476 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 19 Jul 2019 18:04:13 -0700 Subject: [PATCH 04/17] Restore sensiobo turn on/off methods (#25321) --- homeassistant/components/sensibo/climate.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/homeassistant/components/sensibo/climate.py b/homeassistant/components/sensibo/climate.py index 17a1d149b9f..cb9bebe16b3 100644 --- a/homeassistant/components/sensibo/climate.py +++ b/homeassistant/components/sensibo/climate.py @@ -318,6 +318,18 @@ class SensiboClimate(ClimateDevice): await self._client.async_set_ac_state_property( self._id, 'swing', swing_mode, self._ac_states) + async def async_turn_on(self): + """Turn Sensibo unit on.""" + with async_timeout.timeout(TIMEOUT): + await self._client.async_set_ac_state_property( + self._id, 'on', True, self._ac_states) + + async def async_turn_off(self): + """Turn Sensibo unit on.""" + with async_timeout.timeout(TIMEOUT): + await self._client.async_set_ac_state_property( + self._id, 'on', False, self._ac_states) + async def async_assume_state(self, state): """Set external state.""" change_needed = \ From 93a65bf5072aa6c2f99b789989120772db56672b Mon Sep 17 00:00:00 2001 From: eyager1 <44526531+eyager1@users.noreply.github.com> Date: Sun, 21 Jul 2019 13:44:15 -0400 Subject: [PATCH 05/17] Update zwave climate mappings (#25327) hvac_action should be idle when thermostat is in Pending Heat or Pending Cool. --- homeassistant/components/zwave/climate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 188f376e753..81195227ee1 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -49,10 +49,10 @@ HVAC_STATE_MAPPINGS = { HVAC_CURRENT_MAPPINGS = { "Idle": CURRENT_HVAC_IDLE, "Heat": CURRENT_HVAC_HEAT, - "Pending Heat": CURRENT_HVAC_HEAT, + "Pending Heat": CURRENT_HVAC_IDLE, "Heating": CURRENT_HVAC_HEAT, "Cool": CURRENT_HVAC_COOL, - "Pending Cool": CURRENT_HVAC_COOL, + "Pending Cool": CURRENT_HVAC_IDLE, "Cooling": CURRENT_HVAC_COOL, "Fan Only": CURRENT_HVAC_FAN, "Vent / Economiser": CURRENT_HVAC_FAN, From f6b6818fb0d80f6417892008b5839eaac6faf7ba Mon Sep 17 00:00:00 2001 From: Fredrik Erlandsson Date: Sat, 20 Jul 2019 13:41:33 +0200 Subject: [PATCH 06/17] Restore Daikin A/C on/off services (#25332) --- homeassistant/components/daikin/climate.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/homeassistant/components/daikin/climate.py b/homeassistant/components/daikin/climate.py index 397c9a607b3..10d1a6161a3 100644 --- a/homeassistant/components/daikin/climate.py +++ b/homeassistant/components/daikin/climate.py @@ -289,6 +289,17 @@ class DaikinClimate(ClimateDevice): """Retrieve latest state.""" await self._api.async_update() + async def async_turn_on(self): + """Turn device on.""" + await self._api.device.set({}) + + async def async_turn_off(self): + """Turn device off.""" + await self._api.device.set({ + HA_ATTR_TO_DAIKIN[ATTR_HVAC_MODE]: + HA_STATE_TO_DAIKIN[HVAC_MODE_OFF] + }) + @property def device_info(self): """Return a device description for device registry.""" From a56b604936fae61d00c9bf7166f28a378a4eaa5b Mon Sep 17 00:00:00 2001 From: Michael Scherer Date: Sun, 21 Jul 2019 03:00:16 +0200 Subject: [PATCH 07/17] Fix for hvac_modes list being null (#25347) * Fix for empty hvac_modes list * Empty list instead of default value for hvac_modes --- homeassistant/components/zwave/climate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 81195227ee1..f7d31bf764f 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -244,7 +244,9 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): Need to be a subset of HVAC_MODES. """ - return self._hvac_list + if self.values.mode: + return self._hvac_list + return [] @property def hvac_action(self): From e052bcb03b36a4b04370fd6880779560af7440f4 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Sat, 20 Jul 2019 14:44:47 -0400 Subject: [PATCH 08/17] add available to device info (#25349) --- homeassistant/components/zha/core/const.py | 1 + homeassistant/components/zha/core/device.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/zha/core/const.py b/homeassistant/components/zha/core/const.py index f86a5ee9f45..98620858ea8 100644 --- a/homeassistant/components/zha/core/const.py +++ b/homeassistant/components/zha/core/const.py @@ -59,6 +59,7 @@ ATTR_COMMAND = 'command' ATTR_COMMAND_TYPE = 'command_type' ATTR_ARGS = 'args' ATTR_ENDPOINT_ID = 'endpoint_id' +ATTR_AVAILABLE = 'available' IN = 'in' OUT = 'out' diff --git a/homeassistant/components/zha/core/device.py b/homeassistant/components/zha/core/device.py index 1ba890da411..82585552aa7 100644 --- a/homeassistant/components/zha/core/device.py +++ b/homeassistant/components/zha/core/device.py @@ -23,7 +23,7 @@ from .const import ( MANUFACTURER_CODE, MODEL, NAME, NWK, OUT, POWER_CONFIGURATION_CHANNEL, POWER_SOURCE, QUIRK_APPLIED, QUIRK_CLASS, SERVER, SERVER_COMMANDS, SIGNAL_AVAILABLE, UNKNOWN_MANUFACTURER, UNKNOWN_MODEL, ZDO_CHANNEL, - LQI, RSSI, LAST_SEEN) + LQI, RSSI, LAST_SEEN, ATTR_AVAILABLE) _LOGGER = logging.getLogger(__name__) _KEEP_ALIVE_INTERVAL = 7200 @@ -213,7 +213,8 @@ class ZHADevice: POWER_SOURCE: self.power_source, LQI: self.lqi, RSSI: self.rssi, - LAST_SEEN: update_time + LAST_SEEN: update_time, + ATTR_AVAILABLE: self.available } def add_cluster_channel(self, cluster_channel): From 68e7f4ca5af60409fd06faefa848f34b5f8b203e Mon Sep 17 00:00:00 2001 From: cgtobi Date: Sun, 21 Jul 2019 02:58:06 +0200 Subject: [PATCH 09/17] Fix preset service call (#25358) --- homeassistant/components/netatmo/climate.py | 25 ++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/netatmo/climate.py b/homeassistant/components/netatmo/climate.py index b62d7ca8762..48592dea9c9 100644 --- a/homeassistant/components/netatmo/climate.py +++ b/homeassistant/components/netatmo/climate.py @@ -25,6 +25,7 @@ _LOGGER = logging.getLogger(__name__) PRESET_FROST_GUARD = 'Frost Guard' PRESET_SCHEDULE = 'Schedule' +PRESET_MANUAL = 'Manual' SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE) SUPPORT_HVAC = [HVAC_MODE_HEAT, HVAC_MODE_AUTO, HVAC_MODE_OFF] @@ -32,7 +33,7 @@ SUPPORT_PRESET = [ PRESET_AWAY, PRESET_BOOST, PRESET_FROST_GUARD, PRESET_SCHEDULE, ] -STATE_NETATMO_SCHEDULE = PRESET_SCHEDULE +STATE_NETATMO_SCHEDULE = 'schedule' STATE_NETATMO_HG = 'hg' STATE_NETATMO_MAX = 'max' STATE_NETATMO_AWAY = PRESET_AWAY @@ -42,7 +43,6 @@ STATE_NETATMO_MANUAL = 'manual' PRESET_MAP_NETATMO = { PRESET_FROST_GUARD: STATE_NETATMO_HG, PRESET_BOOST: STATE_NETATMO_MAX, - STATE_NETATMO_MAX: STATE_NETATMO_MAX, PRESET_SCHEDULE: STATE_NETATMO_SCHEDULE, PRESET_AWAY: STATE_NETATMO_AWAY, STATE_NETATMO_OFF: STATE_NETATMO_OFF @@ -54,16 +54,17 @@ NETATMO_MAP_PRESET = { STATE_NETATMO_SCHEDULE: PRESET_SCHEDULE, STATE_NETATMO_AWAY: PRESET_AWAY, STATE_NETATMO_OFF: STATE_NETATMO_OFF, - STATE_NETATMO_MANUAL: 'Manual', + STATE_NETATMO_MANUAL: STATE_NETATMO_MANUAL, } HVAC_MAP_NETATMO = { - STATE_NETATMO_SCHEDULE: HVAC_MODE_AUTO, + PRESET_SCHEDULE: HVAC_MODE_AUTO, STATE_NETATMO_HG: HVAC_MODE_AUTO, PRESET_FROST_GUARD: HVAC_MODE_AUTO, - STATE_NETATMO_MAX: HVAC_MODE_HEAT, + PRESET_BOOST: HVAC_MODE_HEAT, STATE_NETATMO_OFF: HVAC_MODE_OFF, STATE_NETATMO_MANUAL: HVAC_MODE_AUTO, + PRESET_MANUAL: HVAC_MODE_AUTO, STATE_NETATMO_AWAY: HVAC_MODE_AUTO } @@ -218,9 +219,9 @@ class NetatmoThermostat(ClimateDevice): if hvac_mode == HVAC_MODE_OFF: mode = STATE_NETATMO_OFF elif hvac_mode == HVAC_MODE_AUTO: - mode = STATE_NETATMO_SCHEDULE + mode = PRESET_SCHEDULE elif hvac_mode == HVAC_MODE_HEAT: - mode = STATE_NETATMO_MAX + mode = PRESET_BOOST self.set_preset_mode(mode) @@ -259,6 +260,8 @@ class NetatmoThermostat(ClimateDevice): self._data.homestatus.setThermmode( self._data.home_id, PRESET_MAP_NETATMO[preset_mode] ) + else: + _LOGGER.error("Preset mode '%s' not available", preset_mode) self.update_without_throttle = True self.schedule_update_ha_state() @@ -308,10 +311,12 @@ class NetatmoThermostat(ClimateDevice): self._data.room_status[self._room_id]["setpoint_mode"] ] self._hvac_mode = HVAC_MAP_NETATMO[self._preset] - except KeyError: + self._battery_level = \ + self._data.room_status[self._room_id].get('battery_level') + except KeyError as err: _LOGGER.error( - "The thermostat in room %s seems to be out of reach.", - self._room_id + "The thermostat in room %s seems to be out of reach. (%s)", + self._room_id, err ) self._away = self._hvac_mode == HVAC_MAP_NETATMO[STATE_NETATMO_AWAY] From 2228a0dcac758a39c8c96ceaf725a8f9ee456c35 Mon Sep 17 00:00:00 2001 From: David Bonnes Date: Sun, 21 Jul 2019 18:07:03 +0100 Subject: [PATCH 10/17] Improve geniushub logging and bump client (#25359) * add debug logging * bump geniushub client library * delint * bump again * bump again, again --- homeassistant/components/geniushub/__init__.py | 7 +++++++ homeassistant/components/geniushub/manifest.json | 2 +- requirements_all.txt | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/geniushub/__init__.py b/homeassistant/components/geniushub/__init__.py index b9ab1515d32..4beca61e139 100644 --- a/homeassistant/components/geniushub/__init__.py +++ b/homeassistant/components/geniushub/__init__.py @@ -54,6 +54,9 @@ async def async_setup(hass, hass_config): exc_info=True) return False + _LOGGER.debug("zones_raw = %s", data._client.hub._zones_raw) # noqa; pylint: disable=protected-access + _LOGGER.debug("devices_raw = %s", data._client.hub._devices_raw) # noqa; pylint: disable=protected-access + async_track_time_interval(hass, data.async_update, SCAN_INTERVAL) for platform in ['climate', 'water_heater']: @@ -84,4 +87,8 @@ class GeniusData: except AssertionError: # assert response.status == HTTP_OK _LOGGER.warning("Update failed.", exc_info=True) return + + _LOGGER.debug("zones_raw = %s", self._client.hub._zones_raw) # noqa; pylint: disable=protected-access + _LOGGER.debug("devices_raw = %s", self._client.hub._devices_raw) # noqa; pylint: disable=protected-access + async_dispatcher_send(self._hass, DOMAIN) diff --git a/homeassistant/components/geniushub/manifest.json b/homeassistant/components/geniushub/manifest.json index 7c82ceeca44..d7f8601ae25 100644 --- a/homeassistant/components/geniushub/manifest.json +++ b/homeassistant/components/geniushub/manifest.json @@ -3,7 +3,7 @@ "name": "Genius Hub", "documentation": "https://www.home-assistant.io/components/geniushub", "requirements": [ - "geniushub-client==0.4.12" + "geniushub-client==0.4.15" ], "dependencies": [], "codeowners": ["@zxdavb"] diff --git a/requirements_all.txt b/requirements_all.txt index d519f700cb9..14c1c03eb5d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -505,7 +505,7 @@ gearbest_parser==1.0.7 geizhals==0.0.9 # homeassistant.components.geniushub -geniushub-client==0.4.12 +geniushub-client==0.4.15 # homeassistant.components.geo_json_events # homeassistant.components.nsw_rural_fire_service_feed From c795c93034f5d0777e70438ee0f89cb2c4aab0ea Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 21 Jul 2019 11:00:42 -0700 Subject: [PATCH 11/17] Introduce PRESET_NONE for climate (#25360) * Introduce PRESET_NONE for climate * Require preset mode to be a string * Lint * Fix tests --- homeassistant/components/climate/__init__.py | 2 +- homeassistant/components/climate/const.py | 2 ++ homeassistant/components/ecobee/climate.py | 5 +++-- homeassistant/components/eq3btsmart/climate.py | 4 ++-- homeassistant/components/evohome/climate.py | 7 +++---- homeassistant/components/generic_thermostat/climate.py | 6 +++--- homeassistant/components/hive/climate.py | 6 +++--- homeassistant/components/homematicip_cloud/climate.py | 4 ++-- homeassistant/components/honeywell/climate.py | 4 ++-- homeassistant/components/mqtt/climate.py | 5 ++++- homeassistant/components/nest/climate.py | 4 ++-- homeassistant/components/nuheat/climate.py | 5 +++-- homeassistant/components/opentherm_gw/climate.py | 2 +- homeassistant/components/toon/climate.py | 5 ++--- homeassistant/components/venstar/climate.py | 5 +++-- homeassistant/components/wink/climate.py | 4 ++-- tests/components/generic_thermostat/test_climate.py | 6 +++--- tests/components/mqtt/test_climate.py | 6 +++--- 18 files changed, 44 insertions(+), 38 deletions(-) diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py index 347cb275e42..cd297548273 100644 --- a/homeassistant/components/climate/__init__.py +++ b/homeassistant/components/climate/__init__.py @@ -74,7 +74,7 @@ SET_FAN_MODE_SCHEMA = vol.Schema({ }) SET_PRESET_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, - vol.Required(ATTR_PRESET_MODE): vol.Maybe(cv.string), + vol.Required(ATTR_PRESET_MODE): cv.string, }) SET_HVAC_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids, diff --git a/homeassistant/components/climate/const.py b/homeassistant/components/climate/const.py index 13f8e3b616a..7b99442c2d7 100644 --- a/homeassistant/components/climate/const.py +++ b/homeassistant/components/climate/const.py @@ -32,6 +32,8 @@ HVAC_MODES = [ HVAC_MODE_FAN_ONLY, ] +# No preset is active +PRESET_NONE = 'none' # Device is running an energy-saving mode PRESET_ECO = 'eco' diff --git a/homeassistant/components/ecobee/climate.py b/homeassistant/components/ecobee/climate.py index 3b034d4a838..b8c73e61447 100644 --- a/homeassistant/components/ecobee/climate.py +++ b/homeassistant/components/ecobee/climate.py @@ -12,7 +12,7 @@ from homeassistant.components.climate.const import ( ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, SUPPORT_TARGET_TEMPERATURE, SUPPORT_AUX_HEAT, SUPPORT_TARGET_TEMPERATURE_RANGE, SUPPORT_FAN_MODE, PRESET_AWAY, FAN_AUTO, FAN_ON, CURRENT_HVAC_OFF, CURRENT_HVAC_HEAT, - CURRENT_HVAC_COOL, SUPPORT_PRESET_MODE + CURRENT_HVAC_COOL, SUPPORT_PRESET_MODE, PRESET_NONE ) from homeassistant.const import ( ATTR_ENTITY_ID, STATE_ON, ATTR_TEMPERATURE, TEMP_FAHRENHEIT) @@ -49,6 +49,7 @@ PRESET_TO_ECOBEE_HOLD = { } PRESET_MODES = [ + PRESET_NONE, PRESET_AWAY, PRESET_HOME, PRESET_SLEEP @@ -331,7 +332,7 @@ class Thermostat(ClimateDevice): self.thermostat_index, PRESET_TO_ECOBEE_HOLD[preset_mode], self.hold_preference()) - elif preset_mode is None: + elif preset_mode is PRESET_NONE: self.data.ecobee.resume_program(self.thermostat_index) else: diff --git a/homeassistant/components/eq3btsmart/climate.py b/homeassistant/components/eq3btsmart/climate.py index 6a9d65b3883..90b6b7e134e 100644 --- a/homeassistant/components/eq3btsmart/climate.py +++ b/homeassistant/components/eq3btsmart/climate.py @@ -7,7 +7,7 @@ import voluptuous as vol from homeassistant.components.climate import PLATFORM_SCHEMA, ClimateDevice from homeassistant.components.climate.const import ( HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_AWAY, PRESET_BOOST, - SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE) + SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, PRESET_NONE) from homeassistant.const import ( ATTR_TEMPERATURE, CONF_DEVICES, CONF_MAC, PRECISION_HALVES, TEMP_CELSIUS) import homeassistant.helpers.config_validation as cv @@ -181,7 +181,7 @@ class EQ3BTSmartThermostat(ClimateDevice): def set_preset_mode(self, preset_mode): """Set new preset mode.""" - if not preset_mode: + if preset_mode == PRESET_NONE: self.set_hvac_mode(HVAC_MODE_HEAT) self._thermostat.mode = HA_TO_EQ_PRESET[preset_mode] diff --git a/homeassistant/components/evohome/climate.py b/homeassistant/components/evohome/climate.py index 540675d7ef4..a953c2e3244 100644 --- a/homeassistant/components/evohome/climate.py +++ b/homeassistant/components/evohome/climate.py @@ -10,7 +10,7 @@ from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( HVAC_MODE_HEAT, HVAC_MODE_AUTO, HVAC_MODE_OFF, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF, - PRESET_AWAY, PRESET_ECO, PRESET_HOME, + PRESET_AWAY, PRESET_ECO, PRESET_HOME, PRESET_NONE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_PRESET_MODE) from homeassistant.const import PRECISION_TENTHS from homeassistant.util.dt import parse_datetime @@ -40,12 +40,11 @@ HA_PRESET_TO_TCS = { TCS_PRESET_TO_HA = {v: k for k, v in HA_PRESET_TO_TCS.items()} EVO_PRESET_TO_HA = { - EVO_FOLLOW: None, + EVO_FOLLOW: PRESET_NONE, EVO_TEMPOVER: 'temporary', EVO_PERMOVER: 'permanent', } -HA_PRESET_TO_EVO = {v: k for k, v in EVO_PRESET_TO_HA.items() - if v is not None} +HA_PRESET_TO_EVO = {v: k for k, v in EVO_PRESET_TO_HA.items()} def setup_platform(hass, hass_config, add_entities, diff --git a/homeassistant/components/generic_thermostat/climate.py b/homeassistant/components/generic_thermostat/climate.py index ba18d9de936..409c44d1bca 100644 --- a/homeassistant/components/generic_thermostat/climate.py +++ b/homeassistant/components/generic_thermostat/climate.py @@ -8,7 +8,7 @@ from homeassistant.components.climate import PLATFORM_SCHEMA, ClimateDevice from homeassistant.components.climate.const import ( ATTR_PRESET_MODE, CURRENT_HVAC_COOL, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, - PRESET_AWAY, SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE) + PRESET_AWAY, SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, PRESET_NONE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_TEMPERATURE, CONF_NAME, EVENT_HOMEASSISTANT_START, PRECISION_HALVES, PRECISION_TENTHS, PRECISION_WHOLE, SERVICE_TURN_OFF, @@ -251,7 +251,7 @@ class GenericThermostat(ClimateDevice, RestoreEntity): def preset_modes(self): """Return a list of available preset modes.""" if self._away_temp: - return [PRESET_AWAY] + return [PRESET_NONE, PRESET_AWAY] return None async def async_set_hvac_mode(self, hvac_mode): @@ -404,7 +404,7 @@ class GenericThermostat(ClimateDevice, RestoreEntity): self._saved_target_temp = self._target_temp self._target_temp = self._away_temp await self._async_control_heating(force=True) - elif not preset_mode and self._is_away: + elif preset_mode == PRESET_NONE and self._is_away: self._is_away = False self._target_temp = self._saved_target_temp await self._async_control_heating(force=True) diff --git a/homeassistant/components/hive/climate.py b/homeassistant/components/hive/climate.py index bfc43e3357f..dd7e0164367 100644 --- a/homeassistant/components/hive/climate.py +++ b/homeassistant/components/hive/climate.py @@ -2,7 +2,7 @@ from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_BOOST, - SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE) + SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, PRESET_NONE) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS from . import DATA_HIVE, DOMAIN @@ -21,7 +21,7 @@ HASS_TO_HIVE_STATE = { SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE SUPPORT_HVAC = [HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF] -SUPPORT_PRESET = [PRESET_BOOST] +SUPPORT_PRESET = [PRESET_NONE, PRESET_BOOST] def setup_platform(hass, config, add_entities, discovery_info=None): @@ -168,7 +168,7 @@ class HiveClimateEntity(ClimateDevice): def set_preset_mode(self, preset_mode) -> None: """Set new preset mode.""" - if preset_mode is None and self.preset_mode == PRESET_BOOST: + if preset_mode == PRESET_NONE and self.preset_mode == PRESET_BOOST: self.session.heating.turn_boost_off(self.node_id) elif preset_mode == PRESET_BOOST: diff --git a/homeassistant/components/homematicip_cloud/climate.py b/homeassistant/components/homematicip_cloud/climate.py index 56cab03396e..44f0c148a41 100644 --- a/homeassistant/components/homematicip_cloud/climate.py +++ b/homeassistant/components/homematicip_cloud/climate.py @@ -10,7 +10,7 @@ from homematicip.aio.home import AsyncHome from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( HVAC_MODE_AUTO, HVAC_MODE_HEAT, PRESET_BOOST, PRESET_ECO, - SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE) + SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, PRESET_NONE) from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS from homeassistant.core import HomeAssistant @@ -121,7 +121,7 @@ class HomematicipHeatingGroup(HomematicipGenericDevice, ClimateDevice): Requires SUPPORT_PRESET_MODE. """ - return [PRESET_BOOST] + return [PRESET_NONE, PRESET_BOOST] @property def min_temp(self) -> float: diff --git a/homeassistant/components/honeywell/climate.py b/homeassistant/components/honeywell/climate.py index 8d0a3602d02..4f3adaf4b2e 100644 --- a/homeassistant/components/honeywell/climate.py +++ b/homeassistant/components/honeywell/climate.py @@ -15,7 +15,7 @@ from homeassistant.components.climate.const import ( SUPPORT_TARGET_HUMIDITY, SUPPORT_TARGET_TEMPERATURE_RANGE, CURRENT_HVAC_COOL, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF, HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL, - PRESET_AWAY, + PRESET_AWAY, PRESET_NONE, ) from homeassistant.const import ( CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT, @@ -229,7 +229,7 @@ class HoneywellUSThermostat(ClimateDevice): @property def preset_modes(self) -> Optional[List[str]]: """Return a list of available preset modes.""" - return [PRESET_AWAY] + return [PRESET_NONE, PRESET_AWAY] @property def is_aux_heat(self) -> Optional[str]: diff --git a/homeassistant/components/mqtt/climate.py b/homeassistant/components/mqtt/climate.py index b70ffa80145..4106ce6fa3b 100644 --- a/homeassistant/components/mqtt/climate.py +++ b/homeassistant/components/mqtt/climate.py @@ -12,7 +12,7 @@ from homeassistant.components.climate.const import ( HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_HEAT, HVAC_MODE_OFF, SUPPORT_AUX_HEAT, SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, PRESET_AWAY, - SUPPORT_TARGET_TEMPERATURE_RANGE) + SUPPORT_TARGET_TEMPERATURE_RANGE, PRESET_NONE) from homeassistant.components.fan import SPEED_HIGH, SPEED_LOW, SPEED_MEDIUM from homeassistant.const import ( ATTR_TEMPERATURE, CONF_DEVICE, CONF_NAME, CONF_VALUE_TEMPLATE, STATE_ON) @@ -538,6 +538,9 @@ class MqttClimate(MqttAttributes, MqttAvailability, MqttDiscoveryUpdate, presets.extend(self._config[CONF_HOLD_LIST]) + if presets: + presets.insert(0, PRESET_NONE) + return presets @property diff --git a/homeassistant/components/nest/climate.py b/homeassistant/components/nest/climate.py index 5dd1db52650..63d91cbc829 100644 --- a/homeassistant/components/nest/climate.py +++ b/homeassistant/components/nest/climate.py @@ -8,7 +8,7 @@ from homeassistant.components.climate.const import ( ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, FAN_AUTO, FAN_ON, HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, SUPPORT_PRESET_MODE, SUPPORT_FAN_MODE, SUPPORT_TARGET_TEMPERATURE, - SUPPORT_TARGET_TEMPERATURE_RANGE, PRESET_AWAY, PRESET_ECO) + SUPPORT_TARGET_TEMPERATURE_RANGE, PRESET_AWAY, PRESET_ECO, PRESET_NONE) from homeassistant.const import ( ATTR_TEMPERATURE, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT) from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -28,7 +28,7 @@ NEST_MODE_HEAT = 'heat' NEST_MODE_COOL = 'cool' NEST_MODE_OFF = 'off' -PRESET_MODES = [PRESET_AWAY, PRESET_ECO] +PRESET_MODES = [PRESET_NONE, PRESET_AWAY, PRESET_ECO] def setup_platform(hass, config, add_entities, discovery_info=None): diff --git a/homeassistant/components/nuheat/climate.py b/homeassistant/components/nuheat/climate.py index dcc85b1a814..e53b60d1ca1 100644 --- a/homeassistant/components/nuheat/climate.py +++ b/homeassistant/components/nuheat/climate.py @@ -7,7 +7,7 @@ import voluptuous as vol from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF, SUPPORT_PRESET_MODE, - SUPPORT_TARGET_TEMPERATURE) + SUPPORT_TARGET_TEMPERATURE, PRESET_NONE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT) import homeassistant.helpers.config_validation as cv @@ -157,6 +157,7 @@ class NuHeatThermostat(ClimateDevice): def preset_modes(self): """Return available preset modes.""" return [ + PRESET_NONE, MODE_HOLD_TEMPERATURE, MODE_TEMPORARY_HOLD ] @@ -173,7 +174,7 @@ class NuHeatThermostat(ClimateDevice): def set_preset_mode(self, preset_mode): """Update the hold mode of the thermostat.""" - if preset_mode is None: + if preset_mode == PRESET_NONE: schedule_mode = SCHEDULE_RUN elif preset_mode == MODE_HOLD_TEMPERATURE: diff --git a/homeassistant/components/opentherm_gw/climate.py b/homeassistant/components/opentherm_gw/climate.py index d0b706cdad8..db6dfd33c91 100644 --- a/homeassistant/components/opentherm_gw/climate.py +++ b/homeassistant/components/opentherm_gw/climate.py @@ -170,7 +170,7 @@ class OpenThermClimate(ClimateDevice): @property def preset_modes(self): """Available preset modes to set.""" - return [PRESET_AWAY] + return [] def set_preset_mode(self, preset_mode): """Set the preset mode.""" diff --git a/homeassistant/components/toon/climate.py b/homeassistant/components/toon/climate.py index d8c2f0ad5ee..2ce0ed954b8 100644 --- a/homeassistant/components/toon/climate.py +++ b/homeassistant/components/toon/climate.py @@ -130,9 +130,8 @@ class ToonThermostatDevice(ToonDisplayDeviceEntity, ClimateDevice): def set_preset_mode(self, preset_mode: str) -> None: """Set new preset mode.""" - if preset_mode is not None: - self._client.thermostat_state = self._preset = preset_mode - self.schedule_update_ha_state() + self._client.thermostat_state = self._preset = preset_mode + self.schedule_update_ha_state() def set_hvac_mode(self, hvac_mode: str) -> None: """Set new target hvac mode.""" diff --git a/homeassistant/components/venstar/climate.py b/homeassistant/components/venstar/climate.py index de7894059d4..7d3fc9e59a1 100644 --- a/homeassistant/components/venstar/climate.py +++ b/homeassistant/components/venstar/climate.py @@ -8,7 +8,7 @@ from homeassistant.components.climate.const import ( ATTR_HVAC_MODE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT, SUPPORT_FAN_MODE, SUPPORT_TARGET_HUMIDITY, SUPPORT_PRESET_MODE, - SUPPORT_TARGET_TEMPERATURE, PRESET_AWAY, + SUPPORT_TARGET_TEMPERATURE, PRESET_AWAY, PRESET_NONE, SUPPORT_TARGET_TEMPERATURE_RANGE, HVAC_MODE_OFF) from homeassistant.const import ( @@ -213,6 +213,7 @@ class VenstarThermostat(ClimateDevice): def preset_modes(self): """Return valid preset modes.""" return [ + PRESET_NONE, PRESET_AWAY, HOLD_MODE_TEMPERATURE, ] @@ -286,7 +287,7 @@ class VenstarThermostat(ClimateDevice): success = self._client.set_away(self._client.AWAY_AWAY) elif preset_mode == HOLD_MODE_TEMPERATURE: success = self._client.set_schedule(0) - elif preset_mode is None: + elif preset_mode == PRESET_NONE: success = False if self._client.away: success = self._client.set_away(self._client.AWAY_HOME) diff --git a/homeassistant/components/wink/climate.py b/homeassistant/components/wink/climate.py index 0a27db396b5..9d7893eefc7 100644 --- a/homeassistant/components/wink/climate.py +++ b/homeassistant/components/wink/climate.py @@ -10,7 +10,7 @@ from homeassistant.components.climate.const import ( FAN_LOW, FAN_MEDIUM, FAN_ON, HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_FAN_ONLY, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_AWAY, PRESET_ECO, SUPPORT_AUX_HEAT, SUPPORT_FAN_MODE, SUPPORT_TARGET_TEMPERATURE, - SUPPORT_TARGET_TEMPERATURE_RANGE) + SUPPORT_TARGET_TEMPERATURE_RANGE, PRESET_NONE) from homeassistant.const import ( ATTR_TEMPERATURE, PRECISION_TENTHS, TEMP_CELSIUS) from homeassistant.helpers.temperature import display_temp as show_temp @@ -44,7 +44,7 @@ SUPPORT_PRESET_THERMOSTAT = [PRESET_AWAY, PRESET_ECO] SUPPORT_FLAGS_AC = SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE SUPPORT_FAN_AC = [FAN_HIGH, FAN_LOW, FAN_MEDIUM] -SUPPORT_PRESET_AC = [PRESET_ECO] +SUPPORT_PRESET_AC = [PRESET_NONE, PRESET_ECO] def setup_platform(hass, config, add_entities, discovery_info=None): diff --git a/tests/components/generic_thermostat/test_climate.py b/tests/components/generic_thermostat/test_climate.py index 46bd021b877..c7d73b02cbf 100644 --- a/tests/components/generic_thermostat/test_climate.py +++ b/tests/components/generic_thermostat/test_climate.py @@ -9,7 +9,7 @@ import voluptuous as vol from homeassistant.components import input_boolean, switch from homeassistant.components.climate.const import ( ATTR_PRESET_MODE, DOMAIN, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, - PRESET_AWAY) + PRESET_AWAY, PRESET_NONE) from homeassistant.const import ( ATTR_TEMPERATURE, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_OFF, STATE_ON, TEMP_CELSIUS, TEMP_FAHRENHEIT) @@ -202,7 +202,7 @@ async def test_set_away_mode_and_restore_prev_temp(hass, setup_comp_2): await common.async_set_preset_mode(hass, PRESET_AWAY) state = hass.states.get(ENTITY) assert 16 == state.attributes.get('temperature') - await common.async_set_preset_mode(hass, None) + await common.async_set_preset_mode(hass, PRESET_NONE) state = hass.states.get(ENTITY) assert 23 == state.attributes.get('temperature') @@ -217,7 +217,7 @@ async def test_set_away_mode_twice_and_restore_prev_temp(hass, setup_comp_2): await common.async_set_preset_mode(hass, PRESET_AWAY) state = hass.states.get(ENTITY) assert 16 == state.attributes.get('temperature') - await common.async_set_preset_mode(hass, None) + await common.async_set_preset_mode(hass, PRESET_NONE) state = hass.states.get(ENTITY) assert 23 == state.attributes.get('temperature') diff --git a/tests/components/mqtt/test_climate.py b/tests/components/mqtt/test_climate.py index 6792675f594..407285b116f 100644 --- a/tests/components/mqtt/test_climate.py +++ b/tests/components/mqtt/test_climate.py @@ -16,7 +16,7 @@ from homeassistant.components.climate.const import ( SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, - SUPPORT_TARGET_TEMPERATURE_RANGE) + SUPPORT_TARGET_TEMPERATURE_RANGE, PRESET_NONE) from homeassistant.components.mqtt.discovery import async_start from homeassistant.const import STATE_OFF, STATE_UNAVAILABLE @@ -425,7 +425,7 @@ async def test_set_away_mode(hass, mqtt_mock): state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('preset_mode') == 'away' - await common.async_set_preset_mode(hass, None, ENTITY_CLIMATE) + await common.async_set_preset_mode(hass, PRESET_NONE, ENTITY_CLIMATE) mqtt_mock.async_publish.assert_called_once_with( 'away-mode-topic', 'AUS', 0, False) state = hass.states.get(ENTITY_CLIMATE) @@ -467,7 +467,7 @@ async def test_set_hold(hass, mqtt_mock): state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('preset_mode') == 'hold-on' - await common.async_set_preset_mode(hass, None, ENTITY_CLIMATE) + await common.async_set_preset_mode(hass, PRESET_NONE, ENTITY_CLIMATE) mqtt_mock.async_publish.assert_called_once_with( 'hold-topic', 'off', 0, False) state = hass.states.get(ENTITY_CLIMATE) From a3043b9a90d23eeba4a3e752aeb917dd83afbaa4 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Sun, 21 Jul 2019 13:02:22 -0400 Subject: [PATCH 12/17] bump quirks version (#25362) --- homeassistant/components/zha/manifest.json | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index e9e6d46cd6a..95374b17ed1 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -5,7 +5,7 @@ "documentation": "https://www.home-assistant.io/components/zha", "requirements": [ "bellows-homeassistant==0.8.2", - "zha-quirks==0.0.18", + "zha-quirks==0.0.19", "zigpy-deconz==0.2.1", "zigpy-homeassistant==0.7.0", "zigpy-xbee-homeassistant==0.4.0" diff --git a/requirements_all.txt b/requirements_all.txt index 14c1c03eb5d..e6c23917b24 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1939,7 +1939,7 @@ zengge==0.2 zeroconf==0.23.0 # homeassistant.components.zha -zha-quirks==0.0.18 +zha-quirks==0.0.19 # homeassistant.components.zhong_hong zhong_hong_hvac==1.0.9 From 0eab89c8f491c23a2e71d045d8d9d9bea8845060 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sun, 21 Jul 2019 19:01:16 +0200 Subject: [PATCH 13/17] Fix ESPHome climate migration (#25366) --- homeassistant/components/esphome/climate.py | 32 +++++++++------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/esphome/climate.py b/homeassistant/components/esphome/climate.py index 2892342ac59..d4cc7940768 100644 --- a/homeassistant/components/esphome/climate.py +++ b/homeassistant/components/esphome/climate.py @@ -76,6 +76,11 @@ class EsphomeClimateDevice(EsphomeEntity, ClimateDevice): for mode in self._static_info.supported_modes ] + @property + def preset_modes(self): + """Return preset modes.""" + return [PRESET_AWAY] if self._static_info.supports_away else [] + @property def target_temperature_step(self) -> float: """Return the supported step of target temperature.""" @@ -97,7 +102,7 @@ class EsphomeClimateDevice(EsphomeEntity, ClimateDevice): """Return the list of supported features.""" features = 0 if self._static_info.supports_two_point_target_temperature: - features |= (SUPPORT_TARGET_TEMPERATURE_RANGE) + features |= SUPPORT_TARGET_TEMPERATURE_RANGE else: features |= SUPPORT_TARGET_TEMPERATURE if self._static_info.supports_away: @@ -109,6 +114,11 @@ class EsphomeClimateDevice(EsphomeEntity, ClimateDevice): """Return current operation ie. heat, cool, idle.""" return _climate_modes.from_esphome(self._state.mode) + @esphome_state_property + def preset_mode(self): + """Return current preset mode.""" + return PRESET_AWAY if self._state.away else None + @esphome_state_property def current_temperature(self) -> Optional[float]: """Return the current temperature.""" @@ -143,29 +153,13 @@ class EsphomeClimateDevice(EsphomeEntity, ClimateDevice): data['target_temperature_high'] = kwargs[ATTR_TARGET_TEMP_HIGH] await self._client.climate_command(**data) - async def async_set_operation_mode(self, operation_mode) -> None: + async def async_set_hvac_mode(self, hvac_mode: str) -> None: """Set new target operation mode.""" await self._client.climate_command( key=self._static_info.key, - mode=_climate_modes.from_hass(operation_mode), + mode=_climate_modes.from_hass(hvac_mode), ) - @property - def preset_mode(self): - """Return current preset mode.""" - if self._state and self._state.away: - return PRESET_AWAY - - return None - - @property - def preset_modes(self): - """Return preset modes.""" - if self._static_info.supports_away: - return [PRESET_AWAY] - - return [] - async def async_set_preset_mode(self, preset_mode): """Set preset mode.""" away = preset_mode == PRESET_AWAY From 35c719628da49081c8e96c5a8a183010b067bebb Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Sun, 21 Jul 2019 13:00:27 -0400 Subject: [PATCH 14/17] fix remove and re-add scenario (#25370) --- homeassistant/components/zha/core/gateway.py | 7 +++++++ homeassistant/components/zha/entity.py | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/zha/core/gateway.py b/homeassistant/components/zha/core/gateway.py index 351ad1c5a67..20bf30dec87 100644 --- a/homeassistant/components/zha/core/gateway.py +++ b/homeassistant/components/zha/core/gateway.py @@ -190,6 +190,13 @@ class ZHAGateway: if entity_id == entity_reference.reference_id: return entity_reference + def remove_entity_reference(self, entity): + """Remove entity reference for given entity_id if found.""" + if entity.zha_device.ieee in self.device_registry: + entity_refs = self.device_registry.get(entity.zha_device.ieee) + self.device_registry[entity.zha_device.ieee] = [ + e for e in entity_refs if e.reference_id != entity.entity_id] + @property def devices(self): """Return devices.""" diff --git a/homeassistant/components/zha/entity.py b/homeassistant/components/zha/entity.py index a854a5c9a6e..77cb5b8deda 100644 --- a/homeassistant/components/zha/entity.py +++ b/homeassistant/components/zha/entity.py @@ -50,7 +50,7 @@ class ZhaEntity(RestoreEntity, entity.Entity): self._available = False self._component = kwargs['component'] self._unsubs = [] - self.remove_future = asyncio.Future() + self.remove_future = None for channel in channels: self.cluster_channels[channel.name] = channel @@ -123,6 +123,7 @@ class ZhaEntity(RestoreEntity, entity.Entity): async def async_added_to_hass(self): """Run when about to be added to hass.""" await super().async_added_to_hass() + self.remove_future = asyncio.Future() await self.async_check_recently_seen() await self.async_accept_signal( None, "{}_{}".format(self.zha_device.available_signal, 'entity'), @@ -151,8 +152,10 @@ class ZhaEntity(RestoreEntity, entity.Entity): async def async_will_remove_from_hass(self) -> None: """Disconnect entity object when removed.""" - for unsub in self._unsubs: + for unsub in self._unsubs[:]: unsub() + self._unsubs.remove(unsub) + self.zha_device.gateway.remove_entity_reference(self) self.remove_future.set_result(True) @callback From 8538e69e286ec446f5690e4d7ab2bb79972a1978 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Sun, 21 Jul 2019 12:57:40 -0400 Subject: [PATCH 15/17] change and condition to or condition (#25374) --- homeassistant/helpers/entity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 762e6813b1d..f039cc315e3 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -433,7 +433,7 @@ class Entity: async def _async_registry_updated(self, event): """Handle entity registry update.""" data = event.data - if data['action'] != 'update' and data.get( + if data['action'] != 'update' or data.get( 'old_entity_id', data['entity_id']) != self.entity_id: return From 15064e83b4ad5bf0a51c851cb4bee82477605a2a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 21 Jul 2019 11:10:36 -0700 Subject: [PATCH 16/17] Bumped version to 0.96.3 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 623c07f39bf..9198e4a3942 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 96 -PATCH_VERSION = '2' +PATCH_VERSION = '3' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 5, 3) From 2189cb0ee7117da88ab3df4aff382a8b900f3ac7 Mon Sep 17 00:00:00 2001 From: cgtobi Date: Mon, 15 Jul 2019 09:46:48 +0200 Subject: [PATCH 17/17] Add Netatmo climate battery level (#25143) * Add battery level sensor * Only update battery level if lower or nonexistent --- homeassistant/components/netatmo/climate.py | 29 ++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/netatmo/climate.py b/homeassistant/components/netatmo/climate.py index 48592dea9c9..668d3056c81 100644 --- a/homeassistant/components/netatmo/climate.py +++ b/homeassistant/components/netatmo/climate.py @@ -16,7 +16,9 @@ from homeassistant.components.climate.const import ( DEFAULT_MIN_TEMP ) from homeassistant.const import ( - TEMP_CELSIUS, ATTR_TEMPERATURE, CONF_NAME, PRECISION_HALVES, STATE_OFF) + TEMP_CELSIUS, ATTR_TEMPERATURE, CONF_NAME, PRECISION_HALVES, STATE_OFF, + ATTR_BATTERY_LEVEL +) from homeassistant.util import Throttle from .const import DATA_NETATMO_AUTH @@ -153,6 +155,7 @@ class NetatmoThermostat(ClimateDevice): self._operation_list = [HVAC_MODE_AUTO, HVAC_MODE_HEAT] self._support_flags = SUPPORT_FLAGS self._hvac_mode = None + self._battery_level = None self.update_without_throttle = False self._module_type = \ self._data.room_status.get(room_id, {}).get('module_type') @@ -287,6 +290,16 @@ class NetatmoThermostat(ClimateDevice): self.update_without_throttle = True self.schedule_update_ha_state() + @property + def device_state_attributes(self): + """Return the state attributes of the thermostat.""" + attr = {} + + if self._battery_level is not None: + attr[ATTR_BATTERY_LEVEL] = self._battery_level + + return attr + def update(self): """Get the latest data from NetAtmo API and updates the states.""" try: @@ -439,6 +452,7 @@ class ThermostatData: roomstatus["module_id"] = None roomstatus["heating_status"] = None roomstatus["heating_power_request"] = None + batterylevel = None for module_id in homedata_room["module_ids"]: if (self.homedata.modules[self.home][module_id]["type"] == NA_THERM @@ -449,6 +463,10 @@ class ThermostatData: rid=roomstatus["module_id"] ) roomstatus["heating_status"] = self.boilerstatus + batterylevel = ( + self.homestatus + .thermostats[roomstatus["module_id"]] + .get("battery_level")) elif roomstatus["module_type"] == NA_VALVE: roomstatus["heating_power_request"] = homestatus_room[ "heating_power_request" @@ -461,6 +479,15 @@ class ThermostatData: self.boilerstatus and roomstatus["heating_status"] ) + batterylevel = ( + self.homestatus.valves[roomstatus["module_id"]] + .get("battery_level")) + + if batterylevel: + if roomstatus.get("battery_level") is None: + roomstatus["battery_level"] = batterylevel + elif batterylevel < roomstatus["battery_level"]: + roomstatus["battery_level"] = batterylevel self.room_status[room] = roomstatus except KeyError as err: _LOGGER.error("Update of room %s failed. Error: %s", room, err)