Optimise requests to the tado servers (#56261)

This avoids calling the tado servers unnecessarily many times, especially for bigger homes. This is done by calling aggregating endpoints instead of iterating over the zones and devices and calling endpoints over and over.
This commit is contained in:
Niklas Åström 2021-09-22 14:01:30 +02:00 committed by GitHub
parent a653da137c
commit 783cc1eacd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 374 additions and 32 deletions

View File

@ -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."""

View File

@ -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": {

View File

@ -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

View File

@ -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

View File

@ -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),

292
tests/fixtures/tado/zone_states.json vendored Normal file
View File

@ -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"
}
}
}
}
}