diff --git a/homeassistant/components/huawei_lte/__init__.py b/homeassistant/components/huawei_lte/__init__.py index 1d54f972907..d3b2d5b1abd 100644 --- a/homeassistant/components/huawei_lte/__init__.py +++ b/homeassistant/components/huawei_lte/__init__.py @@ -5,6 +5,7 @@ from datetime import timedelta from functools import partial import ipaddress import logging +import time from typing import Any, Callable, Dict, List, Set, Tuple from urllib.parse import urlparse @@ -65,6 +66,7 @@ from .const import ( KEY_MONITORING_STATUS, KEY_MONITORING_TRAFFIC_STATISTICS, KEY_WLAN_HOST_LIST, + NOTIFY_SUPPRESS_TIMEOUT, SERVICE_CLEAR_TRAFFIC_STATISTICS, SERVICE_REBOOT, SERVICE_RESUME_INTEGRATION, @@ -138,9 +140,11 @@ class Router: init=False, factory=lambda: defaultdict(set, ((x, {"initial_scan"}) for x in ALL_KEYS)), ) + inflight_gets: Set[str] = attr.ib(init=False, factory=set) unload_handlers: List[CALLBACK_TYPE] = attr.ib(init=False, factory=list) client: Client suspended = attr.ib(init=False, default=False) + notify_last_attempt: float = attr.ib(init=False, default=-1) def __attrs_post_init__(self): """Set up internal state on init.""" @@ -167,6 +171,10 @@ class Router: def _get_data(self, key: str, func: Callable[[None], Any]) -> None: if not self.subscriptions.get(key): return + if key in self.inflight_gets: + _LOGGER.debug("Skipping already inflight get for %s", key) + return + self.inflight_gets.add(key) _LOGGER.debug("Getting %s for subscribers %s", key, self.subscriptions[key]) try: self.data[key] = func() @@ -189,7 +197,21 @@ class Router: "%s requires authorization, excluding from future updates", key ) self.subscriptions.pop(key) + except Timeout: + grace_left = ( + self.notify_last_attempt - time.monotonic() + NOTIFY_SUPPRESS_TIMEOUT + ) + if grace_left > 0: + _LOGGER.debug( + "%s timed out, %.1fs notify timeout suppress grace remaining", + key, + grace_left, + exc_info=True, + ) + else: + raise finally: + self.inflight_gets.discard(key) _LOGGER.debug("%s=%s", key, self.data.get(key)) def update(self) -> None: diff --git a/homeassistant/components/huawei_lte/const.py b/homeassistant/components/huawei_lte/const.py index c6837fce06c..e227f06cf28 100644 --- a/homeassistant/components/huawei_lte/const.py +++ b/homeassistant/components/huawei_lte/const.py @@ -12,6 +12,7 @@ UNIT_BYTES = "B" UNIT_SECONDS = "s" CONNECTION_TIMEOUT = 10 +NOTIFY_SUPPRESS_TIMEOUT = 30 SERVICE_CLEAR_TRAFFIC_STATISTICS = "clear_traffic_statistics" SERVICE_REBOOT = "reboot" diff --git a/homeassistant/components/huawei_lte/notify.py b/homeassistant/components/huawei_lte/notify.py index 5619a5d702c..91cc8864eb0 100644 --- a/homeassistant/components/huawei_lte/notify.py +++ b/homeassistant/components/huawei_lte/notify.py @@ -1,6 +1,7 @@ """Support for Huawei LTE router notifications.""" import logging +import time from typing import Any, List import attr @@ -57,3 +58,5 @@ class HuaweiLteSmsNotificationService(BaseNotificationService): _LOGGER.debug("Sent to %s: %s", targets, resp) except ResponseErrorException as ex: _LOGGER.error("Could not send to %s: %s", targets, ex) + finally: + self.router.notify_last_attempt = time.monotonic()