diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index a05653cd11554..3e6fd7e580596 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -61,10 +61,6 @@ vol.All(cv.ensure_list, [cv.string]), }) -CONNECTION_RETRY = 3 -CONNECTION_RETRY_WAIT = 2 -CONNECTION_TIMEOUT = 10 - @attr.s(slots=True, frozen=True) class ChromecastInfo: @@ -124,7 +120,6 @@ def _fill_out_missing_chromecast_info(info: ChromecastInfo) -> ChromecastInfo: def _discover_chromecast(hass: HomeAssistantType, info: ChromecastInfo): if info in hass.data[KNOWN_CHROMECAST_INFO_KEY]: _LOGGER.debug("Discovered previous chromecast %s", info) - return # Either discovered completely new chromecast or a "moved" one. info = _fill_out_missing_chromecast_info(info) @@ -216,13 +211,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities): if not isinstance(config, list): config = [config] - await asyncio.wait([ + done, pending = await asyncio.wait([ _async_setup_platform(hass, cfg, async_add_entities, None) for cfg in config]) + if pending or any([not task.result() for task in done]): + raise PlatformNotReady async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType, - async_add_entities, discovery_info): + async_add_entities, discovery_info) -> bool: """Set up the cast platform.""" import pychromecast @@ -250,8 +247,8 @@ def async_cast_discovered(discover: ChromecastInfo) -> None: if cast_device is not None: async_add_entities([cast_device]) - async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, - async_cast_discovered) + remove_handler = 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 list(hass.data[KNOWN_CHROMECAST_INFO_KEY]): @@ -265,10 +262,20 @@ def async_cast_discovered(discover: ChromecastInfo) -> None: info = await hass.async_add_job(_fill_out_missing_chromecast_info, info) if info.friendly_name is None: - # HTTP dial failed, so we won't be able to connect. - raise PlatformNotReady + _LOGGER.debug("Cannot retrieve detail information for chromecast" + " %s, the device may not online", info) + if not hass.is_running: + # We don't want to block system setup + # If hass.is_running is True, means we are in the retry setup, + # create an unavailable device and open a socket to keep listen + # configured host + remove_handler() + return False + hass.async_add_job(_discover_chromecast, hass, info) + return True + class CastStatusListener: """Helper class to handle pychromecast status callbacks. @@ -379,7 +386,7 @@ async def async_set_cast_info(self, cast_info): pychromecast._get_chromecast_from_host, ( cast_info.host, cast_info.port, cast_info.uuid, cast_info.model_name, cast_info.friendly_name - ), CONNECTION_RETRY, CONNECTION_RETRY_WAIT, CONNECTION_TIMEOUT) + )) self._chromecast = chromecast self._status_listener = CastStatusListener(self, chromecast) # Initialise connection status as connected because we can only