From eda9291ca1ec966c7a5855db8bcd816baf01866c Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 22 Dec 2021 14:54:36 +0100 Subject: [PATCH] Improve google cast state reporting (#62587) --- homeassistant/components/cast/media_player.py | 7 +++- tests/components/cast/test_media_player.py | 34 +++++++++++++++---- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/cast/media_player.py b/homeassistant/components/cast/media_player.py index 8160c1f5bf0..f3cc9c32661 100644 --- a/homeassistant/components/cast/media_player.py +++ b/homeassistant/components/cast/media_player.py @@ -76,6 +76,8 @@ from .helpers import CastStatusListener, ChromecastInfo, ChromeCastZeroconf _LOGGER = logging.getLogger(__name__) +APP_IDS_UNRELIABLE_MEDIA_INFO = ("Netflix",) + CAST_SPLASH = "https://www.home-assistant.io/images/cast/splash.png" SUPPORT_CAST = SUPPORT_PLAY_MEDIA | SUPPORT_TURN_OFF @@ -564,7 +566,10 @@ class CastDevice(MediaPlayerEntity): if media_status.player_is_idle: return STATE_IDLE if self.app_id is not None and self.app_id != pychromecast.IDLE_APP_ID: - return STATE_PLAYING + if self.app_id in APP_IDS_UNRELIABLE_MEDIA_INFO: + # Some apps don't report media status, show the player as playing + return STATE_PLAYING + return STATE_IDLE if self._chromecast is not None and self._chromecast.is_idle: return STATE_OFF return None diff --git a/tests/components/cast/test_media_player.py b/tests/components/cast/test_media_player.py index 3c5d4705713..9bf1175c1b9 100644 --- a/tests/components/cast/test_media_player.py +++ b/tests/components/cast/test_media_player.py @@ -1082,7 +1082,12 @@ async def test_entity_control(hass: HomeAssistant): chromecast.media_controller.seek.assert_called_once_with(123) -async def test_entity_media_states(hass: HomeAssistant): +# Some smart TV's with Google TV report "Netflix", not the Netflix app's ID +@pytest.mark.parametrize( + "app_id, state_no_media", + [(pychromecast.APP_YOUTUBE, "idle"), ("Netflix", "playing")], +) +async def test_entity_media_states(hass: HomeAssistant, app_id, state_no_media): """Test various entity media states.""" entity_id = "media_player.speaker" reg = er.async_get(hass) @@ -1090,7 +1095,7 @@ async def test_entity_media_states(hass: HomeAssistant): info = get_fake_chromecast_info() chromecast, _ = await async_setup_media_player_cast(hass, info) - _, conn_status_cb, media_status_cb = get_status_callbacks(chromecast) + cast_status_cb, conn_status_cb, media_status_cb = get_status_callbacks(chromecast) connection_status = MagicMock() connection_status.status = "CONNECTED" @@ -1103,6 +1108,15 @@ async def test_entity_media_states(hass: HomeAssistant): assert state.state == "off" assert entity_id == reg.async_get_entity_id("media_player", "cast", str(info.uuid)) + # App id updated, but no media status + chromecast.app_id = app_id + cast_status = MagicMock() + cast_status_cb(cast_status) + await hass.async_block_till_done() + state = hass.states.get(entity_id) + assert state.state == state_no_media + + # Got media status media_status = MagicMock(images=None) media_status.player_is_playing = True media_status_cb(media_status) @@ -1124,15 +1138,23 @@ async def test_entity_media_states(hass: HomeAssistant): state = hass.states.get(entity_id) assert state.state == "idle" - media_status.player_is_idle = False - chromecast.is_idle = True - media_status_cb(media_status) + # No media status, app is still running + media_status_cb(None) + await hass.async_block_till_done() + state = hass.states.get(entity_id) + assert state.state == state_no_media + + # App no longer running + chromecast.app_id = pychromecast.IDLE_APP_ID + cast_status = MagicMock() + cast_status_cb(cast_status) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == "off" + # No cast status chromecast.is_idle = False - media_status_cb(media_status) + cast_status_cb(None) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == "unknown"