diff --git a/homeassistant/components/nest/media_source.py b/homeassistant/components/nest/media_source.py index af8a4af8ba5..7a8ae49bdbc 100644 --- a/homeassistant/components/nest/media_source.py +++ b/homeassistant/components/nest/media_source.py @@ -339,15 +339,21 @@ class NestMediaSource(MediaSource): media_id: MediaId | None = parse_media_id(item.identifier) if not media_id: raise Unresolvable("No identifier specified for MediaSourceItem") - if not media_id.event_token: - raise Unresolvable( - "Identifier missing an event_token: %s" % item.identifier - ) devices = await self.devices() if not (device := devices.get(media_id.device_id)): raise Unresolvable( "Unable to find device with identifier: %s" % item.identifier ) + if not media_id.event_token: + # The device resolves to the most recent event if available + if not ( + last_event_id := await _async_get_recent_event_id(media_id, device) + ): + raise Unresolvable( + "Unable to resolve recent event for device: %s" % item.identifier + ) + media_id = last_event_id + # Infer content type from the device, since it only supports one # snapshot type (either jpg or mp4 clip) content_type = EventImageType.IMAGE.content_type @@ -384,6 +390,7 @@ class NestMediaSource(MediaSource): device_id=last_event_id.device_id, event_token=last_event_id.event_token, ) + browse_device.can_play = True browse_root.children.append(browse_device) return browse_root diff --git a/tests/components/nest/test_media_source.py b/tests/components/nest/test_media_source.py index 2361049ecc1..c733d4d3cfe 100644 --- a/tests/components/nest/test_media_source.py +++ b/tests/components/nest/test_media_source.py @@ -327,6 +327,7 @@ async def test_camera_event(hass, auth, hass_client): assert browse.children[0].identifier == device.id assert browse.children[0].title == "Front: Recent Events" assert browse.children[0].can_expand + assert browse.children[0].can_play # Expanding the root does not expand the device assert len(browse.children[0].children) == 0 @@ -371,6 +372,13 @@ async def test_camera_event(hass, auth, hass_client): contents = await response.read() assert contents == IMAGE_BYTES_FROM_EVENT + # Resolving the device id points to the most recent event + media = await media_source.async_resolve_media( + hass, f"{const.URI_SCHEME}{DOMAIN}/{device.id}" + ) + assert media.url == f"/api/nest/event_media/{device.id}/{event_identifier}" + assert media.mime_type == "image/jpeg" + async def test_event_order(hass, auth): """Test multiple events are in descending timestamp order.""" @@ -787,6 +795,7 @@ async def test_camera_event_clip_preview(hass, auth, hass_client, mp4): browse.children[0].thumbnail == f"/api/nest/event_media/{device.id}/{event_identifier}/thumbnail" ) + assert browse.children[0].can_play # Browse to the device browse = await media_source.async_browse_media( hass, f"{const.URI_SCHEME}{DOMAIN}/{device.id}" @@ -805,7 +814,6 @@ async def test_camera_event_clip_preview(hass, auth, hass_client, mp4): assert not browse.children[0].can_expand assert len(browse.children[0].children) == 0 assert browse.children[0].can_play - # No thumbnail support for mp4 clips yet assert ( browse.children[0].thumbnail == f"/api/nest/event_media/{device.id}/{event_identifier}/thumbnail" @@ -973,6 +981,10 @@ async def test_multiple_devices(hass, auth, hass_client): assert device2 # Very no events have been received yet + browse = await media_source.async_browse_media(hass, f"{const.URI_SCHEME}{DOMAIN}") + assert len(browse.children) == 2 + assert not browse.children[0].can_play + assert not browse.children[1].can_play browse = await media_source.async_browse_media( hass, f"{const.URI_SCHEME}{DOMAIN}/{device1.id}" ) @@ -998,6 +1010,10 @@ async def test_multiple_devices(hass, auth, hass_client): ) await hass.async_block_till_done() + browse = await media_source.async_browse_media(hass, f"{const.URI_SCHEME}{DOMAIN}") + assert len(browse.children) == 2 + assert browse.children[0].can_play + assert not browse.children[1].can_play browse = await media_source.async_browse_media( hass, f"{const.URI_SCHEME}{DOMAIN}/{device1.id}" ) @@ -1020,6 +1036,10 @@ async def test_multiple_devices(hass, auth, hass_client): ) await hass.async_block_till_done() + browse = await media_source.async_browse_media(hass, f"{const.URI_SCHEME}{DOMAIN}") + assert len(browse.children) == 2 + assert browse.children[0].can_play + assert browse.children[1].can_play browse = await media_source.async_browse_media( hass, f"{const.URI_SCHEME}{DOMAIN}/{device1.id}" ) @@ -1427,6 +1447,7 @@ async def test_camera_image_resize(hass, auth, hass_client): browse.children[0].thumbnail == f"/api/nest/event_media/{device.id}/{event_identifier}/thumbnail" ) + assert browse.children[0].can_play # Browse to device. No thumbnail is needed for the device on the device page browse = await media_source.async_browse_media(