mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 02:07:09 +00:00
Bump pychromecast to 9.0.0 (#47086)
* Adapt to Pychromecast 9.0.0 * Bump pychromecast to 9.0.0 * Fix lint issues
This commit is contained in:
parent
d5ee49cd4e
commit
dfbb653107
@ -9,6 +9,7 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.dispatcher import dispatcher_send
|
from homeassistant.helpers.dispatcher import dispatcher_send
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
|
DEFAULT_PORT,
|
||||||
INTERNAL_DISCOVERY_RUNNING_KEY,
|
INTERNAL_DISCOVERY_RUNNING_KEY,
|
||||||
KNOWN_CHROMECAST_INFO_KEY,
|
KNOWN_CHROMECAST_INFO_KEY,
|
||||||
SIGNAL_CAST_DISCOVERED,
|
SIGNAL_CAST_DISCOVERED,
|
||||||
@ -19,8 +20,17 @@ from .helpers import ChromecastInfo, ChromeCastZeroconf
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def discover_chromecast(hass: HomeAssistant, info: ChromecastInfo):
|
def discover_chromecast(hass: HomeAssistant, device_info):
|
||||||
"""Discover a Chromecast."""
|
"""Discover a Chromecast."""
|
||||||
|
|
||||||
|
info = ChromecastInfo(
|
||||||
|
services=device_info.services,
|
||||||
|
uuid=device_info.uuid,
|
||||||
|
model_name=device_info.model_name,
|
||||||
|
friendly_name=device_info.friendly_name,
|
||||||
|
is_audio_group=device_info.port != DEFAULT_PORT,
|
||||||
|
)
|
||||||
|
|
||||||
if info.uuid is None:
|
if info.uuid is None:
|
||||||
_LOGGER.error("Discovered chromecast without uuid %s", info)
|
_LOGGER.error("Discovered chromecast without uuid %s", info)
|
||||||
return
|
return
|
||||||
@ -51,72 +61,39 @@ def setup_internal_discovery(hass: HomeAssistant) -> None:
|
|||||||
# Internal discovery is already running
|
# Internal discovery is already running
|
||||||
return
|
return
|
||||||
|
|
||||||
def internal_add_update_callback(uuid, service_name):
|
class CastListener(pychromecast.discovery.AbstractCastListener):
|
||||||
"""Handle zeroconf discovery of a new or updated chromecast."""
|
"""Listener for discovering chromecasts."""
|
||||||
service = listener.services[uuid]
|
|
||||||
|
|
||||||
# For support of deprecated IP based white listing
|
def add_cast(self, uuid, _):
|
||||||
zconf = ChromeCastZeroconf.get_zeroconf()
|
"""Handle zeroconf discovery of a new chromecast."""
|
||||||
service_info = None
|
discover_chromecast(hass, browser.devices[uuid])
|
||||||
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:
|
def update_cast(self, uuid, _):
|
||||||
_LOGGER.warning(
|
"""Handle zeroconf discovery of an updated chromecast."""
|
||||||
"setup_internal_discovery failed to get info for %s, %s",
|
discover_chromecast(hass, browser.devices[uuid])
|
||||||
uuid,
|
|
||||||
service_name,
|
def remove_cast(self, uuid, service, cast_info):
|
||||||
|
"""Handle zeroconf discovery of a removed chromecast."""
|
||||||
|
_remove_chromecast(
|
||||||
|
hass,
|
||||||
|
ChromecastInfo(
|
||||||
|
services=cast_info.services,
|
||||||
|
uuid=cast_info.uuid,
|
||||||
|
model_name=cast_info.model_name,
|
||||||
|
friendly_name=cast_info.friendly_name,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return
|
|
||||||
|
|
||||||
addresses = service_info.parsed_addresses()
|
|
||||||
host = addresses[0] if addresses else service_info.server
|
|
||||||
|
|
||||||
discover_chromecast(
|
|
||||||
hass,
|
|
||||||
ChromecastInfo(
|
|
||||||
services=service[0],
|
|
||||||
uuid=service[1],
|
|
||||||
model_name=service[2],
|
|
||||||
friendly_name=service[3],
|
|
||||||
host=host,
|
|
||||||
port=service_info.port,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def internal_remove_callback(uuid, service_name, service):
|
|
||||||
"""Handle zeroconf discovery of a removed chromecast."""
|
|
||||||
_remove_chromecast(
|
|
||||||
hass,
|
|
||||||
ChromecastInfo(
|
|
||||||
services=service[0],
|
|
||||||
uuid=service[1],
|
|
||||||
model_name=service[2],
|
|
||||||
friendly_name=service[3],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER.debug("Starting internal pychromecast discovery")
|
_LOGGER.debug("Starting internal pychromecast discovery")
|
||||||
listener = pychromecast.CastListener(
|
browser = pychromecast.discovery.CastBrowser(
|
||||||
internal_add_update_callback,
|
CastListener(), ChromeCastZeroconf.get_zeroconf()
|
||||||
internal_remove_callback,
|
|
||||||
internal_add_update_callback,
|
|
||||||
)
|
)
|
||||||
browser = pychromecast.start_discovery(listener, ChromeCastZeroconf.get_zeroconf())
|
browser.start_discovery()
|
||||||
|
|
||||||
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.discovery.stop_discovery(browser)
|
browser.stop_discovery()
|
||||||
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)
|
||||||
|
@ -7,8 +7,6 @@ import attr
|
|||||||
from pychromecast import dial
|
from pychromecast import dial
|
||||||
from pychromecast.const import CAST_MANUFACTURERS
|
from pychromecast.const import CAST_MANUFACTURERS
|
||||||
|
|
||||||
from .const import DEFAULT_PORT
|
|
||||||
|
|
||||||
|
|
||||||
@attr.s(slots=True, frozen=True)
|
@attr.s(slots=True, frozen=True)
|
||||||
class ChromecastInfo:
|
class ChromecastInfo:
|
||||||
@ -18,21 +16,15 @@ class ChromecastInfo:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
services: Optional[set] = attr.ib()
|
services: Optional[set] = attr.ib()
|
||||||
host: Optional[str] = attr.ib(default=None)
|
|
||||||
port: Optional[int] = attr.ib(default=0)
|
|
||||||
uuid: Optional[str] = attr.ib(
|
uuid: Optional[str] = attr.ib(
|
||||||
converter=attr.converters.optional(str), default=None
|
converter=attr.converters.optional(str), default=None
|
||||||
) # always convert UUID to string if not None
|
) # always convert UUID to string if not None
|
||||||
_manufacturer = attr.ib(type=Optional[str], default=None)
|
_manufacturer = attr.ib(type=Optional[str], default=None)
|
||||||
model_name: str = attr.ib(default="")
|
model_name: str = attr.ib(default="")
|
||||||
friendly_name: Optional[str] = attr.ib(default=None)
|
friendly_name: Optional[str] = attr.ib(default=None)
|
||||||
|
is_audio_group = attr.ib(type=Optional[bool], default=False)
|
||||||
is_dynamic_group = attr.ib(type=Optional[bool], default=None)
|
is_dynamic_group = attr.ib(type=Optional[bool], default=None)
|
||||||
|
|
||||||
@property
|
|
||||||
def is_audio_group(self) -> bool:
|
|
||||||
"""Return if this is an audio group."""
|
|
||||||
return self.port != DEFAULT_PORT
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_information_complete(self) -> bool:
|
def is_information_complete(self) -> bool:
|
||||||
"""Return if all information is filled out."""
|
"""Return if all information is filled out."""
|
||||||
@ -74,7 +66,7 @@ class ChromecastInfo:
|
|||||||
http_group_status = None
|
http_group_status = None
|
||||||
if self.uuid:
|
if self.uuid:
|
||||||
http_group_status = dial.get_multizone_status(
|
http_group_status = dial.get_multizone_status(
|
||||||
self.host,
|
None,
|
||||||
services=self.services,
|
services=self.services,
|
||||||
zconf=ChromeCastZeroconf.get_zeroconf(),
|
zconf=ChromeCastZeroconf.get_zeroconf(),
|
||||||
)
|
)
|
||||||
@ -86,17 +78,16 @@ class ChromecastInfo:
|
|||||||
|
|
||||||
return ChromecastInfo(
|
return ChromecastInfo(
|
||||||
services=self.services,
|
services=self.services,
|
||||||
host=self.host,
|
|
||||||
port=self.port,
|
|
||||||
uuid=self.uuid,
|
uuid=self.uuid,
|
||||||
friendly_name=self.friendly_name,
|
friendly_name=self.friendly_name,
|
||||||
model_name=self.model_name,
|
model_name=self.model_name,
|
||||||
|
is_audio_group=True,
|
||||||
is_dynamic_group=is_dynamic_group,
|
is_dynamic_group=is_dynamic_group,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Fill out some missing information (friendly_name, uuid) via HTTP dial.
|
# Fill out some missing information (friendly_name, uuid) via HTTP dial.
|
||||||
http_device_status = dial.get_device_status(
|
http_device_status = dial.get_device_status(
|
||||||
self.host, services=self.services, zconf=ChromeCastZeroconf.get_zeroconf()
|
None, services=self.services, zconf=ChromeCastZeroconf.get_zeroconf()
|
||||||
)
|
)
|
||||||
if http_device_status is None:
|
if http_device_status is None:
|
||||||
# HTTP dial didn't give us any new information.
|
# HTTP dial didn't give us any new information.
|
||||||
@ -104,8 +95,6 @@ class ChromecastInfo:
|
|||||||
|
|
||||||
return ChromecastInfo(
|
return ChromecastInfo(
|
||||||
services=self.services,
|
services=self.services,
|
||||||
host=self.host,
|
|
||||||
port=self.port,
|
|
||||||
uuid=(self.uuid or http_device_status.uuid),
|
uuid=(self.uuid or http_device_status.uuid),
|
||||||
friendly_name=(self.friendly_name or http_device_status.friendly_name),
|
friendly_name=(self.friendly_name or http_device_status.friendly_name),
|
||||||
manufacturer=(self.manufacturer or http_device_status.manufacturer),
|
manufacturer=(self.manufacturer or http_device_status.manufacturer),
|
||||||
|
@ -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==8.1.2"],
|
"requirements": ["pychromecast==9.0.0"],
|
||||||
"after_dependencies": ["cloud", "http", "media_source", "plex", "tts", "zeroconf"],
|
"after_dependencies": ["cloud", "http", "media_source", "plex", "tts", "zeroconf"],
|
||||||
"zeroconf": ["_googlecast._tcp.local."],
|
"zeroconf": ["_googlecast._tcp.local."],
|
||||||
"codeowners": ["@emontnemery"]
|
"codeowners": ["@emontnemery"]
|
||||||
|
@ -154,15 +154,15 @@ async def _async_setup_platform(
|
|||||||
hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set())
|
hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set())
|
||||||
hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, {})
|
hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, {})
|
||||||
|
|
||||||
info = None
|
wanted_uuid = None
|
||||||
if CONF_UUID in config:
|
if CONF_UUID in config:
|
||||||
info = ChromecastInfo(uuid=config[CONF_UUID], services=None)
|
wanted_uuid = config[CONF_UUID]
|
||||||
|
|
||||||
@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 set, we're handling a specific cast device identified by UUID
|
# If wanted_uuid is set, we're handling a specific cast device identified by UUID
|
||||||
if info is not None and (info.uuid is not None and info.uuid != discover.uuid):
|
if wanted_uuid is not None and wanted_uuid != discover.uuid:
|
||||||
# UUID not matching, this is not it.
|
# UUID not matching, this is not it.
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -251,8 +251,8 @@ class CastDevice(MediaPlayerEntity):
|
|||||||
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_cast_info,
|
||||||
(
|
pychromecast.discovery.CastInfo(
|
||||||
self.services,
|
self.services,
|
||||||
self._cast_info.uuid,
|
self._cast_info.uuid,
|
||||||
self._cast_info.model_name,
|
self._cast_info.model_name,
|
||||||
@ -875,8 +875,8 @@ class DynamicCastGroup:
|
|||||||
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_cast_info,
|
||||||
(
|
pychromecast.discovery.CastInfo(
|
||||||
self.services,
|
self.services,
|
||||||
self._cast_info.uuid,
|
self._cast_info.uuid,
|
||||||
self._cast_info.model_name,
|
self._cast_info.model_name,
|
||||||
|
@ -1305,7 +1305,7 @@ pycfdns==1.2.1
|
|||||||
pychannels==1.0.0
|
pychannels==1.0.0
|
||||||
|
|
||||||
# homeassistant.components.cast
|
# homeassistant.components.cast
|
||||||
pychromecast==8.1.2
|
pychromecast==9.0.0
|
||||||
|
|
||||||
# homeassistant.components.pocketcasts
|
# homeassistant.components.pocketcasts
|
||||||
pycketcasts==1.0.0
|
pycketcasts==1.0.0
|
||||||
|
@ -688,7 +688,7 @@ pybotvac==0.0.20
|
|||||||
pycfdns==1.2.1
|
pycfdns==1.2.1
|
||||||
|
|
||||||
# homeassistant.components.cast
|
# homeassistant.components.cast
|
||||||
pychromecast==8.1.2
|
pychromecast==9.0.0
|
||||||
|
|
||||||
# homeassistant.components.climacell
|
# homeassistant.components.climacell
|
||||||
pyclimacell==0.14.0
|
pyclimacell==0.14.0
|
||||||
|
@ -6,6 +6,7 @@ from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch
|
|||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
import pychromecast
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components import tts
|
from homeassistant.components import tts
|
||||||
@ -47,6 +48,12 @@ def dial_mock():
|
|||||||
return dial_mock
|
return dial_mock
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def castbrowser_mock():
|
||||||
|
"""Mock pychromecast CastBrowser."""
|
||||||
|
return MagicMock()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def mz_mock():
|
def mz_mock():
|
||||||
"""Mock pychromecast MultizoneManager."""
|
"""Mock pychromecast MultizoneManager."""
|
||||||
@ -54,10 +61,13 @@ def mz_mock():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def pycast_mock():
|
def pycast_mock(castbrowser_mock):
|
||||||
"""Mock pychromecast."""
|
"""Mock pychromecast."""
|
||||||
pycast_mock = MagicMock()
|
pycast_mock = MagicMock()
|
||||||
pycast_mock.start_discovery.return_value = (None, Mock())
|
pycast_mock.discovery.CastBrowser.return_value = castbrowser_mock
|
||||||
|
pycast_mock.discovery.AbstractCastListener = (
|
||||||
|
pychromecast.discovery.AbstractCastListener
|
||||||
|
)
|
||||||
return pycast_mock
|
return pycast_mock
|
||||||
|
|
||||||
|
|
||||||
@ -97,7 +107,7 @@ FakeGroupUUID = UUID("57355bce-9364-4aa6-ac1e-eb849dccf9e3")
|
|||||||
|
|
||||||
def get_fake_chromecast(info: ChromecastInfo):
|
def get_fake_chromecast(info: ChromecastInfo):
|
||||||
"""Generate a Fake Chromecast object with the specified arguments."""
|
"""Generate a Fake Chromecast object with the specified arguments."""
|
||||||
mock = MagicMock(host=info.host, port=info.port, uuid=info.uuid)
|
mock = MagicMock(uuid=info.uuid)
|
||||||
mock.media_controller.status = None
|
mock.media_controller.status = None
|
||||||
return mock
|
return mock
|
||||||
|
|
||||||
@ -106,12 +116,35 @@ def get_fake_chromecast_info(
|
|||||||
host="192.168.178.42", port=8009, uuid: Optional[UUID] = FakeUUID
|
host="192.168.178.42", port=8009, uuid: Optional[UUID] = FakeUUID
|
||||||
):
|
):
|
||||||
"""Generate a Fake ChromecastInfo with the specified arguments."""
|
"""Generate a Fake ChromecastInfo with the specified arguments."""
|
||||||
return ChromecastInfo(
|
|
||||||
|
@attr.s(slots=True, frozen=True, eq=False)
|
||||||
|
class ExtendedChromecastInfo(ChromecastInfo):
|
||||||
|
host: Optional[str] = attr.ib(default=None)
|
||||||
|
port: Optional[int] = attr.ib(default=0)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, ChromecastInfo):
|
||||||
|
return (
|
||||||
|
ChromecastInfo(
|
||||||
|
services=self.services,
|
||||||
|
uuid=self.uuid,
|
||||||
|
manufacturer=self.manufacturer,
|
||||||
|
model_name=self.model_name,
|
||||||
|
friendly_name=self.friendly_name,
|
||||||
|
is_audio_group=self.is_audio_group,
|
||||||
|
is_dynamic_group=self.is_dynamic_group,
|
||||||
|
)
|
||||||
|
== other
|
||||||
|
)
|
||||||
|
return super().__eq__(other)
|
||||||
|
|
||||||
|
return ExtendedChromecastInfo(
|
||||||
host=host,
|
host=host,
|
||||||
port=port,
|
port=port,
|
||||||
uuid=uuid,
|
uuid=uuid,
|
||||||
friendly_name="Speaker",
|
friendly_name="Speaker",
|
||||||
services={"the-service"},
|
services={"the-service"},
|
||||||
|
is_audio_group=port != 8009,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -141,32 +174,30 @@ async def async_setup_cast(hass, config=None):
|
|||||||
|
|
||||||
async def async_setup_cast_internal_discovery(hass, config=None):
|
async def async_setup_cast_internal_discovery(hass, config=None):
|
||||||
"""Set up the cast platform and the discovery."""
|
"""Set up the cast platform and the discovery."""
|
||||||
listener = MagicMock(services={})
|
browser = MagicMock(devices={}, zc={})
|
||||||
browser = MagicMock(zc={})
|
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.cast.discovery.pychromecast.CastListener",
|
"homeassistant.components.cast.discovery.pychromecast.discovery.CastBrowser",
|
||||||
return_value=listener,
|
|
||||||
) as cast_listener, patch(
|
|
||||||
"homeassistant.components.cast.discovery.pychromecast.start_discovery",
|
|
||||||
return_value=browser,
|
return_value=browser,
|
||||||
) as start_discovery:
|
) as cast_browser:
|
||||||
add_entities = await async_setup_cast(hass, config)
|
add_entities = await async_setup_cast(hass, config)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert start_discovery.call_count == 1
|
assert browser.start_discovery.call_count == 1
|
||||||
|
|
||||||
discovery_callback = cast_listener.call_args[0][0]
|
discovery_callback = cast_browser.call_args[0][0].add_cast
|
||||||
remove_callback = cast_listener.call_args[0][1]
|
remove_callback = cast_browser.call_args[0][0].remove_cast
|
||||||
|
|
||||||
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[info.uuid] = (
|
browser.devices[info.uuid] = pychromecast.discovery.CastInfo(
|
||||||
{service_name},
|
{service_name},
|
||||||
info.uuid,
|
info.uuid,
|
||||||
info.model_name,
|
info.model_name,
|
||||||
info.friendly_name,
|
info.friendly_name,
|
||||||
|
info.host,
|
||||||
|
info.port,
|
||||||
)
|
)
|
||||||
discovery_callback(info.uuid, service_name)
|
discovery_callback(info.uuid, service_name)
|
||||||
|
|
||||||
@ -175,7 +206,14 @@ async def async_setup_cast_internal_discovery(hass, config=None):
|
|||||||
remove_callback(
|
remove_callback(
|
||||||
info.uuid,
|
info.uuid,
|
||||||
service_name,
|
service_name,
|
||||||
(set(), info.uuid, info.model_name, info.friendly_name),
|
pychromecast.discovery.CastInfo(
|
||||||
|
set(),
|
||||||
|
info.uuid,
|
||||||
|
info.model_name,
|
||||||
|
info.friendly_name,
|
||||||
|
info.host,
|
||||||
|
info.port,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return discover_chromecast, remove_chromecast, add_entities
|
return discover_chromecast, remove_chromecast, add_entities
|
||||||
@ -183,21 +221,17 @@ async def async_setup_cast_internal_discovery(hass, config=None):
|
|||||||
|
|
||||||
async def async_setup_media_player_cast(hass: HomeAssistantType, info: ChromecastInfo):
|
async def async_setup_media_player_cast(hass: HomeAssistantType, info: ChromecastInfo):
|
||||||
"""Set up the cast platform with async_setup_component."""
|
"""Set up the cast platform with async_setup_component."""
|
||||||
listener = MagicMock(services={})
|
browser = MagicMock(devices={}, zc={})
|
||||||
browser = MagicMock(zc={})
|
|
||||||
chromecast = get_fake_chromecast(info)
|
chromecast = get_fake_chromecast(info)
|
||||||
zconf = get_fake_zconf(host=info.host, port=info.port)
|
zconf = get_fake_zconf(host=info.host, port=info.port)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.cast.discovery.pychromecast.get_chromecast_from_service",
|
"homeassistant.components.cast.discovery.pychromecast.get_chromecast_from_cast_info",
|
||||||
return_value=chromecast,
|
return_value=chromecast,
|
||||||
) as get_chromecast, patch(
|
) as get_chromecast, patch(
|
||||||
"homeassistant.components.cast.discovery.pychromecast.CastListener",
|
"homeassistant.components.cast.discovery.pychromecast.discovery.CastBrowser",
|
||||||
return_value=listener,
|
|
||||||
) as cast_listener, patch(
|
|
||||||
"homeassistant.components.cast.discovery.pychromecast.start_discovery",
|
|
||||||
return_value=browser,
|
return_value=browser,
|
||||||
), patch(
|
) as cast_browser, patch(
|
||||||
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
|
"homeassistant.components.cast.discovery.ChromeCastZeroconf.get_zeroconf",
|
||||||
return_value=zconf,
|
return_value=zconf,
|
||||||
):
|
):
|
||||||
@ -205,15 +239,18 @@ async def async_setup_media_player_cast(hass: HomeAssistantType, info: Chromecas
|
|||||||
hass, "cast", {"cast": {"media_player": {"uuid": info.uuid}}}
|
hass, "cast", {"cast": {"media_player": {"uuid": info.uuid}}}
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
discovery_callback = cast_listener.call_args[0][0]
|
discovery_callback = cast_browser.call_args[0][0].add_cast
|
||||||
|
|
||||||
service_name = "the-service"
|
service_name = "the-service"
|
||||||
listener.services[info.uuid] = (
|
browser.devices[info.uuid] = pychromecast.discovery.CastInfo(
|
||||||
{service_name},
|
{service_name},
|
||||||
info.uuid,
|
info.uuid,
|
||||||
info.model_name,
|
info.model_name,
|
||||||
info.friendly_name,
|
info.friendly_name,
|
||||||
|
info.host,
|
||||||
|
info.port,
|
||||||
)
|
)
|
||||||
discovery_callback(info.uuid, service_name)
|
discovery_callback(info.uuid, service_name)
|
||||||
|
|
||||||
@ -223,11 +260,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[info.uuid] = (
|
browser.devices[info.uuid] = pychromecast.discovery.CastInfo(
|
||||||
{service_name},
|
{service_name},
|
||||||
info.uuid,
|
info.uuid,
|
||||||
info.model_name,
|
info.model_name,
|
||||||
info.friendly_name,
|
info.friendly_name,
|
||||||
|
info.host,
|
||||||
|
info.port,
|
||||||
)
|
)
|
||||||
discovery_callback(info.uuid, service_name)
|
discovery_callback(info.uuid, service_name)
|
||||||
|
|
||||||
@ -253,18 +292,13 @@ def get_status_callbacks(chromecast_mock, mz_mock=None):
|
|||||||
return cast_status_cb, conn_status_cb, media_status_cb, group_media_status_cb
|
return cast_status_cb, conn_status_cb, media_status_cb, group_media_status_cb
|
||||||
|
|
||||||
|
|
||||||
async def test_start_discovery_called_once(hass):
|
async def test_start_discovery_called_once(hass, castbrowser_mock):
|
||||||
"""Test pychromecast.start_discovery called exactly once."""
|
"""Test pychromecast.start_discovery called exactly once."""
|
||||||
with patch(
|
await async_setup_cast(hass)
|
||||||
"homeassistant.components.cast.discovery.pychromecast.start_discovery",
|
assert castbrowser_mock.start_discovery.call_count == 1
|
||||||
return_value=Mock(),
|
|
||||||
) as start_discovery:
|
|
||||||
await async_setup_cast(hass)
|
|
||||||
|
|
||||||
assert start_discovery.call_count == 1
|
await async_setup_cast(hass)
|
||||||
|
assert castbrowser_mock.start_discovery.call_count == 1
|
||||||
await async_setup_cast(hass)
|
|
||||||
assert start_discovery.call_count == 1
|
|
||||||
|
|
||||||
|
|
||||||
async def test_internal_discovery_callback_fill_out(hass):
|
async def test_internal_discovery_callback_fill_out(hass):
|
||||||
@ -350,7 +384,6 @@ async def test_internal_discovery_callback_fill_out_fail(hass):
|
|||||||
# when called with incomplete info, it should use HTTP to get missing
|
# when called with incomplete info, it should use HTTP to get missing
|
||||||
discover = signal.mock_calls[0][1][0]
|
discover = signal.mock_calls[0][1][0]
|
||||||
assert discover == full_info
|
assert discover == full_info
|
||||||
# assert 1 == 2
|
|
||||||
|
|
||||||
|
|
||||||
async def test_internal_discovery_callback_fill_out_group(hass):
|
async def test_internal_discovery_callback_fill_out_group(hass):
|
||||||
@ -384,27 +417,16 @@ async def test_internal_discovery_callback_fill_out_group(hass):
|
|||||||
assert discover == full_info
|
assert discover == full_info
|
||||||
|
|
||||||
|
|
||||||
async def test_stop_discovery_called_on_stop(hass):
|
async def test_stop_discovery_called_on_stop(hass, castbrowser_mock):
|
||||||
"""Test pychromecast.stop_discovery called on shutdown."""
|
"""Test pychromecast.stop_discovery called on shutdown."""
|
||||||
browser = MagicMock(zc={})
|
# start_discovery should be called with empty config
|
||||||
|
await async_setup_cast(hass, {})
|
||||||
|
assert castbrowser_mock.start_discovery.call_count == 1
|
||||||
|
|
||||||
with patch(
|
# stop discovery should be called on shutdown
|
||||||
"homeassistant.components.cast.discovery.pychromecast.start_discovery",
|
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||||
return_value=browser,
|
await hass.async_block_till_done()
|
||||||
) as start_discovery:
|
assert castbrowser_mock.stop_discovery.call_count == 1
|
||||||
# start_discovery should be called with empty config
|
|
||||||
await async_setup_cast(hass, {})
|
|
||||||
|
|
||||||
assert start_discovery.call_count == 1
|
|
||||||
|
|
||||||
with patch(
|
|
||||||
"homeassistant.components.cast.discovery.pychromecast.discovery.stop_discovery"
|
|
||||||
) as stop_discovery:
|
|
||||||
# stop discovery should be called on shutdown
|
|
||||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
stop_discovery.assert_called_once_with(browser)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_create_cast_device_without_uuid(hass):
|
async def test_create_cast_device_without_uuid(hass):
|
||||||
@ -539,7 +561,7 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
|
|||||||
tmp2.uuid = FakeUUID2
|
tmp2.uuid = FakeUUID2
|
||||||
dial_mock.get_multizone_status.return_value.dynamic_groups = [tmp1, tmp2]
|
dial_mock.get_multizone_status.return_value.dynamic_groups = [tmp1, tmp2]
|
||||||
|
|
||||||
pycast_mock.get_chromecast_from_service.assert_not_called()
|
pycast_mock.get_chromecast_from_cast_info.assert_not_called()
|
||||||
discover_cast, remove_cast, add_dev1 = await async_setup_cast_internal_discovery(
|
discover_cast, remove_cast, add_dev1 = await async_setup_cast_internal_discovery(
|
||||||
hass
|
hass
|
||||||
)
|
)
|
||||||
@ -552,8 +574,8 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
|
|||||||
discover_cast("service", cast_1)
|
discover_cast("service", 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
|
||||||
pycast_mock.get_chromecast_from_service.assert_called()
|
pycast_mock.get_chromecast_from_cast_info.assert_called()
|
||||||
pycast_mock.get_chromecast_from_service.reset_mock()
|
pycast_mock.get_chromecast_from_cast_info.reset_mock()
|
||||||
assert add_dev1.call_count == 0
|
assert add_dev1.call_count == 0
|
||||||
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
|
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
|
||||||
|
|
||||||
@ -565,8 +587,8 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
|
|||||||
discover_cast("service", cast_2)
|
discover_cast("service", 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
|
||||||
pycast_mock.get_chromecast_from_service.assert_called()
|
pycast_mock.get_chromecast_from_cast_info.assert_called()
|
||||||
pycast_mock.get_chromecast_from_service.reset_mock()
|
pycast_mock.get_chromecast_from_cast_info.reset_mock()
|
||||||
assert add_dev1.call_count == 0
|
assert add_dev1.call_count == 0
|
||||||
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
|
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
|
||||||
|
|
||||||
@ -578,7 +600,7 @@ async def test_discover_dynamic_group(hass, dial_mock, pycast_mock, caplog):
|
|||||||
discover_cast("service", cast_1)
|
discover_cast("service", 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
|
||||||
pycast_mock.get_chromecast_from_service.assert_not_called()
|
pycast_mock.get_chromecast_from_cast_info.assert_not_called()
|
||||||
assert add_dev1.call_count == 0
|
assert add_dev1.call_count == 0
|
||||||
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
|
assert reg.async_get_entity_id("media_player", "cast", cast_1.uuid) is None
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user