Use friendly name for camera media source (#110882)

This commit is contained in:
On Freund 2024-03-12 22:20:14 +02:00 committed by GitHub
parent 46ce438b6d
commit b9837a561b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 68 additions and 4 deletions

View File

@ -13,6 +13,7 @@ from homeassistant.components.media_source.models import (
PlayMedia,
)
from homeassistant.components.stream import FORMAT_CONTENT_TYPE, HLS_PROVIDER
from homeassistant.const import ATTR_FRIENDLY_NAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_component import EntityComponent
@ -26,13 +27,20 @@ async def async_get_media_source(hass: HomeAssistant) -> CameraMediaSource:
return CameraMediaSource(hass)
def _media_source_for_camera(camera: Camera, content_type: str) -> BrowseMediaSource:
def _media_source_for_camera(
hass: HomeAssistant, camera: Camera, content_type: str
) -> BrowseMediaSource:
camera_state = hass.states.get(camera.entity_id)
title = camera.name
if camera_state:
title = camera_state.attributes.get(ATTR_FRIENDLY_NAME, camera.name)
return BrowseMediaSource(
domain=DOMAIN,
identifier=camera.entity_id,
media_class=MediaClass.VIDEO,
media_content_type=content_type,
title=camera.name,
title=title,
thumbnail=f"/api/camera_proxy/{camera.entity_id}",
can_play=True,
can_expand=False,
@ -90,7 +98,7 @@ class CameraMediaSource(MediaSource):
async def _filter_browsable_camera(camera: Camera) -> BrowseMediaSource | None:
stream_type = camera.frontend_stream_type
if stream_type is None:
return _media_source_for_camera(camera, camera.content_type)
return _media_source_for_camera(self.hass, camera, camera.content_type)
if not can_stream_hls:
return None
@ -98,7 +106,7 @@ class CameraMediaSource(MediaSource):
if stream_type != StreamType.HLS and not (await camera.stream_source()):
return None
return _media_source_for_camera(camera, content_type)
return _media_source_for_camera(self.hass, camera, content_type)
component: EntityComponent[Camera] = self.hass.data[DOMAIN]
results = await asyncio.gather(

View File

@ -8,6 +8,7 @@ from homeassistant.components import camera
from homeassistant.components.camera.const import StreamType
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.setup import async_setup_component
from .common import WEBRTC_ANSWER
@ -70,3 +71,37 @@ async def mock_camera_web_rtc_fixture(hass):
return_value=WEBRTC_ANSWER,
):
yield
@pytest.fixture(name="mock_camera_with_device")
async def mock_camera_with_device_fixture():
"""Initialize a demo camera platform with a device."""
dev_info = DeviceInfo(
identifiers={("camera", "test_unique_id")},
name="Test Camera Device",
)
class UniqueIdMock(PropertyMock):
def __get__(self, obj, obj_type=None):
return obj.name
with patch(
"homeassistant.components.camera.Camera.has_entity_name",
new_callable=PropertyMock(return_value=True),
), patch(
"homeassistant.components.camera.Camera.unique_id", new=UniqueIdMock()
), patch(
"homeassistant.components.camera.Camera.device_info",
new_callable=PropertyMock(return_value=dev_info),
):
yield
@pytest.fixture(name="mock_camera_with_no_name")
async def mock_camera_with_no_name_fixture(mock_camera_with_device):
"""Initialize a demo camera platform with a device and no name."""
with patch(
"homeassistant.components.camera.Camera._attr_name",
new_callable=PropertyMock(return_value=None),
):
yield

View File

@ -17,6 +17,26 @@ async def setup_media_source(hass):
assert await async_setup_component(hass, "media_source", {})
async def test_device_with_device(
hass: HomeAssistant, mock_camera_with_device, mock_camera
) -> None:
"""Test browsing when camera has a device and a name."""
item = await media_source.async_browse_media(hass, "media-source://camera")
assert item.not_shown == 2
assert len(item.children) == 1
assert item.children[0].title == "Test Camera Device Demo camera without stream"
async def test_device_with_no_name(
hass: HomeAssistant, mock_camera_with_no_name, mock_camera
) -> None:
"""Test browsing when camera has device and name == None."""
item = await media_source.async_browse_media(hass, "media-source://camera")
assert item.not_shown == 2
assert len(item.children) == 1
assert item.children[0].title == "Test Camera Device Demo camera without stream"
async def test_browsing_hls(hass: HomeAssistant, mock_camera_hls) -> None:
"""Test browsing HLS camera media source."""
item = await media_source.async_browse_media(hass, "media-source://camera")
@ -42,6 +62,7 @@ async def test_browsing_mjpeg(hass: HomeAssistant, mock_camera) -> None:
assert len(item.children) == 1
assert item.not_shown == 2
assert item.children[0].media_content_type == "image/jpg"
assert item.children[0].title == "Demo camera without stream"
async def test_browsing_web_rtc(hass: HomeAssistant, mock_camera_web_rtc) -> None: