From 0dd151c1c3e25d22182f9e24781610d6a290045c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Feb 2020 13:22:48 -0600 Subject: [PATCH] Resolve August integration makes too many requests and hits rate limits (#31558) --- homeassistant/components/august/__init__.py | 69 ++++++++++--------- .../components/august/binary_sensor.py | 2 +- homeassistant/components/august/camera.py | 2 +- homeassistant/components/august/lock.py | 9 ++- homeassistant/components/august/manifest.json | 2 +- requirements_all.txt | 2 +- 6 files changed, 46 insertions(+), 40 deletions(-) diff --git a/homeassistant/components/august/__init__.py b/homeassistant/components/august/__init__.py index 0bb0d639896..a52df5e361c 100644 --- a/homeassistant/components/august/__init__.py +++ b/homeassistant/components/august/__init__.py @@ -36,8 +36,15 @@ AUGUST_CONFIG_FILE = ".august.conf" DATA_AUGUST = "august" DOMAIN = "august" DEFAULT_ENTITY_NAMESPACE = "august" -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5) -DEFAULT_SCAN_INTERVAL = timedelta(seconds=5) + +# Limit battery and hardware updates to 1800 seconds +# in order to reduce the number of api requests and +# avoid hitting rate limits +MIN_TIME_BETWEEN_LOCK_DETAIL_UPDATES = timedelta(seconds=1800) + +DEFAULT_SCAN_INTERVAL = timedelta(seconds=10) +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10) + LOGIN_METHODS = ["phone", "email"] CONFIG_SCHEMA = vol.Schema( @@ -180,7 +187,9 @@ class AugustData: self._access_token = access_token self._doorbells = self._api.get_doorbells(self._access_token) or [] self._locks = self._api.get_operable_locks(self._access_token) or [] - self._house_ids = [d.house_id for d in self._doorbells + self._locks] + self._house_ids = set() + for device in self._doorbells + self._locks: + self._house_ids.add(device.house_id) self._doorbell_detail_by_id = {} self._lock_status_by_id = {} @@ -284,58 +293,51 @@ class AugustData: This is the status from the door sensor. """ - self._update_doors() + self._update_locks_status() return self._door_state_by_id.get(lock_id) + def _update_locks(self): + self._update_locks_status() + self._update_locks_detail() + @Throttle(MIN_TIME_BETWEEN_UPDATES) - def _update_doors(self): + def _update_locks_status(self): + status_by_id = {} state_by_id = {} - _LOGGER.debug("Start retrieving door status") + _LOGGER.debug("Start retrieving lock and door status") for lock in self._locks: - _LOGGER.debug("Updating door status for %s", lock.device_name) - + _LOGGER.debug("Updating lock and door status for %s", lock.device_name) try: - state_by_id[lock.device_id] = self._api.get_lock_door_status( - self._access_token, lock.device_id + ( + status_by_id[lock.device_id], + state_by_id[lock.device_id], + ) = self._api.get_lock_status( + self._access_token, lock.device_id, door_status=True ) except RequestException as ex: _LOGGER.error( - "Request error trying to retrieve door status for %s. %s", + "Request error trying to retrieve lock and door status for %s. %s", lock.device_name, ex, ) + status_by_id[lock.device_id] = None state_by_id[lock.device_id] = None except Exception: + status_by_id[lock.device_id] = None state_by_id[lock.device_id] = None raise - _LOGGER.debug("Completed retrieving door status") + _LOGGER.debug("Completed retrieving lock and door status") + self._lock_status_by_id = status_by_id self._door_state_by_id = state_by_id - @Throttle(MIN_TIME_BETWEEN_UPDATES) - def _update_locks(self): - status_by_id = {} + @Throttle(MIN_TIME_BETWEEN_LOCK_DETAIL_UPDATES) + def _update_locks_detail(self): detail_by_id = {} - _LOGGER.debug("Start retrieving locks status") + _LOGGER.debug("Start retrieving locks detail") for lock in self._locks: - _LOGGER.debug("Updating lock status for %s", lock.device_name) - try: - status_by_id[lock.device_id] = self._api.get_lock_status( - self._access_token, lock.device_id - ) - except RequestException as ex: - _LOGGER.error( - "Request error trying to retrieve door status for %s. %s", - lock.device_name, - ex, - ) - status_by_id[lock.device_id] = None - except Exception: - status_by_id[lock.device_id] = None - raise - try: detail_by_id[lock.device_id] = self._api.get_lock_detail( self._access_token, lock.device_id @@ -351,8 +353,7 @@ class AugustData: detail_by_id[lock.device_id] = None raise - _LOGGER.debug("Completed retrieving locks status") - self._lock_status_by_id = status_by_id + _LOGGER.debug("Completed retrieving locks detail") self._lock_detail_by_id = detail_by_id def lock(self, device_id): diff --git a/homeassistant/components/august/binary_sensor.py b/homeassistant/components/august/binary_sensor.py index 14d03189c92..f840d3db532 100644 --- a/homeassistant/components/august/binary_sensor.py +++ b/homeassistant/components/august/binary_sensor.py @@ -11,7 +11,7 @@ from . import DATA_AUGUST _LOGGER = logging.getLogger(__name__) -SCAN_INTERVAL = timedelta(seconds=5) +SCAN_INTERVAL = timedelta(seconds=10) def _retrieve_door_state(data, lock): diff --git a/homeassistant/components/august/camera.py b/homeassistant/components/august/camera.py index 2492eb75418..885ee444c6b 100644 --- a/homeassistant/components/august/camera.py +++ b/homeassistant/components/august/camera.py @@ -7,7 +7,7 @@ from homeassistant.components.camera import Camera from . import DATA_AUGUST, DEFAULT_TIMEOUT -SCAN_INTERVAL = timedelta(seconds=5) +SCAN_INTERVAL = timedelta(seconds=10) def setup_platform(hass, config, add_entities, discovery_info=None): diff --git a/homeassistant/components/august/lock.py b/homeassistant/components/august/lock.py index a541be67097..d336e21653b 100644 --- a/homeassistant/components/august/lock.py +++ b/homeassistant/components/august/lock.py @@ -12,7 +12,7 @@ from . import DATA_AUGUST _LOGGER = logging.getLogger(__name__) -SCAN_INTERVAL = timedelta(seconds=5) +SCAN_INTERVAL = timedelta(seconds=10) def setup_platform(hass, config, add_entities, discovery_info=None): @@ -88,7 +88,12 @@ class AugustLock(LockDevice): if self._lock_detail is None: return None - return {ATTR_BATTERY_LEVEL: self._lock_detail.battery_level} + attributes = {ATTR_BATTERY_LEVEL: self._lock_detail.battery_level} + + if self._lock_detail.keypad is not None: + attributes["keypad_battery_level"] = self._lock_detail.keypad.battery_level + + return attributes @property def unique_id(self) -> str: diff --git a/homeassistant/components/august/manifest.json b/homeassistant/components/august/manifest.json index e3e417d20e0..bacd7346ca7 100644 --- a/homeassistant/components/august/manifest.json +++ b/homeassistant/components/august/manifest.json @@ -2,7 +2,7 @@ "domain": "august", "name": "August", "documentation": "https://www.home-assistant.io/integrations/august", - "requirements": ["py-august==0.7.0"], + "requirements": ["py-august==0.8.1"], "dependencies": ["configurator"], "codeowners": [] } diff --git a/requirements_all.txt b/requirements_all.txt index 5a04a4dfba9..390ffe68a31 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1068,7 +1068,7 @@ pushetta==1.0.15 pwmled==1.4.1 # homeassistant.components.august -py-august==0.7.0 +py-august==0.8.1 # homeassistant.components.canary py-canary==0.5.0