mirror of
https://github.com/home-assistant/core.git
synced 2025-07-08 13:57:10 +00:00
Use friendly name for camera media source (#110882)
This commit is contained in:
parent
46ce438b6d
commit
b9837a561b
@ -13,6 +13,7 @@ from homeassistant.components.media_source.models import (
|
|||||||
PlayMedia,
|
PlayMedia,
|
||||||
)
|
)
|
||||||
from homeassistant.components.stream import FORMAT_CONTENT_TYPE, HLS_PROVIDER
|
from homeassistant.components.stream import FORMAT_CONTENT_TYPE, HLS_PROVIDER
|
||||||
|
from homeassistant.const import ATTR_FRIENDLY_NAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
@ -26,13 +27,20 @@ async def async_get_media_source(hass: HomeAssistant) -> CameraMediaSource:
|
|||||||
return CameraMediaSource(hass)
|
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(
|
return BrowseMediaSource(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
identifier=camera.entity_id,
|
identifier=camera.entity_id,
|
||||||
media_class=MediaClass.VIDEO,
|
media_class=MediaClass.VIDEO,
|
||||||
media_content_type=content_type,
|
media_content_type=content_type,
|
||||||
title=camera.name,
|
title=title,
|
||||||
thumbnail=f"/api/camera_proxy/{camera.entity_id}",
|
thumbnail=f"/api/camera_proxy/{camera.entity_id}",
|
||||||
can_play=True,
|
can_play=True,
|
||||||
can_expand=False,
|
can_expand=False,
|
||||||
@ -90,7 +98,7 @@ class CameraMediaSource(MediaSource):
|
|||||||
async def _filter_browsable_camera(camera: Camera) -> BrowseMediaSource | None:
|
async def _filter_browsable_camera(camera: Camera) -> BrowseMediaSource | None:
|
||||||
stream_type = camera.frontend_stream_type
|
stream_type = camera.frontend_stream_type
|
||||||
if stream_type is None:
|
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:
|
if not can_stream_hls:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -98,7 +106,7 @@ class CameraMediaSource(MediaSource):
|
|||||||
if stream_type != StreamType.HLS and not (await camera.stream_source()):
|
if stream_type != StreamType.HLS and not (await camera.stream_source()):
|
||||||
return None
|
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]
|
component: EntityComponent[Camera] = self.hass.data[DOMAIN]
|
||||||
results = await asyncio.gather(
|
results = await asyncio.gather(
|
||||||
|
@ -8,6 +8,7 @@ from homeassistant.components import camera
|
|||||||
from homeassistant.components.camera.const import StreamType
|
from homeassistant.components.camera.const import StreamType
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from .common import WEBRTC_ANSWER
|
from .common import WEBRTC_ANSWER
|
||||||
@ -70,3 +71,37 @@ async def mock_camera_web_rtc_fixture(hass):
|
|||||||
return_value=WEBRTC_ANSWER,
|
return_value=WEBRTC_ANSWER,
|
||||||
):
|
):
|
||||||
yield
|
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
|
||||||
|
@ -17,6 +17,26 @@ async def setup_media_source(hass):
|
|||||||
assert await async_setup_component(hass, "media_source", {})
|
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:
|
async def test_browsing_hls(hass: HomeAssistant, mock_camera_hls) -> None:
|
||||||
"""Test browsing HLS camera media source."""
|
"""Test browsing HLS camera media source."""
|
||||||
item = await media_source.async_browse_media(hass, "media-source://camera")
|
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 len(item.children) == 1
|
||||||
assert item.not_shown == 2
|
assert item.not_shown == 2
|
||||||
assert item.children[0].media_content_type == "image/jpg"
|
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:
|
async def test_browsing_web_rtc(hass: HomeAssistant, mock_camera_web_rtc) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user