diff --git a/homeassistant/components/cast/helpers.py b/homeassistant/components/cast/helpers.py index d7419f69563..48f57c39bd5 100644 --- a/homeassistant/components/cast/helpers.py +++ b/homeassistant/components/cast/helpers.py @@ -37,7 +37,7 @@ class ChromecastInfo: @property def friendly_name(self) -> str: - """Return the UUID.""" + """Return the Friendly Name.""" return self.cast_info.friendly_name @property diff --git a/homeassistant/components/cast/media_player.py b/homeassistant/components/cast/media_player.py index 958c53ae394..c8a6a82571e 100644 --- a/homeassistant/components/cast/media_player.py +++ b/homeassistant/components/cast/media_player.py @@ -441,6 +441,19 @@ class CastMediaPlayerEntity(CastDevice, MediaPlayerEntity): connection_status.status, ) self._attr_available = new_available + if new_available and not self._cast_info.is_audio_group: + # Poll current group status + for group_uuid in self.mz_mgr.get_multizone_memberships( + self._cast_info.uuid + ): + group_media_controller = self.mz_mgr.get_multizone_mediacontroller( + group_uuid + ) + if not group_media_controller: + continue + self.multizone_new_media_status( + group_uuid, group_media_controller.status + ) self.schedule_update_ha_state() def multizone_new_media_status(self, group_uuid, media_status): diff --git a/tests/components/cast/test_media_player.py b/tests/components/cast/test_media_player.py index 00626cc8c16..ed575c0fa22 100644 --- a/tests/components/cast/test_media_player.py +++ b/tests/components/cast/test_media_player.py @@ -731,6 +731,20 @@ async def test_entity_availability(hass: HomeAssistant): state = hass.states.get(entity_id) assert state.state == "off" + connection_status = MagicMock() + connection_status.status = "LOST" + conn_status_cb(connection_status) + await hass.async_block_till_done() + state = hass.states.get(entity_id) + assert state.state == "unavailable" + + connection_status = MagicMock() + connection_status.status = "CONNECTED" + conn_status_cb(connection_status) + await hass.async_block_till_done() + state = hass.states.get(entity_id) + assert state.state == "off" + connection_status = MagicMock() connection_status.status = "DISCONNECTED" conn_status_cb(connection_status) @@ -738,6 +752,14 @@ async def test_entity_availability(hass: HomeAssistant): state = hass.states.get(entity_id) assert state.state == "unavailable" + # Can't reconnect after receiving DISCONNECTED + connection_status = MagicMock() + connection_status.status = "CONNECTED" + conn_status_cb(connection_status) + await hass.async_block_till_done() + state = hass.states.get(entity_id) + assert state.state == "unavailable" + @pytest.mark.parametrize("port,entry_type", ((8009, None), (12345, None))) async def test_device_registry(hass: HomeAssistant, hass_ws_client, port, entry_type): @@ -1675,6 +1697,59 @@ async def test_group_media_states(hass, mz_mock): assert state.state == "playing" +async def test_group_media_states_early(hass, mz_mock): + """Test media states are read from group if entity has no state. + + This tests case asserts group state is polled when the player is created. + """ + entity_id = "media_player.speaker" + reg = er.async_get(hass) + + info = get_fake_chromecast_info() + + mz_mock.get_multizone_memberships = MagicMock(return_value=[str(FakeGroupUUID)]) + mz_mock.get_multizone_mediacontroller = MagicMock( + return_value=MagicMock(status=MagicMock(images=None, player_state="BUFFERING")) + ) + + chromecast, _ = await async_setup_media_player_cast(hass, info) + _, conn_status_cb, _, _ = get_status_callbacks(chromecast, mz_mock) + + state = hass.states.get(entity_id) + assert state is not None + assert state.name == "Speaker" + assert state.state == "unavailable" + assert entity_id == reg.async_get_entity_id("media_player", "cast", str(info.uuid)) + + # Check group state is polled when player is first created + connection_status = MagicMock() + connection_status.status = "CONNECTED" + conn_status_cb(connection_status) + await hass.async_block_till_done() + + assert hass.states.get(entity_id).state == "buffering" + + connection_status = MagicMock() + connection_status.status = "LOST" + conn_status_cb(connection_status) + await hass.async_block_till_done() + + assert hass.states.get(entity_id).state == "unavailable" + + # Check group state is polled when player reconnects + mz_mock.get_multizone_mediacontroller = MagicMock( + return_value=MagicMock(status=MagicMock(images=None, player_state="PLAYING")) + ) + + connection_status = MagicMock() + connection_status.status = "CONNECTED" + conn_status_cb(connection_status) + await hass.async_block_till_done() + await hass.async_block_till_done() + + assert hass.states.get(entity_id).state == "playing" + + async def test_group_media_control(hass, mz_mock, quick_play_mock): """Test media controls are handled by group if entity has no state.""" entity_id = "media_player.speaker"