mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 07:37:34 +00:00
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>
This commit is contained in:
parent
fda0fbd115
commit
81ad56b8ad
@ -1,5 +1,7 @@
|
|||||||
"""Component to integrate the Home Assistant cloud."""
|
"""Component to integrate the Home Assistant cloud."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from collections.abc import Callable
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
from hass_nabucasa import Cloud
|
from hass_nabucasa import Cloud
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -18,6 +20,10 @@ from homeassistant.core import HomeAssistant, ServiceCall, callback
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv, entityfilter
|
from homeassistant.helpers import config_validation as cv, entityfilter
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
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.helpers.typing import ConfigType
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
from homeassistant.util.aiohttp import MockRequest
|
from homeassistant.util.aiohttp import MockRequest
|
||||||
@ -52,6 +58,8 @@ DEFAULT_MODE = MODE_PROD
|
|||||||
SERVICE_REMOTE_CONNECT = "remote_connect"
|
SERVICE_REMOTE_CONNECT = "remote_connect"
|
||||||
SERVICE_REMOTE_DISCONNECT = "remote_disconnect"
|
SERVICE_REMOTE_DISCONNECT = "remote_disconnect"
|
||||||
|
|
||||||
|
SIGNAL_CLOUD_CONNECTION_STATE = "CLOUD_CONNECTION_STATE"
|
||||||
|
|
||||||
|
|
||||||
ALEXA_ENTITY_SCHEMA = vol.Schema(
|
ALEXA_ENTITY_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
@ -118,6 +126,13 @@ class CloudNotConnected(CloudNotAvailable):
|
|||||||
"""Raised when an action requires the cloud but it's not connected."""
|
"""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
|
@bind_hass
|
||||||
@callback
|
@callback
|
||||||
def async_is_logged_in(hass: HomeAssistant) -> bool:
|
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
|
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
|
@bind_hass
|
||||||
@callback
|
@callback
|
||||||
def async_active_subscription(hass: HomeAssistant) -> bool:
|
def async_active_subscription(hass: HomeAssistant) -> bool:
|
||||||
@ -252,11 +275,22 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
Platform.TTS, DOMAIN, {}, config
|
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():
|
async def _on_initialized():
|
||||||
"""Update preferences."""
|
"""Update preferences."""
|
||||||
await prefs.async_update(remote_domain=cloud.remote.instance_domain)
|
await prefs.async_update(remote_domain=cloud.remote.instance_domain)
|
||||||
|
|
||||||
cloud.iot.register_on_connect(_on_connect)
|
cloud.iot.register_on_connect(_on_connect)
|
||||||
|
cloud.iot.register_on_disconnect(_on_disconnect)
|
||||||
cloud.register_on_initialized(_on_initialized)
|
cloud.register_on_initialized(_on_initialized)
|
||||||
|
|
||||||
await cloud.initialize()
|
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
|
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])
|
assert "async_setup" in str(cl.iot._on_connect[-1])
|
||||||
await cl.iot._on_connect[-1]()
|
await cl.iot._on_connect[-1]()
|
||||||
await hass.async_block_till_done()
|
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(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):
|
async def test_remote_ui_url(hass, mock_cloud_fixture):
|
||||||
"""Test getting remote ui url."""
|
"""Test getting remote ui url."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user