Use HassKey in cloud integration (#120322)
parent
b223cb7bb9
commit
ea09d0cbed
|
@ -55,6 +55,7 @@ from .const import (
|
||||||
CONF_SERVICEHANDLERS_SERVER,
|
CONF_SERVICEHANDLERS_SERVER,
|
||||||
CONF_THINGTALK_SERVER,
|
CONF_THINGTALK_SERVER,
|
||||||
CONF_USER_POOL_ID,
|
CONF_USER_POOL_ID,
|
||||||
|
DATA_CLOUD,
|
||||||
DATA_PLATFORMS_SETUP,
|
DATA_PLATFORMS_SETUP,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
MODE_DEV,
|
MODE_DEV,
|
||||||
|
@ -155,14 +156,14 @@ def async_is_logged_in(hass: HomeAssistant) -> bool:
|
||||||
|
|
||||||
Note: This returns True even if not currently connected to the cloud.
|
Note: This returns True even if not currently connected to the cloud.
|
||||||
"""
|
"""
|
||||||
return DOMAIN in hass.data and hass.data[DOMAIN].is_logged_in
|
return DATA_CLOUD in hass.data and hass.data[DATA_CLOUD].is_logged_in
|
||||||
|
|
||||||
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
@callback
|
@callback
|
||||||
def async_is_connected(hass: HomeAssistant) -> bool:
|
def async_is_connected(hass: HomeAssistant) -> bool:
|
||||||
"""Test if connected to the cloud."""
|
"""Test if connected to the cloud."""
|
||||||
return DOMAIN in hass.data and hass.data[DOMAIN].iot.connected
|
return DATA_CLOUD in hass.data and hass.data[DATA_CLOUD].iot.connected
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -178,7 +179,7 @@ def async_listen_connection_change(
|
||||||
@callback
|
@callback
|
||||||
def async_active_subscription(hass: HomeAssistant) -> bool:
|
def async_active_subscription(hass: HomeAssistant) -> bool:
|
||||||
"""Test if user has an active subscription."""
|
"""Test if user has an active subscription."""
|
||||||
return async_is_logged_in(hass) and not hass.data[DOMAIN].subscription_expired
|
return async_is_logged_in(hass) and not hass.data[DATA_CLOUD].subscription_expired
|
||||||
|
|
||||||
|
|
||||||
async def async_get_or_create_cloudhook(hass: HomeAssistant, webhook_id: str) -> str:
|
async def async_get_or_create_cloudhook(hass: HomeAssistant, webhook_id: str) -> str:
|
||||||
|
@ -189,7 +190,7 @@ async def async_get_or_create_cloudhook(hass: HomeAssistant, webhook_id: str) ->
|
||||||
if not async_is_logged_in(hass):
|
if not async_is_logged_in(hass):
|
||||||
raise CloudNotAvailable
|
raise CloudNotAvailable
|
||||||
|
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
cloudhooks = cloud.client.cloudhooks
|
cloudhooks = cloud.client.cloudhooks
|
||||||
if hook := cloudhooks.get(webhook_id):
|
if hook := cloudhooks.get(webhook_id):
|
||||||
return cast(str, hook["cloudhook_url"])
|
return cast(str, hook["cloudhook_url"])
|
||||||
|
@ -206,7 +207,7 @@ async def async_create_cloudhook(hass: HomeAssistant, webhook_id: str) -> str:
|
||||||
if not async_is_logged_in(hass):
|
if not async_is_logged_in(hass):
|
||||||
raise CloudNotAvailable
|
raise CloudNotAvailable
|
||||||
|
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
hook = await cloud.cloudhooks.async_create(webhook_id, True)
|
hook = await cloud.cloudhooks.async_create(webhook_id, True)
|
||||||
cloudhook_url: str = hook["cloudhook_url"]
|
cloudhook_url: str = hook["cloudhook_url"]
|
||||||
return cloudhook_url
|
return cloudhook_url
|
||||||
|
@ -215,10 +216,10 @@ async def async_create_cloudhook(hass: HomeAssistant, webhook_id: str) -> str:
|
||||||
@bind_hass
|
@bind_hass
|
||||||
async def async_delete_cloudhook(hass: HomeAssistant, webhook_id: str) -> None:
|
async def async_delete_cloudhook(hass: HomeAssistant, webhook_id: str) -> None:
|
||||||
"""Delete a cloudhook."""
|
"""Delete a cloudhook."""
|
||||||
if DOMAIN not in hass.data:
|
if DATA_CLOUD not in hass.data:
|
||||||
raise CloudNotAvailable
|
raise CloudNotAvailable
|
||||||
|
|
||||||
await hass.data[DOMAIN].cloudhooks.async_delete(webhook_id)
|
await hass.data[DATA_CLOUD].cloudhooks.async_delete(webhook_id)
|
||||||
|
|
||||||
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
|
@ -228,10 +229,10 @@ def async_remote_ui_url(hass: HomeAssistant) -> str:
|
||||||
if not async_is_logged_in(hass):
|
if not async_is_logged_in(hass):
|
||||||
raise CloudNotAvailable
|
raise CloudNotAvailable
|
||||||
|
|
||||||
if not hass.data[DOMAIN].client.prefs.remote_enabled:
|
if not hass.data[DATA_CLOUD].client.prefs.remote_enabled:
|
||||||
raise CloudNotAvailable
|
raise CloudNotAvailable
|
||||||
|
|
||||||
if not (remote_domain := hass.data[DOMAIN].client.prefs.remote_domain):
|
if not (remote_domain := hass.data[DATA_CLOUD].client.prefs.remote_domain):
|
||||||
raise CloudNotAvailable
|
raise CloudNotAvailable
|
||||||
|
|
||||||
return f"https://{remote_domain}"
|
return f"https://{remote_domain}"
|
||||||
|
@ -256,7 +257,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
# Initialize Cloud
|
# Initialize Cloud
|
||||||
websession = async_get_clientsession(hass)
|
websession = async_get_clientsession(hass)
|
||||||
client = CloudClient(hass, prefs, websession, alexa_conf, google_conf)
|
client = CloudClient(hass, prefs, websession, alexa_conf, google_conf)
|
||||||
cloud = hass.data[DOMAIN] = Cloud(client, **kwargs)
|
cloud = hass.data[DATA_CLOUD] = Cloud(client, **kwargs)
|
||||||
|
|
||||||
async def _shutdown(event: Event) -> None:
|
async def _shutdown(event: Event) -> None:
|
||||||
"""Shutdown event."""
|
"""Shutdown event."""
|
||||||
|
@ -373,9 +374,7 @@ def _remote_handle_prefs_updated(cloud: Cloud[CloudClient]) -> None:
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up a config entry."""
|
"""Set up a config entry."""
|
||||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||||
stt_tts_entities_added: asyncio.Event = hass.data[DATA_PLATFORMS_SETUP][
|
stt_tts_entities_added = hass.data[DATA_PLATFORMS_SETUP]["stt_tts_entities_added"]
|
||||||
"stt_tts_entities_added"
|
|
||||||
]
|
|
||||||
stt_tts_entities_added.set()
|
stt_tts_entities_added.set()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -14,7 +14,7 @@ from homeassistant.const import __version__ as HA_VERSION
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow, event
|
from homeassistant.helpers import config_entry_oauth2_flow, event
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DATA_CLOUD, DOMAIN
|
||||||
|
|
||||||
DATA_SERVICES = "cloud_account_link_services"
|
DATA_SERVICES = "cloud_account_link_services"
|
||||||
CACHE_TIMEOUT = 3600
|
CACHE_TIMEOUT = 3600
|
||||||
|
@ -68,7 +68,9 @@ async def _get_services(hass: HomeAssistant) -> list[dict[str, Any]]:
|
||||||
return services # noqa: RET504
|
return services # noqa: RET504
|
||||||
|
|
||||||
try:
|
try:
|
||||||
services = await account_link.async_fetch_available_services(hass.data[DOMAIN])
|
services = await account_link.async_fetch_available_services(
|
||||||
|
hass.data[DATA_CLOUD]
|
||||||
|
)
|
||||||
except (aiohttp.ClientError, TimeoutError):
|
except (aiohttp.ClientError, TimeoutError):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -105,7 +107,7 @@ class CloudOAuth2Implementation(config_entry_oauth2_flow.AbstractOAuth2Implement
|
||||||
async def async_generate_authorize_url(self, flow_id: str) -> str:
|
async def async_generate_authorize_url(self, flow_id: str) -> str:
|
||||||
"""Generate a url for the user to authorize."""
|
"""Generate a url for the user to authorize."""
|
||||||
helper = account_link.AuthorizeAccountHelper(
|
helper = account_link.AuthorizeAccountHelper(
|
||||||
self.hass.data[DOMAIN], self.service
|
self.hass.data[DATA_CLOUD], self.service
|
||||||
)
|
)
|
||||||
authorize_url = await helper.async_get_authorize_url()
|
authorize_url = await helper.async_get_authorize_url()
|
||||||
|
|
||||||
|
@ -138,6 +140,6 @@ class CloudOAuth2Implementation(config_entry_oauth2_flow.AbstractOAuth2Implement
|
||||||
async def _async_refresh_token(self, token: dict) -> dict:
|
async def _async_refresh_token(self, token: dict) -> dict:
|
||||||
"""Refresh a token."""
|
"""Refresh a token."""
|
||||||
new_token = await account_link.async_fetch_access_token(
|
new_token = await account_link.async_fetch_access_token(
|
||||||
self.hass.data[DOMAIN], self.service, token["refresh_token"]
|
self.hass.data[DATA_CLOUD], self.service, token["refresh_token"]
|
||||||
)
|
)
|
||||||
return {**token, **new_token}
|
return {**token, **new_token}
|
||||||
|
|
|
@ -27,7 +27,7 @@ async def async_create_cloud_pipeline(hass: HomeAssistant) -> str | None:
|
||||||
"""Create a cloud assist pipeline."""
|
"""Create a cloud assist pipeline."""
|
||||||
# Wait for stt and tts platforms to set up and entities to be added
|
# Wait for stt and tts platforms to set up and entities to be added
|
||||||
# before creating the pipeline.
|
# before creating the pipeline.
|
||||||
platforms_setup: dict[str, asyncio.Event] = hass.data[DATA_PLATFORMS_SETUP]
|
platforms_setup = hass.data[DATA_PLATFORMS_SETUP]
|
||||||
await asyncio.gather(*(event.wait() for event in platforms_setup.values()))
|
await asyncio.gather(*(event.wait() for event in platforms_setup.values()))
|
||||||
# Make sure the pipeline store is loaded, needed because assist_pipeline
|
# Make sure the pipeline store is loaded, needed because assist_pipeline
|
||||||
# is an after dependency of cloud
|
# is an after dependency of cloud
|
||||||
|
@ -91,7 +91,7 @@ async def async_migrate_cloud_pipeline_engine(
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Invalid platform {platform}")
|
raise ValueError(f"Invalid platform {platform}")
|
||||||
|
|
||||||
platforms_setup: dict[str, asyncio.Event] = hass.data[DATA_PLATFORMS_SETUP]
|
platforms_setup = hass.data[DATA_PLATFORMS_SETUP]
|
||||||
await platforms_setup[wait_for_platform].wait()
|
await platforms_setup[wait_for_platform].wait()
|
||||||
|
|
||||||
# Make sure the pipeline store is loaded, needed because assist_pipeline
|
# Make sure the pipeline store is loaded, needed because assist_pipeline
|
||||||
|
|
|
@ -18,7 +18,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .client import CloudClient
|
from .client import CloudClient
|
||||||
from .const import DISPATCHER_REMOTE_UPDATE, DOMAIN
|
from .const import DATA_CLOUD, DISPATCHER_REMOTE_UPDATE
|
||||||
|
|
||||||
WAIT_UNTIL_CHANGE = 3
|
WAIT_UNTIL_CHANGE = 3
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ async def async_setup_entry(
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the Home Assistant Cloud binary sensors."""
|
"""Set up the Home Assistant Cloud binary sensors."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
async_add_entities([CloudRemoteBinary(cloud)])
|
async_add_entities([CloudRemoteBinary(cloud)])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,22 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
import asyncio
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
from homeassistant.util.hass_dict import HassKey
|
||||||
from homeassistant.util.signal_type import SignalType
|
from homeassistant.util.signal_type import SignalType
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from hass_nabucasa import Cloud
|
||||||
|
|
||||||
|
from .client import CloudClient
|
||||||
|
|
||||||
DOMAIN = "cloud"
|
DOMAIN = "cloud"
|
||||||
DATA_PLATFORMS_SETUP = "cloud_platforms_setup"
|
DATA_CLOUD: HassKey[Cloud[CloudClient]] = HassKey(DOMAIN)
|
||||||
|
DATA_PLATFORMS_SETUP: HassKey[dict[str, asyncio.Event]] = HassKey(
|
||||||
|
"cloud_platforms_setup"
|
||||||
|
)
|
||||||
REQUEST_TIMEOUT = 10
|
REQUEST_TIMEOUT = 10
|
||||||
|
|
||||||
PREF_ENABLE_ALEXA = "alexa_enabled"
|
PREF_ENABLE_ALEXA = "alexa_enabled"
|
||||||
|
|
|
@ -38,7 +38,7 @@ from .alexa_config import entity_supported as entity_supported_by_alexa
|
||||||
from .assist_pipeline import async_create_cloud_pipeline
|
from .assist_pipeline import async_create_cloud_pipeline
|
||||||
from .client import CloudClient
|
from .client import CloudClient
|
||||||
from .const import (
|
from .const import (
|
||||||
DOMAIN,
|
DATA_CLOUD,
|
||||||
PREF_ALEXA_REPORT_STATE,
|
PREF_ALEXA_REPORT_STATE,
|
||||||
PREF_DISABLE_2FA,
|
PREF_DISABLE_2FA,
|
||||||
PREF_ENABLE_ALEXA,
|
PREF_ENABLE_ALEXA,
|
||||||
|
@ -196,7 +196,7 @@ class GoogleActionsSyncView(HomeAssistantView):
|
||||||
async def post(self, request: web.Request) -> web.Response:
|
async def post(self, request: web.Request) -> web.Response:
|
||||||
"""Trigger a Google Actions sync."""
|
"""Trigger a Google Actions sync."""
|
||||||
hass = request.app[KEY_HASS]
|
hass = request.app[KEY_HASS]
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
gconf = await cloud.client.get_google_config()
|
gconf = await cloud.client.get_google_config()
|
||||||
status = await gconf.async_sync_entities(gconf.agent_user_id)
|
status = await gconf.async_sync_entities(gconf.agent_user_id)
|
||||||
return self.json({}, status_code=status)
|
return self.json({}, status_code=status)
|
||||||
|
@ -216,7 +216,7 @@ class CloudLoginView(HomeAssistantView):
|
||||||
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
||||||
"""Handle login request."""
|
"""Handle login request."""
|
||||||
hass = request.app[KEY_HASS]
|
hass = request.app[KEY_HASS]
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
await cloud.login(data["email"], data["password"])
|
await cloud.login(data["email"], data["password"])
|
||||||
|
|
||||||
if "assist_pipeline" in hass.config.components:
|
if "assist_pipeline" in hass.config.components:
|
||||||
|
@ -237,7 +237,7 @@ class CloudLogoutView(HomeAssistantView):
|
||||||
async def post(self, request: web.Request) -> web.Response:
|
async def post(self, request: web.Request) -> web.Response:
|
||||||
"""Handle logout request."""
|
"""Handle logout request."""
|
||||||
hass = request.app[KEY_HASS]
|
hass = request.app[KEY_HASS]
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
async with asyncio.timeout(REQUEST_TIMEOUT):
|
async with asyncio.timeout(REQUEST_TIMEOUT):
|
||||||
await cloud.logout()
|
await cloud.logout()
|
||||||
|
@ -264,7 +264,7 @@ class CloudRegisterView(HomeAssistantView):
|
||||||
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
||||||
"""Handle registration request."""
|
"""Handle registration request."""
|
||||||
hass = request.app[KEY_HASS]
|
hass = request.app[KEY_HASS]
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
client_metadata = None
|
client_metadata = None
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ class CloudResendConfirmView(HomeAssistantView):
|
||||||
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
||||||
"""Handle resending confirm email code request."""
|
"""Handle resending confirm email code request."""
|
||||||
hass = request.app[KEY_HASS]
|
hass = request.app[KEY_HASS]
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
async with asyncio.timeout(REQUEST_TIMEOUT):
|
async with asyncio.timeout(REQUEST_TIMEOUT):
|
||||||
await cloud.auth.async_resend_email_confirm(data["email"])
|
await cloud.auth.async_resend_email_confirm(data["email"])
|
||||||
|
@ -321,7 +321,7 @@ class CloudForgotPasswordView(HomeAssistantView):
|
||||||
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
async def post(self, request: web.Request, data: dict[str, Any]) -> web.Response:
|
||||||
"""Handle forgot password request."""
|
"""Handle forgot password request."""
|
||||||
hass = request.app[KEY_HASS]
|
hass = request.app[KEY_HASS]
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
async with asyncio.timeout(REQUEST_TIMEOUT):
|
async with asyncio.timeout(REQUEST_TIMEOUT):
|
||||||
await cloud.auth.async_forgot_password(data["email"])
|
await cloud.auth.async_forgot_password(data["email"])
|
||||||
|
@ -341,7 +341,7 @@ async def websocket_cloud_remove_data(
|
||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
if cloud.is_logged_in:
|
if cloud.is_logged_in:
|
||||||
connection.send_message(
|
connection.send_message(
|
||||||
websocket_api.error_message(
|
websocket_api.error_message(
|
||||||
|
@ -367,7 +367,7 @@ async def websocket_cloud_status(
|
||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
"""
|
"""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
connection.send_message(
|
connection.send_message(
|
||||||
websocket_api.result_message(msg["id"], await _account_data(hass, cloud))
|
websocket_api.result_message(msg["id"], await _account_data(hass, cloud))
|
||||||
)
|
)
|
||||||
|
@ -391,7 +391,7 @@ def _require_cloud_login(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Require to be logged into the cloud."""
|
"""Require to be logged into the cloud."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
if not cloud.is_logged_in:
|
if not cloud.is_logged_in:
|
||||||
connection.send_message(
|
connection.send_message(
|
||||||
websocket_api.error_message(
|
websocket_api.error_message(
|
||||||
|
@ -414,7 +414,7 @@ async def websocket_subscription(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle request for account info."""
|
"""Handle request for account info."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
if (data := await async_subscription_info(cloud)) is None:
|
if (data := await async_subscription_info(cloud)) is None:
|
||||||
connection.send_error(
|
connection.send_error(
|
||||||
msg["id"], "request_failed", "Failed to request subscription"
|
msg["id"], "request_failed", "Failed to request subscription"
|
||||||
|
@ -457,7 +457,7 @@ async def websocket_update_prefs(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle request for account info."""
|
"""Handle request for account info."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
changes = dict(msg)
|
changes = dict(msg)
|
||||||
changes.pop("id")
|
changes.pop("id")
|
||||||
|
@ -508,7 +508,7 @@ async def websocket_hook_create(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle request for account info."""
|
"""Handle request for account info."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
hook = await cloud.cloudhooks.async_create(msg["webhook_id"], False)
|
hook = await cloud.cloudhooks.async_create(msg["webhook_id"], False)
|
||||||
connection.send_message(websocket_api.result_message(msg["id"], hook))
|
connection.send_message(websocket_api.result_message(msg["id"], hook))
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ async def websocket_hook_delete(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle request for account info."""
|
"""Handle request for account info."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
await cloud.cloudhooks.async_delete(msg["webhook_id"])
|
await cloud.cloudhooks.async_delete(msg["webhook_id"])
|
||||||
connection.send_message(websocket_api.result_message(msg["id"]))
|
connection.send_message(websocket_api.result_message(msg["id"]))
|
||||||
|
|
||||||
|
@ -597,7 +597,7 @@ async def websocket_remote_connect(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle request for connect remote."""
|
"""Handle request for connect remote."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
await cloud.client.prefs.async_update(remote_enabled=True)
|
await cloud.client.prefs.async_update(remote_enabled=True)
|
||||||
connection.send_result(msg["id"], await _account_data(hass, cloud))
|
connection.send_result(msg["id"], await _account_data(hass, cloud))
|
||||||
|
|
||||||
|
@ -613,7 +613,7 @@ async def websocket_remote_disconnect(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Handle request for disconnect remote."""
|
"""Handle request for disconnect remote."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
await cloud.client.prefs.async_update(remote_enabled=False)
|
await cloud.client.prefs.async_update(remote_enabled=False)
|
||||||
connection.send_result(msg["id"], await _account_data(hass, cloud))
|
connection.send_result(msg["id"], await _account_data(hass, cloud))
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ async def google_assistant_get(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Get data for a single google assistant entity."""
|
"""Get data for a single google assistant entity."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
gconf = await cloud.client.get_google_config()
|
gconf = await cloud.client.get_google_config()
|
||||||
entity_id: str = msg["entity_id"]
|
entity_id: str = msg["entity_id"]
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
|
@ -682,7 +682,7 @@ async def google_assistant_list(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""List all google assistant entities."""
|
"""List all google assistant entities."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
gconf = await cloud.client.get_google_config()
|
gconf = await cloud.client.get_google_config()
|
||||||
entities = google_helpers.async_get_entities(hass, gconf)
|
entities = google_helpers.async_get_entities(hass, gconf)
|
||||||
|
|
||||||
|
@ -774,7 +774,7 @@ async def alexa_list(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""List all alexa entities."""
|
"""List all alexa entities."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
alexa_config = await cloud.client.get_alexa_config()
|
alexa_config = await cloud.client.get_alexa_config()
|
||||||
entities = alexa_entities.async_get_entities(hass, alexa_config)
|
entities = alexa_entities.async_get_entities(hass, alexa_config)
|
||||||
|
|
||||||
|
@ -800,7 +800,7 @@ async def alexa_sync(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Sync with Alexa."""
|
"""Sync with Alexa."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
alexa_config = await cloud.client.get_alexa_config()
|
alexa_config = await cloud.client.get_alexa_config()
|
||||||
|
|
||||||
async with asyncio.timeout(10):
|
async with asyncio.timeout(10):
|
||||||
|
@ -830,7 +830,7 @@ async def thingtalk_convert(
|
||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Convert a query."""
|
"""Convert a query."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
async with asyncio.timeout(10):
|
async with asyncio.timeout(10):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -5,7 +5,6 @@ from __future__ import annotations
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from hass_nabucasa import Cloud
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.repairs import (
|
from homeassistant.components.repairs import (
|
||||||
|
@ -17,8 +16,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
from homeassistant.helpers import issue_registry as ir
|
from homeassistant.helpers import issue_registry as ir
|
||||||
|
|
||||||
from .client import CloudClient
|
from .const import DATA_CLOUD, DOMAIN
|
||||||
from .const import DOMAIN
|
|
||||||
from .subscription import async_migrate_paypal_agreement, async_subscription_info
|
from .subscription import async_migrate_paypal_agreement, async_subscription_info
|
||||||
|
|
||||||
BACKOFF_TIME = 5
|
BACKOFF_TIME = 5
|
||||||
|
@ -73,7 +71,7 @@ class LegacySubscriptionRepairFlow(RepairsFlow):
|
||||||
async def async_step_change_plan(self, _: None = None) -> FlowResult:
|
async def async_step_change_plan(self, _: None = None) -> FlowResult:
|
||||||
"""Wait for the user to authorize the app installation."""
|
"""Wait for the user to authorize the app installation."""
|
||||||
|
|
||||||
cloud: Cloud[CloudClient] = self.hass.data[DOMAIN]
|
cloud = self.hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
async def _async_wait_for_plan_change() -> None:
|
async def _async_wait_for_plan_change() -> None:
|
||||||
flow_manager = repairs_flow_manager(self.hass)
|
flow_manager = repairs_flow_manager(self.hass)
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
|
||||||
from collections.abc import AsyncIterable
|
from collections.abc import AsyncIterable
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -28,7 +27,7 @@ from homeassistant.setup import async_when_setup
|
||||||
|
|
||||||
from .assist_pipeline import async_migrate_cloud_pipeline_engine
|
from .assist_pipeline import async_migrate_cloud_pipeline_engine
|
||||||
from .client import CloudClient
|
from .client import CloudClient
|
||||||
from .const import DATA_PLATFORMS_SETUP, DOMAIN, STT_ENTITY_UNIQUE_ID
|
from .const import DATA_CLOUD, DATA_PLATFORMS_SETUP, STT_ENTITY_UNIQUE_ID
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -39,9 +38,9 @@ async def async_setup_entry(
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Home Assistant Cloud speech platform via config entry."""
|
"""Set up Home Assistant Cloud speech platform via config entry."""
|
||||||
stt_platform_loaded: asyncio.Event = hass.data[DATA_PLATFORMS_SETUP][Platform.STT]
|
stt_platform_loaded = hass.data[DATA_PLATFORMS_SETUP][Platform.STT]
|
||||||
stt_platform_loaded.set()
|
stt_platform_loaded.set()
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
async_add_entities([CloudProviderEntity(cloud)])
|
async_add_entities([CloudProviderEntity(cloud)])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,10 @@
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from hass_nabucasa import Cloud
|
|
||||||
|
|
||||||
from homeassistant.components import system_health
|
from homeassistant.components import system_health
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
|
||||||
from .client import CloudClient
|
from .const import DATA_CLOUD
|
||||||
from .const import DOMAIN
|
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -21,7 +18,7 @@ def async_register(
|
||||||
|
|
||||||
async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
|
async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
|
||||||
"""Get info for the info page."""
|
"""Get info for the info page."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
client = cloud.client
|
client = cloud.client
|
||||||
|
|
||||||
data: dict[str, Any] = {
|
data: dict[str, Any] = {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
@ -31,7 +30,7 @@ from homeassistant.setup import async_when_setup
|
||||||
|
|
||||||
from .assist_pipeline import async_migrate_cloud_pipeline_engine
|
from .assist_pipeline import async_migrate_cloud_pipeline_engine
|
||||||
from .client import CloudClient
|
from .client import CloudClient
|
||||||
from .const import DATA_PLATFORMS_SETUP, DOMAIN, TTS_ENTITY_UNIQUE_ID
|
from .const import DATA_CLOUD, DATA_PLATFORMS_SETUP, DOMAIN, TTS_ENTITY_UNIQUE_ID
|
||||||
from .prefs import CloudPreferences
|
from .prefs import CloudPreferences
|
||||||
|
|
||||||
ATTR_GENDER = "gender"
|
ATTR_GENDER = "gender"
|
||||||
|
@ -97,7 +96,7 @@ async def async_get_engine(
|
||||||
discovery_info: DiscoveryInfoType | None = None,
|
discovery_info: DiscoveryInfoType | None = None,
|
||||||
) -> CloudProvider:
|
) -> CloudProvider:
|
||||||
"""Set up Cloud speech component."""
|
"""Set up Cloud speech component."""
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
cloud_provider = CloudProvider(cloud)
|
cloud_provider = CloudProvider(cloud)
|
||||||
if discovery_info is not None:
|
if discovery_info is not None:
|
||||||
discovery_info["platform_loaded"].set()
|
discovery_info["platform_loaded"].set()
|
||||||
|
@ -110,9 +109,9 @@ async def async_setup_entry(
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Home Assistant Cloud text-to-speech platform."""
|
"""Set up Home Assistant Cloud text-to-speech platform."""
|
||||||
tts_platform_loaded: asyncio.Event = hass.data[DATA_PLATFORMS_SETUP][Platform.TTS]
|
tts_platform_loaded = hass.data[DATA_PLATFORMS_SETUP][Platform.TTS]
|
||||||
tts_platform_loaded.set()
|
tts_platform_loaded.set()
|
||||||
cloud: Cloud[CloudClient] = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
async_add_entities([CloudTTSEntity(cloud)])
|
async_add_entities([CloudTTSEntity(cloud)])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
|
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
from hass_nabucasa import Cloud
|
|
||||||
|
|
||||||
from homeassistant.components import cloud
|
from homeassistant.components import cloud
|
||||||
from homeassistant.components.cloud import const, prefs as cloud_prefs
|
from homeassistant.components.cloud import const, prefs as cloud_prefs
|
||||||
|
from homeassistant.components.cloud.const import DATA_CLOUD
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
PIPELINE_DATA = {
|
PIPELINE_DATA = {
|
||||||
|
@ -64,7 +63,7 @@ async def mock_cloud(hass, config=None):
|
||||||
assert await async_setup_component(hass, "homeassistant", {})
|
assert await async_setup_component(hass, "homeassistant", {})
|
||||||
|
|
||||||
assert await async_setup_component(hass, cloud.DOMAIN, {"cloud": config or {}})
|
assert await async_setup_component(hass, cloud.DOMAIN, {"cloud": config or {}})
|
||||||
cloud_inst: Cloud = hass.data["cloud"]
|
cloud_inst = hass.data[DATA_CLOUD]
|
||||||
with patch("hass_nabucasa.Cloud.run_executor", AsyncMock(return_value=None)):
|
with patch("hass_nabucasa.Cloud.run_executor", AsyncMock(return_value=None)):
|
||||||
await cloud_inst.initialize()
|
await cloud_inst.initialize()
|
||||||
|
|
||||||
|
@ -79,5 +78,5 @@ def mock_cloud_prefs(hass, prefs):
|
||||||
const.PREF_GOOGLE_SETTINGS_VERSION: cloud_prefs.GOOGLE_SETTINGS_VERSION,
|
const.PREF_GOOGLE_SETTINGS_VERSION: cloud_prefs.GOOGLE_SETTINGS_VERSION,
|
||||||
}
|
}
|
||||||
prefs_to_set.update(prefs)
|
prefs_to_set.update(prefs)
|
||||||
hass.data[cloud.DOMAIN].client._prefs._prefs = prefs_to_set
|
hass.data[DATA_CLOUD].client._prefs._prefs = prefs_to_set
|
||||||
return hass.data[cloud.DOMAIN].client._prefs
|
return hass.data[DATA_CLOUD].client._prefs
|
||||||
|
|
|
@ -17,7 +17,8 @@ import jwt
|
||||||
import pytest
|
import pytest
|
||||||
from typing_extensions import AsyncGenerator
|
from typing_extensions import AsyncGenerator
|
||||||
|
|
||||||
from homeassistant.components.cloud import CloudClient, const, prefs
|
from homeassistant.components.cloud import CloudClient, prefs
|
||||||
|
from homeassistant.components.cloud.const import DATA_CLOUD
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
|
@ -223,7 +224,7 @@ async def mock_cloud_setup(hass):
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_cloud_login(hass, mock_cloud_setup):
|
def mock_cloud_login(hass, mock_cloud_setup):
|
||||||
"""Mock cloud is logged in."""
|
"""Mock cloud is logged in."""
|
||||||
hass.data[const.DOMAIN].id_token = jwt.encode(
|
hass.data[DATA_CLOUD].id_token = jwt.encode(
|
||||||
{
|
{
|
||||||
"email": "hello@home-assistant.io",
|
"email": "hello@home-assistant.io",
|
||||||
"custom:sub-exp": "2300-01-03",
|
"custom:sub-exp": "2300-01-03",
|
||||||
|
@ -231,7 +232,7 @@ def mock_cloud_login(hass, mock_cloud_setup):
|
||||||
},
|
},
|
||||||
"test",
|
"test",
|
||||||
)
|
)
|
||||||
with patch.object(hass.data[const.DOMAIN].auth, "async_check_token"):
|
with patch.object(hass.data[DATA_CLOUD].auth, "async_check_token"):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,7 +249,7 @@ def mock_auth_fixture():
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_expired_cloud_login(hass, mock_cloud_setup):
|
def mock_expired_cloud_login(hass, mock_cloud_setup):
|
||||||
"""Mock cloud is logged in."""
|
"""Mock cloud is logged in."""
|
||||||
hass.data[const.DOMAIN].id_token = jwt.encode(
|
hass.data[DATA_CLOUD].id_token = jwt.encode(
|
||||||
{
|
{
|
||||||
"email": "hello@home-assistant.io",
|
"email": "hello@home-assistant.io",
|
||||||
"custom:sub-exp": "2018-01-01",
|
"custom:sub-exp": "2018-01-01",
|
||||||
|
|
|
@ -9,6 +9,7 @@ import pytest
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.cloud import account_link
|
from homeassistant.components.cloud import account_link
|
||||||
|
from homeassistant.components.cloud.const import DATA_CLOUD
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResultType
|
from homeassistant.data_entry_flow import FlowResultType
|
||||||
from homeassistant.helpers import config_entry_oauth2_flow
|
from homeassistant.helpers import config_entry_oauth2_flow
|
||||||
|
@ -133,7 +134,7 @@ async def test_setup_provide_implementation(hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
async def test_get_services_cached(hass: HomeAssistant) -> None:
|
async def test_get_services_cached(hass: HomeAssistant) -> None:
|
||||||
"""Test that we cache services."""
|
"""Test that we cache services."""
|
||||||
hass.data["cloud"] = None
|
hass.data[DATA_CLOUD] = None
|
||||||
|
|
||||||
services = 1
|
services = 1
|
||||||
|
|
||||||
|
@ -165,7 +166,7 @@ async def test_get_services_cached(hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
async def test_get_services_error(hass: HomeAssistant) -> None:
|
async def test_get_services_error(hass: HomeAssistant) -> None:
|
||||||
"""Test that we cache services."""
|
"""Test that we cache services."""
|
||||||
hass.data["cloud"] = None
|
hass.data[DATA_CLOUD] = None
|
||||||
|
|
||||||
with (
|
with (
|
||||||
patch.object(account_link, "CACHE_TIMEOUT", 0),
|
patch.object(account_link, "CACHE_TIMEOUT", 0),
|
||||||
|
@ -181,7 +182,7 @@ async def test_get_services_error(hass: HomeAssistant) -> None:
|
||||||
@pytest.mark.usefixtures("current_request_with_host")
|
@pytest.mark.usefixtures("current_request_with_host")
|
||||||
async def test_implementation(hass: HomeAssistant, flow_handler) -> None:
|
async def test_implementation(hass: HomeAssistant, flow_handler) -> None:
|
||||||
"""Test Cloud OAuth2 implementation."""
|
"""Test Cloud OAuth2 implementation."""
|
||||||
hass.data["cloud"] = None
|
hass.data[DATA_CLOUD] = None
|
||||||
|
|
||||||
impl = account_link.CloudOAuth2Implementation(hass, "test")
|
impl = account_link.CloudOAuth2Implementation(hass, "test")
|
||||||
assert impl.name == "Home Assistant Cloud"
|
assert impl.name == "Home Assistant Cloud"
|
||||||
|
|
|
@ -8,6 +8,7 @@ import pytest
|
||||||
from homeassistant.components.alexa import errors
|
from homeassistant.components.alexa import errors
|
||||||
from homeassistant.components.cloud import ALEXA_SCHEMA, alexa_config
|
from homeassistant.components.cloud import ALEXA_SCHEMA, alexa_config
|
||||||
from homeassistant.components.cloud.const import (
|
from homeassistant.components.cloud.const import (
|
||||||
|
DATA_CLOUD,
|
||||||
PREF_ALEXA_DEFAULT_EXPOSE,
|
PREF_ALEXA_DEFAULT_EXPOSE,
|
||||||
PREF_ALEXA_ENTITY_CONFIGS,
|
PREF_ALEXA_ENTITY_CONFIGS,
|
||||||
PREF_SHOULD_EXPOSE,
|
PREF_SHOULD_EXPOSE,
|
||||||
|
@ -425,7 +426,7 @@ async def test_alexa_entity_registry_sync(
|
||||||
expose_new(hass, True)
|
expose_new(hass, True)
|
||||||
|
|
||||||
await alexa_config.CloudAlexaConfig(
|
await alexa_config.CloudAlexaConfig(
|
||||||
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
).async_initialize()
|
).async_initialize()
|
||||||
|
|
||||||
with patch_sync_helper() as (to_update, to_remove):
|
with patch_sync_helper() as (to_update, to_remove):
|
||||||
|
@ -506,11 +507,11 @@ def test_enabled_requires_valid_sub(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that alexa config enabled requires a valid Cloud sub."""
|
"""Test that alexa config enabled requires a valid Cloud sub."""
|
||||||
assert cloud_prefs.alexa_enabled
|
assert cloud_prefs.alexa_enabled
|
||||||
assert hass.data["cloud"].is_logged_in
|
assert hass.data[DATA_CLOUD].is_logged_in
|
||||||
assert hass.data["cloud"].subscription_expired
|
assert hass.data[DATA_CLOUD].subscription_expired
|
||||||
|
|
||||||
config = alexa_config.CloudAlexaConfig(
|
config = alexa_config.CloudAlexaConfig(
|
||||||
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not config.enabled
|
assert not config.enabled
|
||||||
|
|
|
@ -15,6 +15,7 @@ from homeassistant.components.cloud.client import (
|
||||||
CloudClient,
|
CloudClient,
|
||||||
)
|
)
|
||||||
from homeassistant.components.cloud.const import (
|
from homeassistant.components.cloud.const import (
|
||||||
|
DATA_CLOUD,
|
||||||
PREF_ALEXA_REPORT_STATE,
|
PREF_ALEXA_REPORT_STATE,
|
||||||
PREF_ENABLE_ALEXA,
|
PREF_ENABLE_ALEXA,
|
||||||
PREF_ENABLE_GOOGLE,
|
PREF_ENABLE_GOOGLE,
|
||||||
|
@ -63,7 +64,7 @@ async def test_handler_alexa(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_cloud_prefs(hass, {PREF_ALEXA_REPORT_STATE: False})
|
mock_cloud_prefs(hass, {PREF_ALEXA_REPORT_STATE: False})
|
||||||
cloud = hass.data["cloud"]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
resp = await cloud.client.async_alexa_message(
|
resp = await cloud.client.async_alexa_message(
|
||||||
test_alexa.get_new_request("Alexa.Discovery", "Discover")
|
test_alexa.get_new_request("Alexa.Discovery", "Discover")
|
||||||
|
@ -83,7 +84,7 @@ async def test_handler_alexa(hass: HomeAssistant) -> None:
|
||||||
async def test_handler_alexa_disabled(hass: HomeAssistant, mock_cloud_fixture) -> None:
|
async def test_handler_alexa_disabled(hass: HomeAssistant, mock_cloud_fixture) -> None:
|
||||||
"""Test handler Alexa when user has disabled it."""
|
"""Test handler Alexa when user has disabled it."""
|
||||||
mock_cloud_fixture._prefs[PREF_ENABLE_ALEXA] = False
|
mock_cloud_fixture._prefs[PREF_ENABLE_ALEXA] = False
|
||||||
cloud = hass.data["cloud"]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
resp = await cloud.client.async_alexa_message(
|
resp = await cloud.client.async_alexa_message(
|
||||||
test_alexa.get_new_request("Alexa.Discovery", "Discover")
|
test_alexa.get_new_request("Alexa.Discovery", "Discover")
|
||||||
|
@ -117,7 +118,7 @@ async def test_handler_google_actions(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_cloud_prefs(hass, {})
|
mock_cloud_prefs(hass, {})
|
||||||
cloud = hass.data["cloud"]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
reqid = "5711642932632160983"
|
reqid = "5711642932632160983"
|
||||||
data = {"requestId": reqid, "inputs": [{"intent": "action.devices.SYNC"}]}
|
data = {"requestId": reqid, "inputs": [{"intent": "action.devices.SYNC"}]}
|
||||||
|
@ -164,7 +165,7 @@ async def test_handler_google_actions_disabled(
|
||||||
reqid = "5711642932632160983"
|
reqid = "5711642932632160983"
|
||||||
data = {"requestId": reqid, "inputs": [{"intent": intent}]}
|
data = {"requestId": reqid, "inputs": [{"intent": intent}]}
|
||||||
|
|
||||||
cloud = hass.data["cloud"]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
with patch(
|
with patch(
|
||||||
"hass_nabucasa.Cloud._decode_claims",
|
"hass_nabucasa.Cloud._decode_claims",
|
||||||
return_value={"cognito:username": "myUserName"},
|
return_value={"cognito:username": "myUserName"},
|
||||||
|
@ -182,7 +183,7 @@ async def test_webhook_msg(
|
||||||
with patch("hass_nabucasa.Cloud.initialize"):
|
with patch("hass_nabucasa.Cloud.initialize"):
|
||||||
setup = await async_setup_component(hass, "cloud", {"cloud": {}})
|
setup = await async_setup_component(hass, "cloud", {"cloud": {}})
|
||||||
assert setup
|
assert setup
|
||||||
cloud = hass.data["cloud"]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
await cloud.client.prefs.async_initialize()
|
await cloud.client.prefs.async_initialize()
|
||||||
await cloud.client.prefs.async_update(
|
await cloud.client.prefs.async_update(
|
||||||
|
@ -269,7 +270,7 @@ async def test_google_config_expose_entity(
|
||||||
"light", "test", "unique", suggested_object_id="kitchen"
|
"light", "test", "unique", suggested_object_id="kitchen"
|
||||||
)
|
)
|
||||||
|
|
||||||
cloud_client = hass.data[DOMAIN].client
|
cloud_client = hass.data[DATA_CLOUD].client
|
||||||
state = State(entity_entry.entity_id, "on")
|
state = State(entity_entry.entity_id, "on")
|
||||||
gconf = await cloud_client.get_google_config()
|
gconf = await cloud_client.get_google_config()
|
||||||
|
|
||||||
|
@ -293,7 +294,7 @@ async def test_google_config_should_2fa(
|
||||||
"light", "test", "unique", suggested_object_id="kitchen"
|
"light", "test", "unique", suggested_object_id="kitchen"
|
||||||
)
|
)
|
||||||
|
|
||||||
cloud_client = hass.data[DOMAIN].client
|
cloud_client = hass.data[DATA_CLOUD].client
|
||||||
gconf = await cloud_client.get_google_config()
|
gconf = await cloud_client.get_google_config()
|
||||||
state = State(entity_entry.entity_id, "on")
|
state = State(entity_entry.entity_id, "on")
|
||||||
|
|
||||||
|
@ -350,7 +351,7 @@ async def test_system_msg(hass: HomeAssistant) -> None:
|
||||||
with patch("hass_nabucasa.Cloud.initialize"):
|
with patch("hass_nabucasa.Cloud.initialize"):
|
||||||
setup = await async_setup_component(hass, "cloud", {"cloud": {}})
|
setup = await async_setup_component(hass, "cloud", {"cloud": {}})
|
||||||
assert setup
|
assert setup
|
||||||
cloud = hass.data["cloud"]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
assert cloud.client.relayer_region is None
|
assert cloud.client.relayer_region is None
|
||||||
|
|
||||||
|
@ -373,7 +374,7 @@ async def test_cloud_connection_info(hass: HomeAssistant) -> None:
|
||||||
hexmock.return_value = "12345678901234567890"
|
hexmock.return_value = "12345678901234567890"
|
||||||
setup = await async_setup_component(hass, "cloud", {"cloud": {}})
|
setup = await async_setup_component(hass, "cloud", {"cloud": {}})
|
||||||
assert setup
|
assert setup
|
||||||
cloud = hass.data["cloud"]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
response = await cloud.client.async_cloud_connection_info({})
|
response = await cloud.client.async_cloud_connection_info({})
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import pytest
|
||||||
|
|
||||||
from homeassistant.components.cloud import GACTIONS_SCHEMA
|
from homeassistant.components.cloud import GACTIONS_SCHEMA
|
||||||
from homeassistant.components.cloud.const import (
|
from homeassistant.components.cloud.const import (
|
||||||
|
DATA_CLOUD,
|
||||||
PREF_DISABLE_2FA,
|
PREF_DISABLE_2FA,
|
||||||
PREF_GOOGLE_DEFAULT_EXPOSE,
|
PREF_GOOGLE_DEFAULT_EXPOSE,
|
||||||
PREF_GOOGLE_ENTITY_CONFIGS,
|
PREF_GOOGLE_ENTITY_CONFIGS,
|
||||||
|
@ -196,7 +197,7 @@ async def test_google_entity_registry_sync(
|
||||||
expose_new(hass, True)
|
expose_new(hass, True)
|
||||||
|
|
||||||
config = CloudGoogleConfig(
|
config = CloudGoogleConfig(
|
||||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
)
|
)
|
||||||
await config.async_initialize()
|
await config.async_initialize()
|
||||||
await config.async_connect_agent_user("mock-user-id")
|
await config.async_connect_agent_user("mock-user-id")
|
||||||
|
@ -264,7 +265,7 @@ async def test_google_device_registry_sync(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test Google config responds to device registry."""
|
"""Test Google config responds to device registry."""
|
||||||
config = CloudGoogleConfig(
|
config = CloudGoogleConfig(
|
||||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable exposing new entities to Google
|
# Enable exposing new entities to Google
|
||||||
|
@ -333,7 +334,7 @@ async def test_sync_google_when_started(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test Google config syncs on init."""
|
"""Test Google config syncs on init."""
|
||||||
config = CloudGoogleConfig(
|
config = CloudGoogleConfig(
|
||||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
)
|
)
|
||||||
with patch.object(config, "async_sync_entities_all") as mock_sync:
|
with patch.object(config, "async_sync_entities_all") as mock_sync:
|
||||||
await config.async_initialize()
|
await config.async_initialize()
|
||||||
|
@ -346,7 +347,7 @@ async def test_sync_google_on_home_assistant_start(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test Google config syncs when home assistant started."""
|
"""Test Google config syncs when home assistant started."""
|
||||||
config = CloudGoogleConfig(
|
config = CloudGoogleConfig(
|
||||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
)
|
)
|
||||||
hass.set_state(CoreState.not_running)
|
hass.set_state(CoreState.not_running)
|
||||||
with patch.object(config, "async_sync_entities_all") as mock_sync:
|
with patch.object(config, "async_sync_entities_all") as mock_sync:
|
||||||
|
@ -441,11 +442,11 @@ def test_enabled_requires_valid_sub(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that google config enabled requires a valid Cloud sub."""
|
"""Test that google config enabled requires a valid Cloud sub."""
|
||||||
assert cloud_prefs.google_enabled
|
assert cloud_prefs.google_enabled
|
||||||
assert hass.data["cloud"].is_logged_in
|
assert hass.data[DATA_CLOUD].is_logged_in
|
||||||
assert hass.data["cloud"].subscription_expired
|
assert hass.data[DATA_CLOUD].subscription_expired
|
||||||
|
|
||||||
config = CloudGoogleConfig(
|
config = CloudGoogleConfig(
|
||||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
)
|
)
|
||||||
|
|
||||||
assert not config.enabled
|
assert not config.enabled
|
||||||
|
@ -494,7 +495,7 @@ async def test_google_handle_logout(
|
||||||
await cloud_prefs.get_cloud_user()
|
await cloud_prefs.get_cloud_user()
|
||||||
|
|
||||||
with patch.object(
|
with patch.object(
|
||||||
hass.data["cloud"].auth,
|
hass.data[DATA_CLOUD].auth,
|
||||||
"async_check_token",
|
"async_check_token",
|
||||||
side_effect=AssertionError("Should not be called"),
|
side_effect=AssertionError("Should not be called"),
|
||||||
):
|
):
|
||||||
|
@ -857,7 +858,7 @@ async def test_google_config_get_agent_user_id(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test overridden get_agent_user_id_from_webhook method."""
|
"""Test overridden get_agent_user_id_from_webhook method."""
|
||||||
config = CloudGoogleConfig(
|
config = CloudGoogleConfig(
|
||||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data[DATA_CLOUD]
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
config.get_agent_user_id_from_webhook(cloud_prefs.google_local_webhook_id)
|
config.get_agent_user_id_from_webhook(cloud_prefs.google_local_webhook_id)
|
||||||
|
|
|
@ -4,7 +4,6 @@ from collections.abc import Callable, Coroutine
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from hass_nabucasa import Cloud
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components import cloud
|
from homeassistant.components import cloud
|
||||||
|
@ -13,7 +12,7 @@ from homeassistant.components.cloud import (
|
||||||
CloudNotConnected,
|
CloudNotConnected,
|
||||||
async_get_or_create_cloudhook,
|
async_get_or_create_cloudhook,
|
||||||
)
|
)
|
||||||
from homeassistant.components.cloud.const import DOMAIN, PREF_CLOUDHOOKS
|
from homeassistant.components.cloud.const import DATA_CLOUD, DOMAIN, PREF_CLOUDHOOKS
|
||||||
from homeassistant.components.cloud.prefs import STORAGE_KEY
|
from homeassistant.components.cloud.prefs import STORAGE_KEY
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import Context, HomeAssistant
|
from homeassistant.core import Context, HomeAssistant
|
||||||
|
@ -47,7 +46,7 @@ async def test_constructor_loads_info_from_config(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
assert result
|
assert result
|
||||||
|
|
||||||
cl = hass.data["cloud"]
|
cl = hass.data[DATA_CLOUD]
|
||||||
assert cl.mode == cloud.MODE_DEV
|
assert cl.mode == cloud.MODE_DEV
|
||||||
assert cl.cognito_client_id == "test-cognito_client_id"
|
assert cl.cognito_client_id == "test-cognito_client_id"
|
||||||
assert cl.user_pool_id == "test-user_pool_id"
|
assert cl.user_pool_id == "test-user_pool_id"
|
||||||
|
@ -65,7 +64,7 @@ async def test_remote_services(
|
||||||
hass: HomeAssistant, mock_cloud_fixture, hass_read_only_user: MockUser
|
hass: HomeAssistant, mock_cloud_fixture, hass_read_only_user: MockUser
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Setup cloud component and test services."""
|
"""Setup cloud component and test services."""
|
||||||
cloud = hass.data[DOMAIN]
|
cloud = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
assert hass.services.has_service(DOMAIN, "remote_connect")
|
assert hass.services.has_service(DOMAIN, "remote_connect")
|
||||||
assert hass.services.has_service(DOMAIN, "remote_disconnect")
|
assert hass.services.has_service(DOMAIN, "remote_disconnect")
|
||||||
|
@ -145,7 +144,7 @@ async def test_setup_existing_cloud_user(
|
||||||
|
|
||||||
async def test_on_connect(hass: HomeAssistant, mock_cloud_fixture) -> None:
|
async def test_on_connect(hass: HomeAssistant, mock_cloud_fixture) -> None:
|
||||||
"""Test cloud on connect triggers."""
|
"""Test cloud on connect triggers."""
|
||||||
cl: Cloud[cloud.client.CloudClient] = hass.data["cloud"]
|
cl = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
assert len(cl.iot._on_connect) == 3
|
assert len(cl.iot._on_connect) == 3
|
||||||
|
|
||||||
|
@ -202,7 +201,7 @@ async def test_on_connect(hass: HomeAssistant, mock_cloud_fixture) -> None:
|
||||||
|
|
||||||
async def test_remote_ui_url(hass: HomeAssistant, mock_cloud_fixture) -> None:
|
async def test_remote_ui_url(hass: HomeAssistant, mock_cloud_fixture) -> None:
|
||||||
"""Test getting remote ui url."""
|
"""Test getting remote ui url."""
|
||||||
cl = hass.data["cloud"]
|
cl = hass.data[DATA_CLOUD]
|
||||||
|
|
||||||
# Not logged in
|
# Not logged in
|
||||||
with pytest.raises(cloud.CloudNotAvailable):
|
with pytest.raises(cloud.CloudNotAvailable):
|
||||||
|
|
Loading…
Reference in New Issue