Skip to content

Commit

Permalink
Don't hang forever if manually added cast is down (#21565)
Browse files Browse the repository at this point in the history
* Don't hang forever if manually added cast is down

* Adapt to pychromecast

* Do not set available until connected

* Update __init__.py

* Update requirements

* Lint, tests

* Fix tests
  • Loading branch information
emontnemery authored and balloob committed Mar 11, 2019
1 parent fe1840f commit fc85b3f
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 20 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/cast/__init__.py
Expand Up @@ -2,7 +2,7 @@
from homeassistant import config_entries
from homeassistant.helpers import config_entry_flow

REQUIREMENTS = ['pychromecast==2.5.2']
REQUIREMENTS = ['pychromecast==3.0.0']

DOMAIN = 'cast'

Expand Down
21 changes: 10 additions & 11 deletions homeassistant/components/cast/media_player.py
Expand Up @@ -257,6 +257,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
_async_setup_platform(hass, cfg, async_add_entities, None)
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


Expand Down Expand Up @@ -289,7 +292,7 @@ def async_cast_discovered(discover: ChromecastInfo) -> None:
if cast_device is not None:
async_add_entities([cast_device])

remove_handler = async_dispatcher_connect(
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.
Expand All @@ -306,8 +309,6 @@ def async_cast_discovered(discover: ChromecastInfo) -> None:
if info.friendly_name is None:
_LOGGER.debug("Cannot retrieve detail information for chromecast"
" %s, the device may not be online", info)
remove_handler()
raise PlatformNotReady

hass.async_add_job(_discover_chromecast, hass, info)

Expand Down Expand Up @@ -477,16 +478,10 @@ async def async_set_cast_info(self, cast_info):
))
self._chromecast = chromecast
self._status_listener = CastStatusListener(self, chromecast)
# Initialise connection status as connected because we can only
# register the connection listener *after* the initial connection
# attempt. If the initial connection failed, we would never reach
# this code anyway.
self._available = True
self._available = False
self.cast_status = chromecast.status
self.media_status = chromecast.media_controller.status
_LOGGER.debug("[%s %s (%s:%s)] Connection successful!",
self.entity_id, self._cast_info.friendly_name,
self._cast_info.host, self._cast_info.port)
self._chromecast.start()
self.async_schedule_update_ha_state()

async def async_del_cast_info(self, cast_info):
Expand Down Expand Up @@ -562,6 +557,10 @@ def new_connection_status(self, connection_status):
self.entity_id, self._cast_info.friendly_name,
self._cast_info.host, self._cast_info.port,
connection_status.status)
info = self._cast_info
if info.friendly_name is None and not info.is_audio_group:
# We couldn't find friendly_name when the cast was added, retry
self._cast_info = _fill_out_missing_chromecast_info(info)
self._available = new_available
self.schedule_update_ha_state()

Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Expand Up @@ -977,7 +977,7 @@ pycfdns==0.0.1
pychannels==1.0.0

# homeassistant.components.cast
pychromecast==2.5.2
pychromecast==3.0.0

# homeassistant.components.media_player.cmus
pycmus==0.1.1
Expand Down
11 changes: 4 additions & 7 deletions tests/components/cast/test_media_player.py
Expand Up @@ -222,13 +222,6 @@ async def test_normal_chromecast_not_starting_discovery(hass):
assert setup_discovery.call_count == 1


async def test_normal_raises_platform_not_ready(hass):
"""Test cast platform raises PlatformNotReady if HTTP dial fails."""
with patch('pychromecast.dial.get_device_status', return_value=None):
with pytest.raises(PlatformNotReady):
await async_setup_cast(hass, {'host': 'host1'})


async def test_replay_past_chromecasts(hass):
"""Test cast platform re-playing past chromecasts when adding new one."""
cast_group1 = get_fake_chromecast_info(host='host1', port=42)
Expand Down Expand Up @@ -262,6 +255,10 @@ async def test_entity_media_states(hass: HomeAssistantType):
return_value=full_info):
chromecast, entity = await async_setup_media_player_cast(hass, info)

entity._available = True
entity.schedule_update_ha_state()
await hass.async_block_till_done()

state = hass.states.get('media_player.speaker')
assert state is not None
assert state.name == 'Speaker'
Expand Down

0 comments on commit fc85b3f

Please sign in to comment.