diff --git a/homeassistant/components/cloud/__init__.py b/homeassistant/components/cloud/__init__.py index 33b5e248561..f1833899fec 100644 --- a/homeassistant/components/cloud/__init__.py +++ b/homeassistant/components/cloud/__init__.py @@ -1,4 +1,6 @@ """Component to integrate the Home Assistant cloud.""" +import asyncio + from hass_nabucasa import Cloud import voluptuous as vol @@ -193,13 +195,13 @@ async def async_setup(hass, config): hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown) + _remote_handle_prefs_updated(cloud) + async def _service_handler(service): """Handle service for cloud.""" if service.service == SERVICE_REMOTE_CONNECT: - await cloud.remote.connect() await prefs.async_update(remote_enabled=True) elif service.service == SERVICE_REMOTE_DISCONNECT: - await cloud.remote.disconnect() await prefs.async_update(remote_enabled=False) hass.helpers.service.async_register_admin_service( @@ -234,3 +236,28 @@ async def async_setup(hass, config): account_link.async_setup(hass) return True + + +@callback +def _remote_handle_prefs_updated(cloud: Cloud) -> None: + """Handle remote preferences updated.""" + cur_pref = cloud.client.prefs.remote_enabled + lock = asyncio.Lock() + + # Sync remote connection with prefs + async def remote_prefs_updated(prefs: CloudPreferences) -> None: + """Update remote status.""" + nonlocal cur_pref + + async with lock: + if prefs.remote_enabled == cur_pref: + return + + cur_pref = prefs.remote_enabled + + if cur_pref: + await cloud.remote.connect() + else: + await cloud.remote.disconnect() + + cloud.client.prefs.async_listen_updates(remote_prefs_updated) diff --git a/homeassistant/components/cloud/client.py b/homeassistant/components/cloud/client.py index 4c039f3888c..54c471e2a83 100644 --- a/homeassistant/components/cloud/client.py +++ b/homeassistant/components/cloud/client.py @@ -172,6 +172,10 @@ class CloudClient(Interface): if identifier.startswith("remote_"): async_dispatcher_send(self._hass, DISPATCHER_REMOTE_UPDATE, data) + async def async_cloud_connect_update(self, connect: bool) -> None: + """Process cloud remote message to client.""" + await self._prefs.async_update(remote_enabled=connect) + async def async_alexa_message(self, payload: dict[Any, Any]) -> dict[Any, Any]: """Process cloud alexa message to client.""" cloud_user = await self._prefs.get_cloud_user() diff --git a/homeassistant/components/cloud/http_api.py b/homeassistant/components/cloud/http_api.py index cab41ebb0b8..1f17f46013e 100644 --- a/homeassistant/components/cloud/http_api.py +++ b/homeassistant/components/cloud/http_api.py @@ -452,7 +452,6 @@ async def websocket_remote_connect(hass, connection, msg): """Handle request for connect remote.""" cloud = hass.data[DOMAIN] await cloud.client.prefs.async_update(remote_enabled=True) - await cloud.remote.connect() connection.send_result(msg["id"], await _account_data(cloud)) @@ -465,7 +464,6 @@ async def websocket_remote_disconnect(hass, connection, msg): """Handle request for disconnect remote.""" cloud = hass.data[DOMAIN] await cloud.client.prefs.async_update(remote_enabled=False) - await cloud.remote.disconnect() connection.send_result(msg["id"], await _account_data(cloud)) diff --git a/homeassistant/components/cloud/manifest.json b/homeassistant/components/cloud/manifest.json index 8eaad3b4129..517aa887a30 100644 --- a/homeassistant/components/cloud/manifest.json +++ b/homeassistant/components/cloud/manifest.json @@ -2,7 +2,7 @@ "domain": "cloud", "name": "Home Assistant Cloud", "documentation": "https://www.home-assistant.io/integrations/cloud", - "requirements": ["hass-nabucasa==0.49.0"], + "requirements": ["hass-nabucasa==0.50.0"], "dependencies": ["http", "webhook"], "after_dependencies": ["google_assistant", "alexa"], "codeowners": ["@home-assistant/cloud"], diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 70d1fddc790..ceac76606d5 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -15,7 +15,7 @@ ciso8601==2.1.3 cryptography==3.4.8 defusedxml==0.7.1 emoji==1.2.0 -hass-nabucasa==0.49.0 +hass-nabucasa==0.50.0 home-assistant-frontend==20210911.0 httpx==0.19.0 ifaddr==0.1.7 diff --git a/requirements_all.txt b/requirements_all.txt index 8b14f2dc932..5023ecabd62 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -769,7 +769,7 @@ habitipy==0.2.0 hangups==0.4.14 # homeassistant.components.cloud -hass-nabucasa==0.49.0 +hass-nabucasa==0.50.0 # homeassistant.components.splunk hass_splunk==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 44ac5935a13..da36a577fb5 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -456,7 +456,7 @@ habitipy==0.2.0 hangups==0.4.14 # homeassistant.components.cloud -hass-nabucasa==0.49.0 +hass-nabucasa==0.50.0 # homeassistant.components.tasmota hatasmota==0.2.20 diff --git a/tests/components/cloud/test_http_api.py b/tests/components/cloud/test_http_api.py index b678796a5c4..4116e97be92 100644 --- a/tests/components/cloud/test_http_api.py +++ b/tests/components/cloud/test_http_api.py @@ -549,14 +549,8 @@ async def test_enabling_remote(hass, hass_ws_client, setup_api, mock_cloud_login assert len(mock_connect.mock_calls) == 1 - -async def test_disabling_remote(hass, hass_ws_client, setup_api, mock_cloud_login): - """Test we call right code to disable remote UI.""" - client = await hass_ws_client(hass) - cloud = hass.data[DOMAIN] - with patch("hass_nabucasa.remote.RemoteUI.disconnect") as mock_disconnect: - await client.send_json({"id": 5, "type": "cloud/remote/disconnect"}) + await client.send_json({"id": 6, "type": "cloud/remote/disconnect"}) response = await client.receive_json() assert response["success"] assert not cloud.client.remote_autostart diff --git a/tests/components/cloud/test_init.py b/tests/components/cloud/test_init.py index e478849d3ef..f4ca4cbd75a 100644 --- a/tests/components/cloud/test_init.py +++ b/tests/components/cloud/test_init.py @@ -163,7 +163,9 @@ async def test_remote_ui_url(hass, mock_cloud_fixture): with pytest.raises(cloud.CloudNotAvailable): cloud.async_remote_ui_url(hass) - await cl.client.prefs.async_update(remote_enabled=True) + with patch.object(cl.remote, "connect"): + await cl.client.prefs.async_update(remote_enabled=True) + await hass.async_block_till_done() # No instance domain with pytest.raises(cloud.CloudNotAvailable):