Detect newly connected clients in jellyfin (#89168)

This commit is contained in:
Chris Talkington 2023-03-05 08:00:16 -06:00 committed by GitHub
parent 680f3c27a5
commit 2e1f6cad96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 4899 additions and 12 deletions

View file

@ -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():

View file

@ -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

View file

@ -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):

File diff suppressed because it is too large Load diff

View file

@ -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