Cloud: Recover when internet is not available yet (#42877)

This commit is contained in:
Paulus Schoutsen 2020-11-06 12:12:18 +01:00 committed by GitHub
parent fd04b96132
commit 15da7b3ca6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 3 deletions

View File

@ -1,5 +1,6 @@
"""Interface implementation for cloud client.""" """Interface implementation for cloud client."""
import asyncio import asyncio
import logging
from pathlib import Path from pathlib import Path
from typing import Any, Dict from typing import Any, Dict
@ -14,6 +15,7 @@ from homeassistant.components.google_assistant import const as gc, smart_home as
from homeassistant.const import HTTP_OK from homeassistant.const import HTTP_OK
from homeassistant.core import Context, callback from homeassistant.core import Context, callback
from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_call_later
from homeassistant.helpers.typing import HomeAssistantType from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.util.aiohttp import MockRequest from homeassistant.util.aiohttp import MockRequest
@ -106,13 +108,22 @@ class CloudClient(Interface):
"""When user logs in.""" """When user logs in."""
await self.prefs.async_set_username(self.cloud.username) await self.prefs.async_set_username(self.cloud.username)
if self.alexa_config.enabled and self.alexa_config.should_report_state: async def enable_alexa(_):
"""Enable Alexa."""
try: try:
await self.alexa_config.async_enable_proactive_mode() await self.alexa_config.async_enable_proactive_mode()
except aiohttp.ClientError as err: # If no internet available yet
if self._hass.is_running:
logging.getLogger(__package__).warning(
"Unable to activate Alexa Report State: %s. Retrying in 30 seconds",
err,
)
async_call_later(self._hass, 30, enable_alexa)
except alexa_errors.NoTokenAvailable: except alexa_errors.NoTokenAvailable:
pass pass
if self._prefs.google_enabled: async def enable_google(_):
"""Enable Google."""
gconf = await self.get_google_config() gconf = await self.get_google_config()
gconf.async_enable_local_sdk() gconf.async_enable_local_sdk()
@ -120,6 +131,17 @@ class CloudClient(Interface):
if gconf.should_report_state: if gconf.should_report_state:
gconf.async_enable_report_state() gconf.async_enable_report_state()
tasks = []
if self.alexa_config.enabled and self.alexa_config.should_report_state:
tasks.append(enable_alexa)
if self._prefs.google_enabled:
tasks.append(enable_google)
if tasks:
await asyncio.gather(*[task(None) for task in tasks])
async def cleanups(self) -> None: async def cleanups(self) -> None:
"""Cleanup some stuff after logout.""" """Cleanup some stuff after logout."""
await self.prefs.async_set_username(None) await self.prefs.async_set_username(None)

View File

@ -1,4 +1,7 @@
"""Test the cloud.iot module.""" """Test the cloud.iot module."""
from datetime import timedelta
import aiohttp
from aiohttp import web from aiohttp import web
import pytest import pytest
@ -8,10 +11,12 @@ from homeassistant.components.cloud.const import PREF_ENABLE_ALEXA, PREF_ENABLE_
from homeassistant.const import CONTENT_TYPE_JSON from homeassistant.const import CONTENT_TYPE_JSON
from homeassistant.core import State from homeassistant.core import State
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from . import mock_cloud, mock_cloud_prefs from . import mock_cloud, mock_cloud_prefs
from tests.async_mock import AsyncMock, MagicMock, patch from tests.async_mock import AsyncMock, MagicMock, Mock, patch
from tests.common import async_fire_time_changed
from tests.components.alexa import test_smart_home as test_alexa from tests.components.alexa import test_smart_home as test_alexa
@ -260,3 +265,25 @@ async def test_set_username(hass):
assert len(prefs.async_set_username.mock_calls) == 1 assert len(prefs.async_set_username.mock_calls) == 1
assert prefs.async_set_username.mock_calls[0][1][0] == "mock-username" assert prefs.async_set_username.mock_calls[0][1][0] == "mock-username"
async def test_login_recovers_bad_internet(hass, caplog):
"""Test Alexa can recover bad auth."""
prefs = Mock(
alexa_enabled=True,
google_enabled=False,
async_set_username=AsyncMock(return_value=None),
)
client = CloudClient(hass, prefs, None, {}, {})
client.cloud = Mock()
client._alexa_config = Mock(
async_enable_proactive_mode=Mock(side_effect=aiohttp.ClientError)
)
await client.logged_in()
assert len(client._alexa_config.async_enable_proactive_mode.mock_calls) == 1
assert "Unable to activate Alexa Report State" in caplog.text
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
await hass.async_block_till_done()
assert len(client._alexa_config.async_enable_proactive_mode.mock_calls) == 2