diff --git a/homeassistant/components/tado/__init__.py b/homeassistant/components/tado/__init__.py index 3cb2abe90f6..7a1965e31fb 100644 --- a/homeassistant/components/tado/__init__.py +++ b/homeassistant/components/tado/__init__.py @@ -3,6 +3,7 @@ from datetime import timedelta import logging from PyTado.interface import Tado +from PyTado.zone import TadoZone from requests import RequestException import requests.exceptions @@ -155,52 +156,96 @@ class TadoConnector: @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Update the registered zones.""" - for device in self.devices: - self.update_sensor("device", device["shortSerialNo"]) - for zone in self.zones: - self.update_sensor("zone", zone["id"]) + self.update_devices() + self.update_zones() self.data["weather"] = self.tado.getWeather() dispatcher_send( self.hass, SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, "weather", "data"), ) - def update_sensor(self, sensor_type, sensor): - """Update the internal data from Tado.""" - _LOGGER.debug("Updating %s %s", sensor_type, sensor) - try: - if sensor_type == "device": - data = self.tado.getDeviceInfo(sensor) + def update_devices(self): + """Update the device data from Tado.""" + devices = self.tado.getDevices() + for device in devices: + device_short_serial_no = device["shortSerialNo"] + _LOGGER.debug("Updating device %s", device_short_serial_no) + try: if ( INSIDE_TEMPERATURE_MEASUREMENT - in data["characteristics"]["capabilities"] + in device["characteristics"]["capabilities"] ): - data[TEMP_OFFSET] = self.tado.getDeviceInfo(sensor, TEMP_OFFSET) - elif sensor_type == "zone": - data = self.tado.getZoneState(sensor) - else: - _LOGGER.debug("Unknown sensor: %s", sensor_type) + device[TEMP_OFFSET] = self.tado.getDeviceInfo( + device_short_serial_no, TEMP_OFFSET + ) + except RuntimeError: + _LOGGER.error( + "Unable to connect to Tado while updating device %s", + device_short_serial_no, + ) return - except RuntimeError: - _LOGGER.error( - "Unable to connect to Tado while updating %s %s", - sensor_type, - sensor, + + self.data["device"][device_short_serial_no] = device + + _LOGGER.debug( + "Dispatching update to %s device %s: %s", + self.home_id, + device_short_serial_no, + device, ) + dispatcher_send( + self.hass, + SIGNAL_TADO_UPDATE_RECEIVED.format( + self.home_id, "device", device_short_serial_no + ), + ) + + def update_zones(self): + """Update the zone data from Tado.""" + try: + zone_states = self.tado.getZoneStates()["zoneStates"] + except RuntimeError: + _LOGGER.error("Unable to connect to Tado while updating zones") return - self.data[sensor_type][sensor] = data + for zone in self.zones: + zone_id = zone["id"] + _LOGGER.debug("Updating zone %s", zone_id) + zone_state = TadoZone(zone_states[str(zone_id)], zone_id) + + self.data["zone"][zone_id] = zone_state + + _LOGGER.debug( + "Dispatching update to %s zone %s: %s", + self.home_id, + zone_id, + zone_state, + ) + dispatcher_send( + self.hass, + SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, "zone", zone["id"]), + ) + + def update_zone(self, zone_id): + """Update the internal data from Tado.""" + _LOGGER.debug("Updating zone %s", zone_id) + try: + data = self.tado.getZoneState(zone_id) + except RuntimeError: + _LOGGER.error("Unable to connect to Tado while updating zone %s", zone_id) + return + + self.data["zone"][zone_id] = data _LOGGER.debug( - "Dispatching update to %s %s %s: %s", + "Dispatching update to %s zone %s: %s", self.home_id, - sensor_type, - sensor, + zone_id, data, ) dispatcher_send( self.hass, - SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, sensor_type, sensor), + SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, "zone", zone_id), ) def get_capabilities(self, zone_id): @@ -210,7 +255,7 @@ class TadoConnector: def reset_zone_overlay(self, zone_id): """Reset the zone back to the default operation.""" self.tado.resetZoneOverlay(zone_id) - self.update_sensor("zone", zone_id) + self.update_zone(zone_id) def set_presence( self, @@ -262,7 +307,7 @@ class TadoConnector: except RequestException as exc: _LOGGER.error("Could not set zone overlay: %s", exc) - self.update_sensor("zone", zone_id) + self.update_zone(zone_id) def set_zone_off(self, zone_id, overlay_mode, device_type="HEATING"): """Set a zone to off.""" @@ -273,7 +318,7 @@ class TadoConnector: except RequestException as exc: _LOGGER.error("Could not set zone overlay: %s", exc) - self.update_sensor("zone", zone_id) + self.update_zone(zone_id) def set_temperature_offset(self, device_id, offset): """Set temperature offset of device.""" diff --git a/homeassistant/components/tado/manifest.json b/homeassistant/components/tado/manifest.json index 8cf0ed260e8..a77974ab803 100644 --- a/homeassistant/components/tado/manifest.json +++ b/homeassistant/components/tado/manifest.json @@ -2,7 +2,7 @@ "domain": "tado", "name": "Tado", "documentation": "https://www.home-assistant.io/integrations/tado", - "requirements": ["python-tado==0.10.0"], + "requirements": ["python-tado==0.12.0"], "codeowners": ["@michaelarnauts", "@noltari"], "config_flow": true, "homekit": { diff --git a/requirements_all.txt b/requirements_all.txt index 986b79e278d..5b16bd0f064 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1926,7 +1926,7 @@ python-sochain-api==0.0.2 python-songpal==0.12 # homeassistant.components.tado -python-tado==0.10.0 +python-tado==0.12.0 # homeassistant.components.telegram_bot python-telegram-bot==13.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c0dff9c66d4..f9428de92d3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1107,7 +1107,7 @@ python-smarttub==0.0.25 python-songpal==0.12 # homeassistant.components.tado -python-tado==0.10.0 +python-tado==0.12.0 # homeassistant.components.twitch python-twitch-client==0.6.0 diff --git a/tests/components/tado/util.py b/tests/components/tado/util.py index ce1dd92942d..a5e23b6021a 100644 --- a/tests/components/tado/util.py +++ b/tests/components/tado/util.py @@ -20,6 +20,7 @@ async def async_init_integration( me_fixture = "tado/me.json" weather_fixture = "tado/weather.json" zones_fixture = "tado/zones.json" + zone_states_fixture = "tado/zone_states.json" # WR1 Device device_wr1_fixture = "tado/device_wr1.json" @@ -80,6 +81,10 @@ async def async_init_integration( "https://my.tado.com/api/v2/homes/1/zones", text=load_fixture(zones_fixture), ) + m.get( + "https://my.tado.com/api/v2/homes/1/zoneStates", + text=load_fixture(zone_states_fixture), + ) m.get( "https://my.tado.com/api/v2/homes/1/zones/5/capabilities", text=load_fixture(zone_5_capabilities_fixture), diff --git a/tests/fixtures/tado/zone_states.json b/tests/fixtures/tado/zone_states.json new file mode 100644 index 00000000000..c5bd0dfbe2c --- /dev/null +++ b/tests/fixtures/tado/zone_states.json @@ -0,0 +1,292 @@ +{ + "zoneStates": { + "1": { + "tadoMode": "HOME", + "geolocationOverride": false, + "geolocationOverrideDisableTime": null, + "preparation": null, + "setting": { + "type": "HEATING", + "power": "ON", + "temperature": { + "celsius": 20.50, + "fahrenheit": 68.90 + } + }, + "overlayType": "MANUAL", + "overlay": { + "type": "MANUAL", + "setting": { + "type": "HEATING", + "power": "ON", + "temperature": { + "celsius": 20.50, + "fahrenheit": 68.90 + } + }, + "termination": { + "type": "MANUAL", + "typeSkillBasedApp": "MANUAL", + "projectedExpiry": null + } + }, + "openWindow": null, + "nextScheduleChange": { + "start": "2020-03-10T17:00:00Z", + "setting": { + "type": "HEATING", + "power": "ON", + "temperature": { + "celsius": 21.00, + "fahrenheit": 69.80 + } + } + }, + "nextTimeBlock": { + "start": "2020-03-10T17:00:00.000Z" + }, + "link": { + "state": "ONLINE" + }, + "activityDataPoints": { + "heatingPower": { + "type": "PERCENTAGE", + "percentage": 0.00, + "timestamp": "2020-03-10T07:47:45.978Z" + } + }, + "sensorDataPoints": { + "insideTemperature": { + "celsius": 20.65, + "fahrenheit": 69.17, + "timestamp": "2020-03-10T07:44:11.947Z", + "type": "TEMPERATURE", + "precision": { + "celsius": 0.1, + "fahrenheit": 0.1 + } + }, + "humidity": { + "type": "PERCENTAGE", + "percentage": 45.20, + "timestamp": "2020-03-10T07:44:11.947Z" + } + } + }, + "2": { + "tadoMode": "HOME", + "geolocationOverride": false, + "geolocationOverrideDisableTime": null, + "preparation": null, + "setting": { + "type": "HOT_WATER", + "power": "ON", + "temperature": { + "celsius": 65.00, + "fahrenheit": 149.00 + } + }, + "overlayType": null, + "overlay": null, + "openWindow": null, + "nextScheduleChange": { + "start": "2020-03-10T22:00:00Z", + "setting": { + "type": "HOT_WATER", + "power": "OFF", + "temperature": null + } + }, + "nextTimeBlock": { + "start": "2020-03-10T22:00:00.000Z" + }, + "link": { + "state": "ONLINE" + }, + "activityDataPoints": {}, + "sensorDataPoints": {} + }, + "3": { + "tadoMode": "HOME", + "sensorDataPoints": { + "insideTemperature": { + "fahrenheit": 76.57, + "timestamp": "2020-03-05T03:57:38.850Z", + "celsius": 24.76, + "type": "TEMPERATURE", + "precision": { + "fahrenheit": 0.1, + "celsius": 0.1 + } + }, + "humidity": { + "timestamp": "2020-03-05T03:57:38.850Z", + "percentage": 60.9, + "type": "PERCENTAGE" + } + }, + "link": { + "state": "ONLINE" + }, + "openWindow": null, + "geolocationOverride": false, + "geolocationOverrideDisableTime": null, + "overlay": { + "termination": { + "typeSkillBasedApp": "TADO_MODE", + "projectedExpiry": null, + "type": "TADO_MODE" + }, + "setting": { + "fanSpeed": "AUTO", + "type": "AIR_CONDITIONING", + "mode": "COOL", + "power": "ON", + "temperature": { + "fahrenheit": 64.0, + "celsius": 17.78 + } + }, + "type": "MANUAL" + }, + "activityDataPoints": { + "acPower": { + "timestamp": "2020-03-05T04:01:07.162Z", + "type": "POWER", + "value": "ON" + } + }, + "nextTimeBlock": { + "start": "2020-03-05T08:00:00.000Z" + }, + "preparation": null, + "overlayType": "MANUAL", + "nextScheduleChange": null, + "setting": { + "fanSpeed": "AUTO", + "type": "AIR_CONDITIONING", + "mode": "COOL", + "power": "ON", + "temperature": { + "fahrenheit": 64.0, + "celsius": 17.78 + } + } + }, + "4": { + "activityDataPoints": {}, + "preparation": null, + "openWindow": null, + "tadoMode": "HOME", + "nextScheduleChange": { + "setting": { + "temperature": { + "fahrenheit": 149, + "celsius": 65 + }, + "type": "HOT_WATER", + "power": "ON" + }, + "start": "2020-03-26T05:00:00Z" + }, + "nextTimeBlock": { + "start": "2020-03-26T05:00:00.000Z" + }, + "overlay": { + "setting": { + "temperature": { + "celsius": 30, + "fahrenheit": 86 + }, + "type": "HOT_WATER", + "power": "ON" + }, + "termination": { + "type": "TADO_MODE", + "projectedExpiry": "2020-03-26T05:00:00Z", + "typeSkillBasedApp": "TADO_MODE" + }, + "type": "MANUAL" + }, + "geolocationOverride": false, + "geolocationOverrideDisableTime": null, + "sensorDataPoints": {}, + "overlayType": "MANUAL", + "link": { + "state": "ONLINE" + }, + "setting": { + "type": "HOT_WATER", + "temperature": { + "fahrenheit": 86, + "celsius": 30 + }, + "power": "ON" + } + }, + "5": { + "tadoMode": "HOME", + "geolocationOverride": false, + "geolocationOverrideDisableTime": null, + "preparation": null, + "setting": { + "type": "AIR_CONDITIONING", + "power": "ON", + "mode": "HEAT", + "temperature": { + "celsius": 20.00, + "fahrenheit": 68.00 + }, + "fanSpeed": "AUTO", + "swing": "ON" + }, + "overlayType": null, + "overlay": null, + "openWindow": null, + "nextScheduleChange": { + "start": "2020-03-28T04:30:00Z", + "setting": { + "type": "AIR_CONDITIONING", + "power": "ON", + "mode": "HEAT", + "temperature": { + "celsius": 23.00, + "fahrenheit": 73.40 + }, + "fanSpeed": "AUTO", + "swing": "ON" + } + }, + "nextTimeBlock": { + "start": "2020-03-28T04:30:00.000Z" + }, + "link": { + "state": "ONLINE" + }, + "activityDataPoints": { + "acPower": { + "timestamp": "2020-03-27T23:02:22.260Z", + "type": "POWER", + "value": "ON" + } + }, + "sensorDataPoints": { + "insideTemperature": { + "celsius": 20.88, + "fahrenheit": 69.58, + "timestamp": "2020-03-28T02:09:27.830Z", + "type": "TEMPERATURE", + "precision": { + "celsius": 0.1, + "fahrenheit": 0.1 + } + }, + "humidity": { + "type": "PERCENTAGE", + "percentage": 42.30, + "timestamp": "2020-03-28T02:09:27.830Z" + } + } + } + } +} \ No newline at end of file