-
-
Notifications
You must be signed in to change notification settings - Fork 37.4k
Add allowed UUIDs and ignore CEC to Google Cast options flow #47269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
17151f8
d80b8ea
fe07c9f
cf4d297
be3c4ad
4487596
fa14da8
cc305b9
090194d
7ea9378
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,42 @@ | ||
| """Component to embed Google Cast.""" | ||
| import logging | ||
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant import config_entries | ||
| from homeassistant.helpers import config_validation as cv | ||
|
|
||
| from . import home_assistant_cast | ||
| from .const import DOMAIN | ||
| from .media_player import ENTITY_SCHEMA | ||
|
|
||
| # Deprecated from 2021.4, remove in 2021.6 | ||
| CONFIG_SCHEMA = cv.deprecated(DOMAIN) | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| async def async_setup(hass, config): | ||
| """Set up the Cast component.""" | ||
| conf = config.get(DOMAIN) | ||
|
|
||
| hass.data[DOMAIN] = conf or {} | ||
|
|
||
| if conf is not None: | ||
| media_player_config_validated = [] | ||
| media_player_config = conf.get("media_player", {}) | ||
| if not isinstance(media_player_config, list): | ||
| media_player_config = [media_player_config] | ||
| for cfg in media_player_config: | ||
| try: | ||
| cfg = ENTITY_SCHEMA(cfg) | ||
| media_player_config_validated.append(cfg) | ||
| except vol.Error as ex: | ||
| _LOGGER.warning("Invalid config '%s': %s", cfg, ex) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we accept a partial valid config to be more backwards compatible? The alternative would be to extend the config schema instead which would fail the whole config on invalid result.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the intention is to accept a partial valid config by simply skipping invalid media players instead of rejecting the entire config. |
||
|
|
||
| hass.async_create_task( | ||
| hass.config_entries.flow.async_init( | ||
| DOMAIN, context={"source": config_entries.SOURCE_IMPORT} | ||
| DOMAIN, | ||
| context={"source": config_entries.SOURCE_IMPORT}, | ||
| data=media_player_config_validated, | ||
| ) | ||
| ) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,6 @@ | ||
| """Provide functionality to interact with Cast devices on the network.""" | ||
| from __future__ import annotations | ||
|
|
||
| import asyncio | ||
| from contextlib import suppress | ||
| from datetime import timedelta | ||
| import functools as ft | ||
|
|
@@ -52,19 +51,19 @@ | |
| STATE_PLAYING, | ||
| ) | ||
| from homeassistant.core import callback | ||
| from homeassistant.exceptions import PlatformNotReady | ||
| import homeassistant.helpers.config_validation as cv | ||
| from homeassistant.helpers.dispatcher import async_dispatcher_connect | ||
| from homeassistant.helpers.network import NoURLAvailableError, get_url | ||
| from homeassistant.helpers.typing import ConfigType, HomeAssistantType | ||
| from homeassistant.helpers.typing import HomeAssistantType | ||
| import homeassistant.util.dt as dt_util | ||
| from homeassistant.util.logging import async_create_catching_coro | ||
|
|
||
| from .const import ( | ||
| ADDED_CAST_DEVICES_KEY, | ||
| CAST_MULTIZONE_MANAGER_KEY, | ||
| CONF_IGNORE_CEC, | ||
| CONF_UUID, | ||
| DOMAIN as CAST_DOMAIN, | ||
| KNOWN_CHROMECAST_INFO_KEY, | ||
| SIGNAL_CAST_DISCOVERED, | ||
| SIGNAL_CAST_REMOVED, | ||
| SIGNAL_HASS_CAST_SHOW_VIEW, | ||
|
|
@@ -74,8 +73,6 @@ | |
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| CONF_IGNORE_CEC = "ignore_cec" | ||
| CONF_UUID = "uuid" | ||
| CAST_SPLASH = "https://www.home-assistant.io/images/cast/splash.png" | ||
|
|
||
| SUPPORT_CAST = ( | ||
|
|
@@ -129,57 +126,27 @@ def _async_create_cast_device(hass: HomeAssistantType, info: ChromecastInfo): | |
|
|
||
| async def async_setup_entry(hass, config_entry, async_add_entities): | ||
| """Set up Cast from a config entry.""" | ||
| config = hass.data[CAST_DOMAIN].get("media_player") or {} | ||
| if not isinstance(config, list): | ||
| config = [config] | ||
|
|
||
| # no pending task | ||
| done, _ = await asyncio.wait( | ||
| [ | ||
| _async_setup_platform( | ||
| hass, ENTITY_SCHEMA(cfg), async_add_entities, config_entry | ||
| ) | ||
| for cfg in config | ||
| ] | ||
| ) | ||
| if any(task.exception() for task in done): | ||
| exceptions = [task.exception() for task in done] | ||
| for exception in exceptions: | ||
| _LOGGER.debug("Failed to setup chromecast", exc_info=exception) | ||
| raise PlatformNotReady | ||
|
|
||
|
|
||
| async def _async_setup_platform( | ||
| hass: HomeAssistantType, config: ConfigType, async_add_entities, config_entry | ||
| ): | ||
| """Set up the cast platform.""" | ||
| # Import CEC IGNORE attributes | ||
| pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) | ||
| hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set()) | ||
| hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, {}) | ||
|
|
||
| wanted_uuid = None | ||
| if CONF_UUID in config: | ||
| wanted_uuid = config[CONF_UUID] | ||
| # Import CEC IGNORE attributes | ||
| pychromecast.IGNORE_CEC += config_entry.data.get(CONF_IGNORE_CEC) or [] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a bit weird that we're modifying a constant.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but that's how the lib is designed. It could be refactored to a more sane API, with a setter function, but not in this PR. |
||
|
|
||
| wanted_uuids = config_entry.data.get(CONF_UUID) or None | ||
|
|
||
| @callback | ||
| def async_cast_discovered(discover: ChromecastInfo) -> None: | ||
| """Handle discovery of a new chromecast.""" | ||
| # If wanted_uuid is set, we're handling a specific cast device identified by UUID | ||
| if wanted_uuid is not None and wanted_uuid != discover.uuid: | ||
| # UUID not matching, this is not it. | ||
| # If wanted_uuids is set, we're only accepting specific cast devices identified | ||
| # by UUID | ||
| if wanted_uuids is not None and discover.uuid not in wanted_uuids: | ||
| # UUID not matching, ignore. | ||
| return | ||
|
|
||
| cast_device = _async_create_cast_device(hass, discover) | ||
| if cast_device is not None: | ||
| async_add_entities([cast_device]) | ||
|
|
||
| async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) | ||
| # Re-play the callback for all past chromecasts, store the objects in | ||
| # a list to avoid concurrent modification resulting in exception. | ||
| for chromecast in hass.data[KNOWN_CHROMECAST_INFO_KEY].values(): | ||
| async_cast_discovered(chromecast) | ||
|
|
||
| ChromeCastZeroconf.set_zeroconf(await zeroconf.async_get_instance(hass)) | ||
| hass.async_add_executor_job(setup_internal_discovery, hass, config_entry) | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, we had no config schema to begin with and just passed that to import? 🤔