Bump pychromecast to 7.0.1 (#37225)

* Bump pychromecast to 7.0.1

* Fix tests

* Mark configuration via platform for removal in 0.116

* Fix uuid check
pull/37104/head
Erik Montnemery 2020-06-30 16:35:10 +02:00 committed by GitHub
parent 333dccc7af
commit 86c27b50f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 213 additions and 144 deletions

View File

@ -21,20 +21,16 @@ _LOGGER = logging.getLogger(__name__)
def discover_chromecast(hass: HomeAssistant, info: ChromecastInfo): def discover_chromecast(hass: HomeAssistant, info: ChromecastInfo):
"""Discover a Chromecast.""" """Discover a Chromecast."""
if info in hass.data[KNOWN_CHROMECAST_INFO_KEY]: if info.uuid is None:
_LOGGER.debug("Discovered previous chromecast %s", info) _LOGGER.error("Discovered chromecast without uuid %s", info)
return
# Either discovered completely new chromecast or a "moved" one. if info.uuid in hass.data[KNOWN_CHROMECAST_INFO_KEY]:
_LOGGER.debug("Discovered chromecast %s", info) _LOGGER.debug("Discovered update for known chromecast %s", info)
else:
_LOGGER.debug("Discovered chromecast %s", info)
if info.uuid is not None: hass.data[KNOWN_CHROMECAST_INFO_KEY][info.uuid] = info
# Remove previous cast infos with same uuid from known chromecasts.
same_uuid = {
x for x in hass.data[KNOWN_CHROMECAST_INFO_KEY] if info.uuid == x.uuid
}
hass.data[KNOWN_CHROMECAST_INFO_KEY] -= same_uuid
hass.data[KNOWN_CHROMECAST_INFO_KEY].add(info)
dispatcher_send(hass, SIGNAL_CAST_DISCOVERED, info) dispatcher_send(hass, SIGNAL_CAST_DISCOVERED, info)
@ -54,47 +50,72 @@ def setup_internal_discovery(hass: HomeAssistant) -> None:
# Internal discovery is already running # Internal discovery is already running
return return
def internal_add_callback(name): def internal_add_update_callback(uuid, service_name):
"""Handle zeroconf discovery of a new chromecast.""" """Handle zeroconf discovery of a new or updated chromecast."""
mdns = listener.services[name] service = listener.services[uuid]
# For support of deprecated IP based white listing
zconf = ChromeCastZeroconf.get_zeroconf()
service_info = None
tries = 0
while service_info is None and tries < 4:
try:
service_info = zconf.get_service_info(
"_googlecast._tcp.local.", service_name
)
except OSError:
# If the zeroconf fails to receive the necessary data we abort
# adding the service
break
tries += 1
if not service_info:
_LOGGER.warning(
"setup_internal_discovery failed to get info for %s, %s",
uuid,
service_name,
)
return
addresses = service_info.parsed_addresses()
host = addresses[0] if addresses else service_info.server
discover_chromecast( discover_chromecast(
hass, hass,
ChromecastInfo( ChromecastInfo(
service=name, services=service[0],
host=mdns[0], uuid=service[1],
port=mdns[1], model_name=service[2],
uuid=mdns[2], friendly_name=service[3],
model_name=mdns[3], host=host,
friendly_name=mdns[4], port=service_info.port,
), ),
) )
def internal_remove_callback(name, mdns): def internal_remove_callback(uuid, service_name, service):
"""Handle zeroconf discovery of a removed chromecast.""" """Handle zeroconf discovery of a removed chromecast."""
_remove_chromecast( _remove_chromecast(
hass, hass,
ChromecastInfo( ChromecastInfo(
service=name, services=service[0],
host=mdns[0], uuid=service[1],
port=mdns[1], model_name=service[2],
uuid=mdns[2], friendly_name=service[3],
model_name=mdns[3],
friendly_name=mdns[4],
), ),
) )
_LOGGER.debug("Starting internal pychromecast discovery.") _LOGGER.debug("Starting internal pychromecast discovery.")
listener = pychromecast.CastListener( listener = pychromecast.CastListener(
internal_add_callback, internal_add_update_callback,
internal_remove_callback, internal_remove_callback,
internal_add_callback, # Use internal_add_callback also for updates internal_add_update_callback,
) )
browser = pychromecast.start_discovery(listener, ChromeCastZeroconf.get_zeroconf()) browser = pychromecast.start_discovery(listener, ChromeCastZeroconf.get_zeroconf())
def stop_discovery(event): def stop_discovery(event):
"""Stop discovery of new chromecasts.""" """Stop discovery of new chromecasts."""
_LOGGER.debug("Stopping internal pychromecast discovery.") _LOGGER.debug("Stopping internal pychromecast discovery.")
pychromecast.stop_discovery(browser) pychromecast.discovery.stop_discovery(browser)
hass.data[INTERNAL_DISCOVERY_RUNNING_KEY].release() hass.data[INTERNAL_DISCOVERY_RUNNING_KEY].release()
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_discovery) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_discovery)

View File

@ -14,9 +14,9 @@ class ChromecastInfo:
This also has the same attributes as the mDNS fields by zeroconf. This also has the same attributes as the mDNS fields by zeroconf.
""" """
host = attr.ib(type=str) services = attr.ib(type=Optional[set])
port = attr.ib(type=int) host = attr.ib(type=Optional[str], default=None)
service = attr.ib(type=Optional[str], default=None) port = attr.ib(type=Optional[int], default=0)
uuid = attr.ib( uuid = attr.ib(
type=Optional[str], converter=attr.converters.optional(str), default=None type=Optional[str], converter=attr.converters.optional(str), default=None
) # always convert UUID to string if not None ) # always convert UUID to string if not None

View File

@ -3,7 +3,7 @@
"name": "Google Cast", "name": "Google Cast",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/cast", "documentation": "https://www.home-assistant.io/integrations/cast",
"requirements": ["pychromecast==6.0.0"], "requirements": ["pychromecast==7.0.1"],
"after_dependencies": ["cloud","zeroconf"], "after_dependencies": ["cloud","zeroconf"],
"zeroconf": ["_googlecast._tcp.local."], "zeroconf": ["_googlecast._tcp.local."],
"codeowners": ["@emontnemery"] "codeowners": ["@emontnemery"]

View File

@ -55,7 +55,6 @@ from .const import (
DOMAIN as CAST_DOMAIN, DOMAIN as CAST_DOMAIN,
KNOWN_CHROMECAST_INFO_KEY, KNOWN_CHROMECAST_INFO_KEY,
SIGNAL_CAST_DISCOVERED, SIGNAL_CAST_DISCOVERED,
SIGNAL_CAST_REMOVED,
SIGNAL_HASS_CAST_SHOW_VIEW, SIGNAL_HASS_CAST_SHOW_VIEW,
) )
from .discovery import setup_internal_discovery from .discovery import setup_internal_discovery
@ -64,6 +63,7 @@ from .helpers import CastStatusListener, ChromecastInfo, ChromeCastZeroconf
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CONF_IGNORE_CEC = "ignore_cec" CONF_IGNORE_CEC = "ignore_cec"
CONF_UUID = "uuid"
CAST_SPLASH = "https://www.home-assistant.io/images/cast/splash.png" CAST_SPLASH = "https://www.home-assistant.io/images/cast/splash.png"
SUPPORT_CAST = ( SUPPORT_CAST = (
@ -78,11 +78,26 @@ SUPPORT_CAST = (
) )
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( ENTITY_SCHEMA = vol.All(
{ cv.deprecated(CONF_HOST, invalidation_version="0.116"),
vol.Optional(CONF_HOST): cv.string, vol.Schema(
vol.Optional(CONF_IGNORE_CEC, default=[]): vol.All(cv.ensure_list, [cv.string]), {
} vol.Exclusive(CONF_HOST, "device_identifier"): cv.string,
vol.Exclusive(CONF_UUID, "device_identifier"): cv.string,
vol.Optional(CONF_IGNORE_CEC): vol.All(cv.ensure_list, [cv.string]),
}
),
)
PLATFORM_SCHEMA = vol.All(
cv.deprecated(CONF_HOST, invalidation_version="0.116"),
PLATFORM_SCHEMA.extend(
{
vol.Exclusive(CONF_HOST, "device_identifier"): cv.string,
vol.Exclusive(CONF_UUID, "device_identifier"): cv.string,
vol.Optional(CONF_IGNORE_CEC): vol.All(cv.ensure_list, [cv.string]),
}
),
) )
@ -111,13 +126,14 @@ def _async_create_cast_device(hass: HomeAssistantType, info: ChromecastInfo):
async def async_setup_platform( async def async_setup_platform(
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
): ):
"""Set up thet Cast platform. """Set up the Cast platform.
Deprecated. Deprecated.
""" """
_LOGGER.warning( _LOGGER.warning(
"Setting configuration for Cast via platform is deprecated. " "Setting configuration for Cast via platform is deprecated. "
"Configure via Cast integration instead." "Configure via Cast integration instead."
"This option will become invalid in version 0.116."
) )
await _async_setup_platform(hass, config, async_add_entities, discovery_info) await _async_setup_platform(hass, config, async_add_entities, discovery_info)
@ -130,7 +146,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
# no pending task # no pending task
done, _ = await asyncio.wait( done, _ = await asyncio.wait(
[_async_setup_platform(hass, cfg, async_add_entities, None) for cfg in config] [
_async_setup_platform(hass, ENTITY_SCHEMA(cfg), async_add_entities, None)
for cfg in config
]
) )
if any([task.exception() for task in done]): if any([task.exception() for task in done]):
exceptions = [task.exception() for task in done] exceptions = [task.exception() for task in done]
@ -146,18 +165,25 @@ async def _async_setup_platform(
# Import CEC IGNORE attributes # Import CEC IGNORE attributes
pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set()) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set())
hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set()) hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, dict())
info = None info = None
if discovery_info is not None: if discovery_info is not None:
info = ChromecastInfo(host=discovery_info["host"], port=discovery_info["port"]) info = ChromecastInfo(
host=discovery_info["host"], port=discovery_info["port"], services=None
)
elif CONF_UUID in config:
info = ChromecastInfo(uuid=config[CONF_UUID], services=None)
elif CONF_HOST in config: elif CONF_HOST in config:
info = ChromecastInfo(host=config[CONF_HOST], port=DEFAULT_PORT) info = ChromecastInfo(host=config[CONF_HOST], port=DEFAULT_PORT, services=None)
@callback @callback
def async_cast_discovered(discover: ChromecastInfo) -> None: def async_cast_discovered(discover: ChromecastInfo) -> None:
"""Handle discovery of a new chromecast.""" """Handle discovery of a new chromecast."""
if info is not None and info.host_port != discover.host_port: if info is not None and (
(info.uuid is not None and info.uuid != discover.uuid)
or (info.host is not None and info.host_port != discover.host_port)
):
# Waiting for a specific cast device, this is not it. # Waiting for a specific cast device, this is not it.
return return
@ -168,7 +194,7 @@ async def _async_setup_platform(
async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered)
# Re-play the callback for all past chromecasts, store the objects in # Re-play the callback for all past chromecasts, store the objects in
# a list to avoid concurrent modification resulting in exception. # a list to avoid concurrent modification resulting in exception.
for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]): for chromecast in hass.data[KNOWN_CHROMECAST_INFO_KEY].values():
async_cast_discovered(chromecast) async_cast_discovered(chromecast)
ChromeCastZeroconf.set_zeroconf(await zeroconf.async_get_instance(hass)) ChromeCastZeroconf.set_zeroconf(await zeroconf.async_get_instance(hass))
@ -187,10 +213,7 @@ class CastDevice(MediaPlayerEntity):
"""Initialize the cast device.""" """Initialize the cast device."""
self._cast_info = cast_info self._cast_info = cast_info
self.services = None self.services = cast_info.services
if cast_info.service:
self.services = set()
self.services.add(cast_info.service)
self._chromecast: Optional[pychromecast.Chromecast] = None self._chromecast: Optional[pychromecast.Chromecast] = None
self.cast_status = None self.cast_status = None
self.media_status = None self.media_status = None
@ -211,9 +234,6 @@ class CastDevice(MediaPlayerEntity):
self._add_remove_handler = async_dispatcher_connect( self._add_remove_handler = async_dispatcher_connect(
self.hass, SIGNAL_CAST_DISCOVERED, self._async_cast_discovered self.hass, SIGNAL_CAST_DISCOVERED, self._async_cast_discovered
) )
self._del_remove_handler = async_dispatcher_connect(
self.hass, SIGNAL_CAST_REMOVED, self._async_cast_removed
)
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self._async_stop) self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self._async_stop)
self.hass.async_create_task( self.hass.async_create_task(
async_create_catching_coro(self.async_set_cast_info(self._cast_info)) async_create_catching_coro(self.async_set_cast_info(self._cast_info))
@ -245,42 +265,26 @@ class CastDevice(MediaPlayerEntity):
self._cast_info = cast_info self._cast_info = cast_info
if self.services is not None:
if cast_info.service not in self.services:
_LOGGER.debug(
"[%s %s (%s:%s)] Got new service: %s (%s)",
self.entity_id,
self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
cast_info.service,
self.services,
)
self.services.add(cast_info.service)
if self._chromecast is not None: if self._chromecast is not None:
# Only setup the chromecast once, added elements to services # Only setup the chromecast once, added elements to services
# will automatically be picked up. # will automatically be picked up.
return return
_LOGGER.debug( _LOGGER.debug(
"[%s %s (%s:%s)] Connecting to cast device by service %s", "[%s %s] Connecting to cast device by service %s",
self.entity_id, self.entity_id,
self._cast_info.friendly_name, self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
self.services, self.services,
) )
chromecast = await self.hass.async_add_executor_job( chromecast = await self.hass.async_add_executor_job(
pychromecast.get_chromecast_from_service, pychromecast.get_chromecast_from_service,
( (
self.services, self.services,
ChromeCastZeroconf.get_zeroconf(),
cast_info.uuid, cast_info.uuid,
cast_info.model_name, cast_info.model_name,
cast_info.friendly_name, cast_info.friendly_name,
), ),
ChromeCastZeroconf.get_zeroconf(),
) )
self._chromecast = chromecast self._chromecast = chromecast
@ -296,30 +300,15 @@ class CastDevice(MediaPlayerEntity):
self._chromecast.start() self._chromecast.start()
self.async_write_ha_state() self.async_write_ha_state()
async def async_del_cast_info(self, cast_info):
"""Remove the service."""
self.services.discard(cast_info.service)
_LOGGER.debug(
"[%s %s (%s:%s)] Remove service: %s (%s)",
self.entity_id,
self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
cast_info.service,
self.services,
)
async def _async_disconnect(self): async def _async_disconnect(self):
"""Disconnect Chromecast object if it is set.""" """Disconnect Chromecast object if it is set."""
if self._chromecast is None: if self._chromecast is None:
# Can't disconnect if not connected. # Can't disconnect if not connected.
return return
_LOGGER.debug( _LOGGER.debug(
"[%s %s (%s:%s)] Disconnecting from chromecast socket.", "[%s %s] Disconnecting from chromecast socket.",
self.entity_id, self.entity_id,
self._cast_info.friendly_name, self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
) )
self._available = False self._available = False
self.async_write_ha_state() self.async_write_ha_state()
@ -359,11 +348,9 @@ class CastDevice(MediaPlayerEntity):
def new_connection_status(self, connection_status): def new_connection_status(self, connection_status):
"""Handle updates of connection status.""" """Handle updates of connection status."""
_LOGGER.debug( _LOGGER.debug(
"[%s %s (%s:%s)] Received cast device connection status: %s", "[%s %s] Received cast device connection status: %s",
self.entity_id, self.entity_id,
self._cast_info.friendly_name, self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
connection_status.status, connection_status.status,
) )
if connection_status.status == CONNECTION_STATUS_DISCONNECTED: if connection_status.status == CONNECTION_STATUS_DISCONNECTED:
@ -378,11 +365,9 @@ class CastDevice(MediaPlayerEntity):
# Only update state when availability changed to put less pressure # Only update state when availability changed to put less pressure
# on state machine. # on state machine.
_LOGGER.debug( _LOGGER.debug(
"[%s %s (%s:%s)] Cast device availability changed: %s", "[%s %s] Cast device availability changed: %s",
self.entity_id, self.entity_id,
self._cast_info.friendly_name, self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
connection_status.status, connection_status.status,
) )
self._available = new_available self._available = new_available
@ -391,11 +376,9 @@ class CastDevice(MediaPlayerEntity):
def multizone_new_media_status(self, group_uuid, media_status): def multizone_new_media_status(self, group_uuid, media_status):
"""Handle updates of audio group media status.""" """Handle updates of audio group media status."""
_LOGGER.debug( _LOGGER.debug(
"[%s %s (%s:%s)] Multizone %s media status: %s", "[%s %s] Multizone %s media status: %s",
self.entity_id, self.entity_id,
self._cast_info.friendly_name, self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
group_uuid, group_uuid,
media_status, media_status,
) )
@ -738,32 +721,9 @@ class CastDevice(MediaPlayerEntity):
# Discovered is not our device. # Discovered is not our device.
return return
if self.services is None:
_LOGGER.warning(
"[%s %s (%s:%s)] Received update for manually added Cast",
self.entity_id,
self._cast_info.friendly_name,
self._cast_info.host,
self._cast_info.port,
)
return
_LOGGER.debug("Discovered chromecast with same UUID: %s", discover) _LOGGER.debug("Discovered chromecast with same UUID: %s", discover)
await self.async_set_cast_info(discover) await self.async_set_cast_info(discover)
async def _async_cast_removed(self, discover: ChromecastInfo):
"""Handle removal of Chromecast."""
if self._cast_info.uuid is None:
# We can't handle empty UUIDs
return
if self._cast_info.uuid != discover.uuid:
# Removed is not our device.
return
_LOGGER.debug("Removed chromecast with same UUID: %s", discover)
await self.async_del_cast_info(discover)
async def _async_stop(self, event): async def _async_stop(self, event):
"""Disconnect socket on Home Assistant stop.""" """Disconnect socket on Home Assistant stop."""
await self._async_disconnect() await self._async_disconnect()

View File

@ -1255,7 +1255,7 @@ pycfdns==0.0.1
pychannels==1.0.0 pychannels==1.0.0
# homeassistant.components.cast # homeassistant.components.cast
pychromecast==6.0.0 pychromecast==7.0.1
# homeassistant.components.cmus # homeassistant.components.cmus
pycmus==0.1.1 pycmus==0.1.1

View File

@ -567,7 +567,7 @@ pyblackbird==0.5
pybotvac==0.0.17 pybotvac==0.0.17
# homeassistant.components.cast # homeassistant.components.cast
pychromecast==6.0.0 pychromecast==7.0.1
# homeassistant.components.coolmaster # homeassistant.components.coolmaster
pycoolmasternet==0.0.4 pycoolmasternet==0.0.4

View File

@ -56,10 +56,24 @@ def get_fake_chromecast_info(
): ):
"""Generate a Fake ChromecastInfo with the specified arguments.""" """Generate a Fake ChromecastInfo with the specified arguments."""
return ChromecastInfo( return ChromecastInfo(
host=host, port=port, uuid=uuid, friendly_name="Speaker", service="the-service" host=host,
port=port,
uuid=uuid,
friendly_name="Speaker",
services={"the-service"},
) )
def get_fake_zconf(host="192.168.178.42", port=8009):
"""Generate a Fake Zeroconf object with the specified arguments."""
parsed_addresses = MagicMock()
parsed_addresses.return_value = [host]
service_info = MagicMock(parsed_addresses=parsed_addresses, port=port)
zconf = MagicMock()
zconf.get_service_info.return_value = service_info
return zconf
async def async_setup_cast(hass, config=None, discovery_info=None): async def async_setup_cast(hass, config=None, discovery_info=None):
"""Set up the cast platform.""" """Set up the cast platform."""
if config is None: if config is None:
@ -96,14 +110,13 @@ async def async_setup_cast_internal_discovery(hass, config=None, discovery_info=
def discover_chromecast(service_name: str, info: ChromecastInfo) -> None: def discover_chromecast(service_name: str, info: ChromecastInfo) -> None:
"""Discover a chromecast device.""" """Discover a chromecast device."""
listener.services[service_name] = ( listener.services[info.uuid] = (
info.host, {service_name},
info.port,
info.uuid, info.uuid,
info.model_name, info.model_name,
info.friendly_name, info.friendly_name,
) )
discovery_callback(service_name) discovery_callback(info.uuid, service_name)
return discover_chromecast, add_entities return discover_chromecast, add_entities
@ -113,6 +126,7 @@ async def async_setup_media_player_cast(hass: HomeAssistantType, info: Chromecas
listener = MagicMock(services={}) listener = MagicMock(services={})
browser = MagicMock(zc={}) browser = MagicMock(zc={})
chromecast = get_fake_chromecast(info) chromecast = get_fake_chromecast(info)
zconf = get_fake_zconf(host=info.host, port=info.port)
cast.CastStatusListener = MagicMock() cast.CastStatusListener = MagicMock()
@ -125,6 +139,9 @@ async def async_setup_media_player_cast(hass: HomeAssistantType, info: Chromecas
) as cast_listener, patch( ) as cast_listener, patch(
"homeassistant.components.cast.discovery.pychromecast.start_discovery", "homeassistant.components.cast.discovery.pychromecast.start_discovery",
return_value=browser, return_value=browser,
), patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf,
): ):
await async_setup_component( await async_setup_component(
hass, hass,
@ -138,14 +155,13 @@ async def async_setup_media_player_cast(hass: HomeAssistantType, info: Chromecas
def discover_chromecast(service_name: str, info: ChromecastInfo) -> None: def discover_chromecast(service_name: str, info: ChromecastInfo) -> None:
"""Discover a chromecast device.""" """Discover a chromecast device."""
listener.services[service_name] = ( listener.services[info.uuid] = (
info.host, {service_name},
info.port,
info.uuid, info.uuid,
info.model_name, info.model_name,
info.friendly_name, info.friendly_name,
) )
discovery_callback(service_name) discovery_callback(info.uuid, service_name)
discover_chromecast("the-service", info) discover_chromecast("the-service", info)
await hass.async_block_till_done() await hass.async_block_till_done()
@ -184,7 +200,7 @@ async def test_stop_discovery_called_on_stop(hass):
assert start_discovery.call_count == 1 assert start_discovery.call_count == 1
with patch( with patch(
"homeassistant.components.cast.discovery.pychromecast.stop_discovery" "homeassistant.components.cast.discovery.pychromecast.discovery.stop_discovery"
) as stop_discovery: ) as stop_discovery:
# stop discovery should be called on shutdown # stop discovery should be called on shutdown
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP) hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
@ -229,15 +245,26 @@ async def test_replay_past_chromecasts(hass):
cast_group2 = get_fake_chromecast_info( cast_group2 = get_fake_chromecast_info(
host="host2", port=42, uuid=UUID("9462202c-e747-4af5-a66b-7dce0e1ebc09") host="host2", port=42, uuid=UUID("9462202c-e747-4af5-a66b-7dce0e1ebc09")
) )
zconf_1 = get_fake_zconf(host="host1", port=42)
zconf_2 = get_fake_zconf(host="host2", port=42)
discover_cast, add_dev1 = await async_setup_cast_internal_discovery( discover_cast, add_dev1 = await async_setup_cast_internal_discovery(
hass, discovery_info={"host": "host1", "port": 42} hass, discovery_info={"host": "host1", "port": 42}
) )
discover_cast("service2", cast_group2)
await hass.async_block_till_done()
assert add_dev1.call_count == 0
discover_cast("service1", cast_group1) with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service2", cast_group2)
await hass.async_block_till_done()
assert add_dev1.call_count == 0
with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service1", cast_group1)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1 assert add_dev1.call_count == 1
@ -249,21 +276,61 @@ async def test_replay_past_chromecasts(hass):
assert add_dev2.call_count == 1 assert add_dev2.call_count == 1
async def test_manual_cast_chromecasts(hass): async def test_manual_cast_chromecasts_host(hass):
"""Test only wanted casts are added for manual configuration.""" """Test only wanted casts are added for manual configuration."""
cast_1 = get_fake_chromecast_info(host="configured_host") cast_1 = get_fake_chromecast_info(host="configured_host")
cast_2 = get_fake_chromecast_info(host="other_host", uuid=FakeUUID2) cast_2 = get_fake_chromecast_info(host="other_host", uuid=FakeUUID2)
zconf_1 = get_fake_zconf(host="configured_host")
zconf_2 = get_fake_zconf(host="other_host")
# Manual configuration of media player with host "configured_host" # Manual configuration of media player with host "configured_host"
discover_cast, add_dev1 = await async_setup_cast_internal_discovery( discover_cast, add_dev1 = await async_setup_cast_internal_discovery(
hass, config={"host": "configured_host"} hass, config={"host": "configured_host"}
) )
discover_cast("service2", cast_2) with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service2", cast_2)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 0 assert add_dev1.call_count == 0
discover_cast("service1", cast_1) with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service1", cast_1)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1
async def test_manual_cast_chromecasts_uuid(hass):
"""Test only wanted casts are added for manual configuration."""
cast_1 = get_fake_chromecast_info(host="host_1", uuid=FakeUUID)
cast_2 = get_fake_chromecast_info(host="host_2", uuid=FakeUUID2)
zconf_1 = get_fake_zconf(host="host_1")
zconf_2 = get_fake_zconf(host="host_2")
# Manual configuration of media player with host "configured_host"
discover_cast, add_dev1 = await async_setup_cast_internal_discovery(
hass, config={"uuid": FakeUUID}
)
with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service2", cast_2)
await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 0
with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service1", cast_1)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1 assert add_dev1.call_count == 1
@ -273,15 +340,25 @@ async def test_auto_cast_chromecasts(hass):
"""Test all discovered casts are added for default configuration.""" """Test all discovered casts are added for default configuration."""
cast_1 = get_fake_chromecast_info(host="some_host") cast_1 = get_fake_chromecast_info(host="some_host")
cast_2 = get_fake_chromecast_info(host="other_host", uuid=FakeUUID2) cast_2 = get_fake_chromecast_info(host="other_host", uuid=FakeUUID2)
zconf_1 = get_fake_zconf(host="some_host")
zconf_2 = get_fake_zconf(host="other_host")
# Manual configuration of media player with host "configured_host" # Manual configuration of media player with host "configured_host"
discover_cast, add_dev1 = await async_setup_cast_internal_discovery(hass) discover_cast, add_dev1 = await async_setup_cast_internal_discovery(hass)
discover_cast("service2", cast_2) with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service2", cast_2)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1 assert add_dev1.call_count == 1
discover_cast("service1", cast_1) with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service1", cast_1)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 2 assert add_dev1.call_count == 2
@ -291,15 +368,26 @@ async def test_update_cast_chromecasts(hass):
"""Test discovery of same UUID twice only adds one cast.""" """Test discovery of same UUID twice only adds one cast."""
cast_1 = get_fake_chromecast_info(host="old_host") cast_1 = get_fake_chromecast_info(host="old_host")
cast_2 = get_fake_chromecast_info(host="new_host") cast_2 = get_fake_chromecast_info(host="new_host")
zconf_1 = get_fake_zconf(host="old_host")
zconf_2 = get_fake_zconf(host="new_host")
# Manual configuration of media player with host "configured_host" # Manual configuration of media player with host "configured_host"
discover_cast, add_dev1 = await async_setup_cast_internal_discovery(hass) discover_cast, add_dev1 = await async_setup_cast_internal_discovery(hass)
discover_cast("service1", cast_1)
with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_1,
):
discover_cast("service1", cast_1)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1 assert add_dev1.call_count == 1
discover_cast("service2", cast_2) with patch(
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
return_value=zconf_2,
):
discover_cast("service2", cast_2)
await hass.async_block_till_done() await hass.async_block_till_done()
await hass.async_block_till_done() # having tasks that add jobs await hass.async_block_till_done() # having tasks that add jobs
assert add_dev1.call_count == 1 assert add_dev1.call_count == 1