From da9430ed12314e1463ac322fa2ddecc1d6f24deb Mon Sep 17 00:00:00 2001 From: Wolfgang Malgadey Date: Fri, 23 Jun 2017 18:45:44 +0200 Subject: [PATCH] Tado climate device (#8041) * added default parameter * zone overlay can be set with or without a temperature and with or without a duration. Duration is not supported by hass * Fixes issue #7059 with missing sensorDataPoints * Fixes issue #6943 added ac_mode * ac_mode cases * added fan modes * changed handling of device state OFF * fixed an error initializing a dictionary (#6943) * changed pytado version * activated pytado debugging * Changed pyTado version * mytado.com changed authentication challenge * Fixed linelength and whitespace issues * requirements to pytado changed --- homeassistant/components/climate/tado.py | 114 ++++++++++++++++------- homeassistant/components/tado.py | 5 +- requirements_all.txt | 2 +- 3 files changed, 85 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/climate/tado.py b/homeassistant/components/climate/tado.py index af9ad44fd7eb62..832bca6f9b6200 100644 --- a/homeassistant/components/climate/tado.py +++ b/homeassistant/components/climate/tado.py @@ -24,6 +24,17 @@ # the temperature will be reset after a timespan CONST_OVERLAY_TIMER = 'TIMER' +CONST_MODE_FAN_HIGH = 'HIGH' +CONST_MODE_FAN_MIDDLE = 'MIDDLE' +CONST_MODE_FAN_LOW = 'LOW' + +FAN_MODES_LIST = { + CONST_MODE_FAN_HIGH: 'High', + CONST_MODE_FAN_MIDDLE: 'Middle', + CONST_MODE_FAN_LOW: 'Low', + CONST_MODE_OFF: 'Off', +} + OPERATION_LIST = { CONST_OVERLAY_MANUAL: 'Manual', CONST_OVERLAY_TIMER: 'Timer', @@ -60,9 +71,15 @@ def create_climate_device(tado, hass, zone, name, zone_id): capabilities = tado.get_capabilities(zone_id) unit = TEMP_CELSIUS - min_temp = float(capabilities['temperatures']['celsius']['min']) - max_temp = float(capabilities['temperatures']['celsius']['max']) - ac_mode = capabilities['type'] != 'HEATING' + ac_mode = capabilities['type'] == 'AIR_CONDITIONING' + + if ac_mode: + temperatures = capabilities['HEAT']['temperatures'] + else: + temperatures = capabilities['temperatures'] + + min_temp = float(temperatures['celsius']['min']) + max_temp = float(temperatures['celsius']['max']) data_id = 'zone {} {}'.format(name, zone_id) device = TadoClimate(tado, @@ -107,7 +124,9 @@ def __init__(self, store, zone_name, zone_id, data_id, self._max_temp = max_temp self._target_temp = None self._tolerance = tolerance + self._cooling = False + self._current_fan = CONST_MODE_OFF self._current_operation = CONST_MODE_SMART_SCHEDULE self._overlay_mode = CONST_MODE_SMART_SCHEDULE @@ -129,13 +148,32 @@ def current_temperature(self): @property def current_operation(self): """Return current readable operation mode.""" - return OPERATION_LIST.get(self._current_operation) + if self._cooling: + return "Cooling" + else: + return OPERATION_LIST.get(self._current_operation) @property def operation_list(self): """Return the list of available operation modes (readable).""" return list(OPERATION_LIST.values()) + @property + def current_fan_mode(self): + """Return the fan setting.""" + if self.ac_mode: + return FAN_MODES_LIST.get(self._current_fan) + else: + return None + + @property + def fan_list(self): + """List of available fan modes.""" + if self.ac_mode: + return list(FAN_MODES_LIST.values()) + else: + return None + @property def temperature_unit(self): """Return the unit of measurement used by the platform.""" @@ -205,27 +243,27 @@ def update(self): if 'sensorDataPoints' in data: sensor_data = data['sensorDataPoints'] - temperature = float( - sensor_data['insideTemperature']['celsius']) - humidity = float( - sensor_data['humidity']['percentage']) - setting = 0 + + unit = TEMP_CELSIUS + + if 'insideTemperature' in sensor_data: + temperature = float( + sensor_data['insideTemperature']['celsius']) + self._cur_temp = self.hass.config.units.temperature( + temperature, unit) + + if 'humidity' in sensor_data: + humidity = float( + sensor_data['humidity']['percentage']) + self._cur_humidity = humidity # temperature setting will not exist when device is off if 'temperature' in data['setting'] and \ data['setting']['temperature'] is not None: setting = float( data['setting']['temperature']['celsius']) - - unit = TEMP_CELSIUS - - self._cur_temp = self.hass.config.units.temperature( - temperature, unit) - - self._target_temp = self.hass.config.units.temperature( - setting, unit) - - self._cur_humidity = humidity + self._target_temp = self.hass.config.units.temperature( + setting, unit) if 'tadoMode' in data: mode = data['tadoMode'] @@ -235,29 +273,39 @@ def update(self): power = data['setting']['power'] if power == 'OFF': self._current_operation = CONST_MODE_OFF + self._current_fan = CONST_MODE_OFF + # There is no overlay, the mode will always be + # "SMART_SCHEDULE" + self._overlay_mode = CONST_MODE_SMART_SCHEDULE self._device_is_active = False else: self._device_is_active = True - if 'overlay' in data and data['overlay'] is not None: - overlay = True - termination = data['overlay']['termination']['type'] - else: + if self._device_is_active: overlay = False - termination = "" + overlay_data = None + termination = self._current_operation + cooling = False + fan_speed = CONST_MODE_OFF + + if 'overlay' in data: + overlay_data = data['overlay'] + overlay = overlay_data is not None - # If you set mode manualy to off, there will be an overlay - # and a termination, but we want to see the mode "OFF" + if overlay: + termination = overlay_data['termination']['type'] + + if 'setting' in overlay_data: + cooling = overlay_data['setting']['mode'] == 'COOL' + fan_speed = overlay_data['setting']['fanSpeed'] + + # If you set mode manualy to off, there will be an overlay + # and a termination, but we want to see the mode "OFF" - if overlay and self._device_is_active: - # There is an overlay the device is on self._overlay_mode = termination self._current_operation = termination - else: - # There is no overlay, the mode will always be - # "SMART_SCHEDULE" - self._overlay_mode = CONST_MODE_SMART_SCHEDULE - self._current_operation = CONST_MODE_SMART_SCHEDULE + self._cooling = cooling + self._current_fan = fan_speed def _control_heating(self): """Send new target temperature to mytado.""" diff --git a/homeassistant/components/tado.py b/homeassistant/components/tado.py index a465119dc2d03a..24712fa2fbe76a 100644 --- a/homeassistant/components/tado.py +++ b/homeassistant/components/tado.py @@ -16,8 +16,8 @@ from homeassistant.util import Throttle REQUIREMENTS = ['https://github.com/wmalgadey/PyTado/archive/' - '0.1.10.zip#' - 'PyTado==0.1.10'] + '0.2.1.zip#' + 'PyTado==0.2.1'] _LOGGER = logging.getLogger(__name__) @@ -47,6 +47,7 @@ def setup(hass, config): try: tado = Tado(username, password) + tado.setDebugging(True) except (RuntimeError, urllib.error.HTTPError): _LOGGER.error("Unable to connect to mytado with username and password") return False diff --git a/requirements_all.txt b/requirements_all.txt index 5c6902a86bdb07..3e4c6e0ff4e2ab 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -307,7 +307,7 @@ https://github.com/soldag/pyflic/archive/0.4.zip#pyflic==0.4 https://github.com/tfriedel/python-lightify/archive/1bb1db0e7bd5b14304d7bb267e2398cd5160df46.zip#lightify==1.0.5 # homeassistant.components.tado -https://github.com/wmalgadey/PyTado/archive/0.1.10.zip#PyTado==0.1.10 +https://github.com/wmalgadey/PyTado/archive/0.2.1.zip#PyTado==0.2.1 # homeassistant.components.media_player.lg_netcast https://github.com/wokar/pylgnetcast/archive/v0.2.0.zip#pylgnetcast==0.2.0