Detect newly connected clients in jellyfin (#89168)
This commit is contained in:
parent
680f3c27a5
commit
2e1f6cad96
5 changed files with 4899 additions and 12 deletions
|
@ -36,7 +36,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
server_info: dict[str, Any] = connect_result["Servers"][0]
|
||||
|
||||
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():
|
||||
|
|
|
@ -11,7 +11,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from .const import DOMAIN, LOGGER
|
||||
from .const import DOMAIN, LOGGER, USER_APP_NAME
|
||||
|
||||
JellyfinDataT = TypeVar(
|
||||
"JellyfinDataT",
|
||||
|
@ -29,6 +29,7 @@ class JellyfinDataUpdateCoordinator(DataUpdateCoordinator[JellyfinDataT], ABC):
|
|||
hass: HomeAssistant,
|
||||
api_client: JellyfinClient,
|
||||
system_info: dict[str, Any],
|
||||
client_device_id: str,
|
||||
user_id: str,
|
||||
) -> None:
|
||||
"""Initialize the coordinator."""
|
||||
|
@ -42,8 +43,11 @@ class JellyfinDataUpdateCoordinator(DataUpdateCoordinator[JellyfinDataT], ABC):
|
|||
self.server_id: str = system_info["Id"]
|
||||
self.server_name: str = system_info["Name"]
|
||||
self.server_version: str | None = system_info.get("Version")
|
||||
self.client_device_id: str = client_device_id
|
||||
self.user_id: str = user_id
|
||||
|
||||
self.session_ids: set[str] = set()
|
||||
|
||||
async def _async_update_data(self) -> JellyfinDataT:
|
||||
"""Get the latest data from Jellyfin."""
|
||||
return await self._fetch_data()
|
||||
|
@ -65,7 +69,10 @@ class SessionsDataUpdateCoordinator(
|
|||
)
|
||||
|
||||
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
|
||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.util.dt import parse_datetime
|
|||
|
||||
from .browse_media import build_item_response, build_root_response
|
||||
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 .entity import JellyfinEntity
|
||||
from .models import JellyfinData
|
||||
|
@ -34,14 +34,23 @@ async def async_setup_entry(
|
|||
jellyfin_data: JellyfinData = hass.data[DOMAIN][entry.entry_id]
|
||||
coordinator = jellyfin_data.coordinators["sessions"]
|
||||
|
||||
async_add_entities(
|
||||
(
|
||||
JellyfinMediaPlayer(coordinator, session_id, session_data)
|
||||
for session_id, session_data in coordinator.data.items()
|
||||
if session_data["DeviceId"] != jellyfin_data.client_device_id
|
||||
and session_data["Client"] != USER_APP_NAME
|
||||
),
|
||||
)
|
||||
@callback
|
||||
def handle_coordinator_update() -> None:
|
||||
"""Add media player per session."""
|
||||
entities: list[MediaPlayerEntity] = []
|
||||
for session_id, session_data in coordinator.data.items():
|
||||
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):
|
||||
|
|
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.util.dt import utcnow
|
||||
|
||||
from . import async_load_json_fixture
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
from tests.typing import WebSocketGenerator
|
||||
|
||||
|
@ -353,3 +355,24 @@ async def test_browse_media(
|
|||
response["error"]["message"]
|
||||
== "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…
Add table
Reference in a new issue