mirror of
https://github.com/home-assistant/core.git
synced 2025-07-12 15:57:06 +00:00
Detect newly connected clients in jellyfin (#89168)
This commit is contained in:
parent
680f3c27a5
commit
2e1f6cad96
@ -36,7 +36,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
server_info: dict[str, Any] = connect_result["Servers"][0]
|
server_info: dict[str, Any] = connect_result["Servers"][0]
|
||||||
|
|
||||||
coordinators: dict[str, JellyfinDataUpdateCoordinator[Any]] = {
|
coordinators: dict[str, JellyfinDataUpdateCoordinator[Any]] = {
|
||||||
"sessions": SessionsDataUpdateCoordinator(hass, client, server_info, user_id),
|
"sessions": SessionsDataUpdateCoordinator(
|
||||||
|
hass, client, server_info, entry.data[CONF_CLIENT_DEVICE_ID], user_id
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
for coordinator in coordinators.values():
|
for coordinator in coordinators.values():
|
||||||
|
@ -11,7 +11,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from .const import DOMAIN, LOGGER
|
from .const import DOMAIN, LOGGER, USER_APP_NAME
|
||||||
|
|
||||||
JellyfinDataT = TypeVar(
|
JellyfinDataT = TypeVar(
|
||||||
"JellyfinDataT",
|
"JellyfinDataT",
|
||||||
@ -29,6 +29,7 @@ class JellyfinDataUpdateCoordinator(DataUpdateCoordinator[JellyfinDataT], ABC):
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
api_client: JellyfinClient,
|
api_client: JellyfinClient,
|
||||||
system_info: dict[str, Any],
|
system_info: dict[str, Any],
|
||||||
|
client_device_id: str,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the coordinator."""
|
"""Initialize the coordinator."""
|
||||||
@ -42,8 +43,11 @@ class JellyfinDataUpdateCoordinator(DataUpdateCoordinator[JellyfinDataT], ABC):
|
|||||||
self.server_id: str = system_info["Id"]
|
self.server_id: str = system_info["Id"]
|
||||||
self.server_name: str = system_info["Name"]
|
self.server_name: str = system_info["Name"]
|
||||||
self.server_version: str | None = system_info.get("Version")
|
self.server_version: str | None = system_info.get("Version")
|
||||||
|
self.client_device_id: str = client_device_id
|
||||||
self.user_id: str = user_id
|
self.user_id: str = user_id
|
||||||
|
|
||||||
|
self.session_ids: set[str] = set()
|
||||||
|
|
||||||
async def _async_update_data(self) -> JellyfinDataT:
|
async def _async_update_data(self) -> JellyfinDataT:
|
||||||
"""Get the latest data from Jellyfin."""
|
"""Get the latest data from Jellyfin."""
|
||||||
return await self._fetch_data()
|
return await self._fetch_data()
|
||||||
@ -65,7 +69,10 @@ class SessionsDataUpdateCoordinator(
|
|||||||
)
|
)
|
||||||
|
|
||||||
sessions_by_id: dict[str, dict[str, Any]] = {
|
sessions_by_id: dict[str, dict[str, Any]] = {
|
||||||
session["Id"]: session for session in sessions
|
session["Id"]: session
|
||||||
|
for session in sessions
|
||||||
|
if session["DeviceId"] != self.client_device_id
|
||||||
|
and session["Client"] != USER_APP_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessions_by_id
|
return sessions_by_id
|
||||||
|
@ -19,7 +19,7 @@ from homeassistant.util.dt import parse_datetime
|
|||||||
|
|
||||||
from .browse_media import build_item_response, build_root_response
|
from .browse_media import build_item_response, build_root_response
|
||||||
from .client_wrapper import get_artwork_url
|
from .client_wrapper import get_artwork_url
|
||||||
from .const import CONTENT_TYPE_MAP, DOMAIN, USER_APP_NAME
|
from .const import CONTENT_TYPE_MAP, DOMAIN, LOGGER
|
||||||
from .coordinator import JellyfinDataUpdateCoordinator
|
from .coordinator import JellyfinDataUpdateCoordinator
|
||||||
from .entity import JellyfinEntity
|
from .entity import JellyfinEntity
|
||||||
from .models import JellyfinData
|
from .models import JellyfinData
|
||||||
@ -34,14 +34,23 @@ async def async_setup_entry(
|
|||||||
jellyfin_data: JellyfinData = hass.data[DOMAIN][entry.entry_id]
|
jellyfin_data: JellyfinData = hass.data[DOMAIN][entry.entry_id]
|
||||||
coordinator = jellyfin_data.coordinators["sessions"]
|
coordinator = jellyfin_data.coordinators["sessions"]
|
||||||
|
|
||||||
async_add_entities(
|
@callback
|
||||||
(
|
def handle_coordinator_update() -> None:
|
||||||
JellyfinMediaPlayer(coordinator, session_id, session_data)
|
"""Add media player per session."""
|
||||||
for session_id, session_data in coordinator.data.items()
|
entities: list[MediaPlayerEntity] = []
|
||||||
if session_data["DeviceId"] != jellyfin_data.client_device_id
|
for session_id, session_data in coordinator.data.items():
|
||||||
and session_data["Client"] != USER_APP_NAME
|
if session_id not in coordinator.session_ids:
|
||||||
),
|
entity: MediaPlayerEntity = JellyfinMediaPlayer(
|
||||||
)
|
coordinator, session_id, session_data
|
||||||
|
)
|
||||||
|
LOGGER.debug("Creating media player for session: %s", session_id)
|
||||||
|
coordinator.session_ids.add(session_id)
|
||||||
|
entities.append(entity)
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
handle_coordinator_update()
|
||||||
|
|
||||||
|
entry.async_on_unload(coordinator.async_add_listener(handle_coordinator_update))
|
||||||
|
|
||||||
|
|
||||||
class JellyfinMediaPlayer(JellyfinEntity, MediaPlayerEntity):
|
class JellyfinMediaPlayer(JellyfinEntity, MediaPlayerEntity):
|
||||||
|
4846
tests/components/jellyfin/fixtures/sessions-new-client.json
Normal file
4846
tests/components/jellyfin/fixtures/sessions-new-client.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,8 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
|
|
||||||
|
from . import async_load_json_fixture
|
||||||
|
|
||||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
from tests.typing import WebSocketGenerator
|
from tests.typing import WebSocketGenerator
|
||||||
|
|
||||||
@ -353,3 +355,24 @@ async def test_browse_media(
|
|||||||
response["error"]["message"]
|
response["error"]["message"]
|
||||||
== "Media not found: collection / COLLECTION-UUID-404"
|
== "Media not found: collection / COLLECTION-UUID-404"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_new_client_connected(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
init_integration: MockConfigEntry,
|
||||||
|
mock_jellyfin: MagicMock,
|
||||||
|
mock_api: MagicMock,
|
||||||
|
) -> None:
|
||||||
|
"""Test Jellyfin media player reacts to new clients connecting."""
|
||||||
|
mock_api.sessions.return_value = await async_load_json_fixture(
|
||||||
|
hass,
|
||||||
|
"sessions-new-client.json",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(mock_api.sessions.mock_calls) == 1
|
||||||
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=10))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(mock_api.sessions.mock_calls) == 2
|
||||||
|
|
||||||
|
state = hass.states.get("media_player.jellyfin_device_five")
|
||||||
|
assert state
|
||||||
|
Loading…
x
Reference in New Issue
Block a user