diff --git a/homeassistant/components/august/__init__.py b/homeassistant/components/august/__init__.py index d58541e708d..3fc113c6038 100644 --- a/homeassistant/components/august/__init__.py +++ b/homeassistant/components/august/__init__.py @@ -43,7 +43,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return await async_setup_august(hass, entry, august_gateway) except (RequireValidation, InvalidAuth) as err: raise ConfigEntryAuthFailed from err - except (ClientResponseError, CannotConnect, asyncio.TimeoutError) as err: + except asyncio.TimeoutError as err: + raise ConfigEntryNotReady("Timed out connecting to august api") from err + except (ClientResponseError, CannotConnect) as err: raise ConfigEntryNotReady from err @@ -141,15 +143,34 @@ class AugustData(AugustSubscriberMixin): self._pubnub_unsub = async_create_pubnub(user_data["UserID"], pubnub) if self._locks_by_id: - tasks = [] - for lock_id in self._locks_by_id: - detail = self._device_detail_by_id[lock_id] - tasks.append( - self.async_status_async( - lock_id, bool(detail.bridge and detail.bridge.hyper_bridge) - ) + # Do not prevent setup as the sync can timeout + # but it is not a fatal error as the lock + # will recover automatically when it comes back online. + asyncio.create_task(self._async_initial_sync()) + + async def _async_initial_sync(self): + """Attempt to request an initial sync.""" + # We don't care if this fails because we only want to wake + # locks that are actually online anyways and they will be + # awake when they come back online + for result in await asyncio.gather( + *[ + self.async_status_async( + device_id, bool(detail.bridge and detail.bridge.hyper_bridge) + ) + for device_id, detail in self._device_detail_by_id.items() + if device_id in self._locks_by_id + ], + return_exceptions=True, + ): + if isinstance(result, Exception) and not isinstance( + result, (asyncio.TimeoutError, ClientResponseError, CannotConnect) + ): + _LOGGER.warning( + "Unexpected exception during initial sync: %s", + result, + exc_info=result, ) - await asyncio.gather(*tasks) @callback def async_pubnub_message(self, device_id, date_time, message): diff --git a/homeassistant/components/august/const.py b/homeassistant/components/august/const.py index dfe9cc0f700..ae3fcdf90e3 100644 --- a/homeassistant/components/august/const.py +++ b/homeassistant/components/august/const.py @@ -4,7 +4,7 @@ from datetime import timedelta from homeassistant.const import Platform -DEFAULT_TIMEOUT = 10 +DEFAULT_TIMEOUT = 15 CONF_ACCESS_TOKEN_CACHE_FILE = "access_token_cache_file" CONF_LOGIN_METHOD = "login_method" diff --git a/homeassistant/components/august/manifest.json b/homeassistant/components/august/manifest.json index db537287b05..ea6769fabcf 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": ["yalexs==1.1.19"], + "requirements": ["yalexs==1.1.20"], "codeowners": ["@bdraco"], "dhcp": [ { diff --git a/requirements_all.txt b/requirements_all.txt index 5628e197e2c..0585eb636e2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2513,7 +2513,7 @@ xs1-api-client==3.0.0 yalesmartalarmclient==0.3.7 # homeassistant.components.august -yalexs==1.1.19 +yalexs==1.1.20 # homeassistant.components.yeelight yeelight==0.7.8 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c2cae070fd4..9178470f838 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1541,7 +1541,7 @@ xmltodict==0.12.0 yalesmartalarmclient==0.3.7 # homeassistant.components.august -yalexs==1.1.19 +yalexs==1.1.20 # homeassistant.components.yeelight yeelight==0.7.8 diff --git a/tests/components/august/test_init.py b/tests/components/august/test_init.py index 4d73eec7f1f..320461ca6e9 100644 --- a/tests/components/august/test_init.py +++ b/tests/components/august/test_init.py @@ -30,6 +30,26 @@ from tests.components.august.mocks import ( ) +async def test_august_api_is_failing(hass): + """Config entry state is SETUP_RETRY when august api is failing.""" + + config_entry = MockConfigEntry( + domain=DOMAIN, + data=_mock_get_config()[DOMAIN], + title="August august", + ) + config_entry.add_to_hass(hass) + + with patch( + "yalexs.authenticator_async.AuthenticatorAsync.async_authenticate", + side_effect=ClientResponseError(None, None, status=500), + ): + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.SETUP_RETRY + + async def test_august_is_offline(hass): """Config entry state is SETUP_RETRY when august is offline."""