Add events on cloud connect and disconnect (#65215)
* Add events on cloud connect and disconnect Signed-off-by: cgtobi <cgtobi@gmail.com> * Use event capture helper Signed-off-by: cgtobi <cgtobi@gmail.com> * Provide listener method instead of public event Signed-off-by: cgtobi <cgtobi@gmail.com> * Add test for disconnect notification Signed-off-by: cgtobi <cgtobi@gmail.com> * Apply suggestions from code review Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Use Enum Signed-off-by: cgtobi <cgtobi@gmail.com> * Add module level api Signed-off-by: cgtobi <cgtobi@gmail.com> * Apply suggestions from code review Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Clean up dead code Signed-off-by: cgtobi <cgtobi@gmail.com> * Flake8 Signed-off-by: cgtobi <cgtobi@gmail.com> * Clean up Co-authored-by: Martin Hjelmare <marhje52@gmail.com>pull/65443/head
parent
fda0fbd115
commit
81ad56b8ad
|
@ -1,5 +1,7 @@
|
|||
"""Component to integrate the Home Assistant cloud."""
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
from enum import Enum
|
||||
|
||||
from hass_nabucasa import Cloud
|
||||
import voluptuous as vol
|
||||
|
@ -18,6 +20,10 @@ from homeassistant.core import HomeAssistant, ServiceCall, callback
|
|||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv, entityfilter
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
async_dispatcher_connect,
|
||||
async_dispatcher_send,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.loader import bind_hass
|
||||
from homeassistant.util.aiohttp import MockRequest
|
||||
|
@ -52,6 +58,8 @@ DEFAULT_MODE = MODE_PROD
|
|||
SERVICE_REMOTE_CONNECT = "remote_connect"
|
||||
SERVICE_REMOTE_DISCONNECT = "remote_disconnect"
|
||||
|
||||
SIGNAL_CLOUD_CONNECTION_STATE = "CLOUD_CONNECTION_STATE"
|
||||
|
||||
|
||||
ALEXA_ENTITY_SCHEMA = vol.Schema(
|
||||
{
|
||||
|
@ -118,6 +126,13 @@ class CloudNotConnected(CloudNotAvailable):
|
|||
"""Raised when an action requires the cloud but it's not connected."""
|
||||
|
||||
|
||||
class CloudConnectionState(Enum):
|
||||
"""Cloud connection state."""
|
||||
|
||||
CLOUD_CONNECTED = "cloud_connected"
|
||||
CLOUD_DISCONNECTED = "cloud_disconnected"
|
||||
|
||||
|
||||
@bind_hass
|
||||
@callback
|
||||
def async_is_logged_in(hass: HomeAssistant) -> bool:
|
||||
|
@ -135,6 +150,14 @@ def async_is_connected(hass: HomeAssistant) -> bool:
|
|||
return DOMAIN in hass.data and hass.data[DOMAIN].iot.connected
|
||||
|
||||
|
||||
@callback
|
||||
def async_listen_connection_change(
|
||||
hass: HomeAssistant, target: Callable[[CloudConnectionState], None]
|
||||
) -> Callable[[], None]:
|
||||
"""Notify on connection state changes."""
|
||||
return async_dispatcher_connect(hass, SIGNAL_CLOUD_CONNECTION_STATE, target)
|
||||
|
||||
|
||||
@bind_hass
|
||||
@callback
|
||||
def async_active_subscription(hass: HomeAssistant) -> bool:
|
||||
|
@ -252,11 +275,22 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
Platform.TTS, DOMAIN, {}, config
|
||||
)
|
||||
|
||||
async_dispatcher_send(
|
||||
hass, SIGNAL_CLOUD_CONNECTION_STATE, CloudConnectionState.CLOUD_CONNECTED
|
||||
)
|
||||
|
||||
async def _on_disconnect():
|
||||
"""Handle cloud disconnect."""
|
||||
async_dispatcher_send(
|
||||
hass, SIGNAL_CLOUD_CONNECTION_STATE, CloudConnectionState.CLOUD_DISCONNECTED
|
||||
)
|
||||
|
||||
async def _on_initialized():
|
||||
"""Update preferences."""
|
||||
await prefs.async_update(remote_domain=cloud.remote.instance_domain)
|
||||
|
||||
cloud.iot.register_on_connect(_on_connect)
|
||||
cloud.iot.register_on_disconnect(_on_disconnect)
|
||||
cloud.register_on_initialized(_on_initialized)
|
||||
|
||||
await cloud.initialize()
|
||||
|
|
|
@ -137,6 +137,14 @@ async def test_on_connect(hass, mock_cloud_fixture):
|
|||
|
||||
assert len(hass.states.async_entity_ids("binary_sensor")) == 0
|
||||
|
||||
cloud_states = []
|
||||
|
||||
def handle_state(cloud_state):
|
||||
nonlocal cloud_states
|
||||
cloud_states.append(cloud_state)
|
||||
|
||||
cloud.async_listen_connection_change(hass, handle_state)
|
||||
|
||||
assert "async_setup" in str(cl.iot._on_connect[-1])
|
||||
await cl.iot._on_connect[-1]()
|
||||
await hass.async_block_till_done()
|
||||
|
@ -149,6 +157,17 @@ async def test_on_connect(hass, mock_cloud_fixture):
|
|||
|
||||
assert len(mock_load.mock_calls) == 0
|
||||
|
||||
assert len(cloud_states) == 1
|
||||
assert cloud_states[-1] == cloud.CloudConnectionState.CLOUD_CONNECTED
|
||||
|
||||
assert len(cl.iot._on_disconnect) == 2
|
||||
assert "async_setup" in str(cl.iot._on_disconnect[-1])
|
||||
await cl.iot._on_disconnect[-1]()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(cloud_states) == 2
|
||||
assert cloud_states[-1] == cloud.CloudConnectionState.CLOUD_DISCONNECTED
|
||||
|
||||
|
||||
async def test_remote_ui_url(hass, mock_cloud_fixture):
|
||||
"""Test getting remote ui url."""
|
||||
|
|
Loading…
Reference in New Issue