Central update for Plex platforms (#27764)
* Update Plex platforms together * Remove unnecessary methods * Overhaul of Plex update logic * Apply suggestions from code review Use set instead of list Co-Authored-By: Martin Hjelmare <marhje52@kth.se> * Review suggestions and cleanup * Fixes, remove sensor throttle * Guarantee entity name, use common scheme * Keep name stable once set
This commit is contained in:
parent
5c50fa3405
commit
eeb1bfc6f5
6 changed files with 252 additions and 266 deletions
|
@ -1,17 +1,24 @@
|
|||
"""Shared class to maintain Plex server instances."""
|
||||
import logging
|
||||
|
||||
import plexapi.myplex
|
||||
import plexapi.playqueue
|
||||
import plexapi.server
|
||||
from requests import Session
|
||||
import requests.exceptions
|
||||
|
||||
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
|
||||
from homeassistant.const import CONF_TOKEN, CONF_URL, CONF_VERIFY_SSL
|
||||
from homeassistant.helpers.dispatcher import dispatcher_send
|
||||
|
||||
from .const import (
|
||||
CONF_SERVER,
|
||||
CONF_SHOW_ALL_CONTROLS,
|
||||
CONF_USE_EPISODE_ART,
|
||||
DEFAULT_VERIFY_SSL,
|
||||
PLEX_NEW_MP_SIGNAL,
|
||||
PLEX_UPDATE_MEDIA_PLAYER_SIGNAL,
|
||||
PLEX_UPDATE_SENSOR_SIGNAL,
|
||||
X_PLEX_DEVICE_NAME,
|
||||
X_PLEX_PLATFORM,
|
||||
X_PLEX_PRODUCT,
|
||||
|
@ -19,6 +26,8 @@ from .const import (
|
|||
)
|
||||
from .errors import NoServersFound, ServerNotSpecified
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# Set default headers sent by plexapi
|
||||
plexapi.X_PLEX_DEVICE_NAME = X_PLEX_DEVICE_NAME
|
||||
plexapi.X_PLEX_PLATFORM = X_PLEX_PLATFORM
|
||||
|
@ -31,9 +40,11 @@ plexapi.server.BASE_HEADERS = plexapi.reset_base_headers()
|
|||
class PlexServer:
|
||||
"""Manages a single Plex server connection."""
|
||||
|
||||
def __init__(self, server_config, options=None):
|
||||
def __init__(self, hass, server_config, options=None):
|
||||
"""Initialize a Plex server instance."""
|
||||
self._hass = hass
|
||||
self._plex_server = None
|
||||
self._known_clients = set()
|
||||
self._url = server_config.get(CONF_URL)
|
||||
self._token = server_config.get(CONF_TOKEN)
|
||||
self._server_name = server_config.get(CONF_SERVER)
|
||||
|
@ -76,13 +87,69 @@ class PlexServer:
|
|||
else:
|
||||
_connect_with_token()
|
||||
|
||||
def clients(self):
|
||||
"""Pass through clients call to plexapi."""
|
||||
return self._plex_server.clients()
|
||||
def refresh_entity(self, machine_identifier, device, session):
|
||||
"""Forward refresh dispatch to media_player."""
|
||||
dispatcher_send(
|
||||
self._hass,
|
||||
PLEX_UPDATE_MEDIA_PLAYER_SIGNAL.format(machine_identifier),
|
||||
device,
|
||||
session,
|
||||
)
|
||||
|
||||
def sessions(self):
|
||||
"""Pass through sessions call to plexapi."""
|
||||
return self._plex_server.sessions()
|
||||
def update_platforms(self):
|
||||
"""Update the platform entities."""
|
||||
available_clients = {}
|
||||
new_clients = set()
|
||||
|
||||
try:
|
||||
devices = self._plex_server.clients()
|
||||
sessions = self._plex_server.sessions()
|
||||
except plexapi.exceptions.BadRequest:
|
||||
_LOGGER.exception("Error requesting Plex client data from server")
|
||||
return
|
||||
except requests.exceptions.RequestException as ex:
|
||||
_LOGGER.warning(
|
||||
"Could not connect to Plex server: %s (%s)", self.friendly_name, ex
|
||||
)
|
||||
return
|
||||
|
||||
for device in devices:
|
||||
available_clients[device.machineIdentifier] = {"device": device}
|
||||
|
||||
if device.machineIdentifier not in self._known_clients:
|
||||
new_clients.add(device.machineIdentifier)
|
||||
_LOGGER.debug("New device: %s", device.machineIdentifier)
|
||||
|
||||
for session in sessions:
|
||||
for player in session.players:
|
||||
available_clients.setdefault(
|
||||
player.machineIdentifier, {"device": player}
|
||||
)
|
||||
available_clients[player.machineIdentifier]["session"] = session
|
||||
|
||||
if player.machineIdentifier not in self._known_clients:
|
||||
new_clients.add(player.machineIdentifier)
|
||||
_LOGGER.debug("New session: %s", player.machineIdentifier)
|
||||
|
||||
new_entity_configs = []
|
||||
for client_id, client_data in available_clients.items():
|
||||
if client_id in new_clients:
|
||||
new_entity_configs.append(client_data)
|
||||
else:
|
||||
self.refresh_entity(
|
||||
client_id, client_data["device"], client_data.get("session")
|
||||
)
|
||||
|
||||
self._known_clients.update(new_clients)
|
||||
|
||||
idle_clients = self._known_clients.difference(available_clients)
|
||||
for client_id in idle_clients:
|
||||
self.refresh_entity(client_id, None, None)
|
||||
|
||||
if new_entity_configs:
|
||||
dispatcher_send(self._hass, PLEX_NEW_MP_SIGNAL, new_entity_configs)
|
||||
|
||||
dispatcher_send(self._hass, PLEX_UPDATE_SENSOR_SIGNAL, sessions)
|
||||
|
||||
@property
|
||||
def friendly_name(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue