Assign plex update entity to server device (#143654)

* Assign plex update entity to server device

* Fix tests

* Apply suggestions from code review

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Paul Bottein 2025-04-25 11:21:14 +02:00 committed by GitHub
parent fa0bb35e6c
commit 2be6ecd50f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 15 deletions

View File

@ -62,6 +62,11 @@
"scan_clients": { "scan_clients": {
"name": "Scan clients" "name": "Scan clients"
} }
},
"update": {
"server_update": {
"name": "[%key:component::update::title%]"
}
} }
}, },
"services": { "services": {

View File

@ -4,16 +4,16 @@ import logging
from typing import Any from typing import Any
from plexapi.exceptions import PlexApiException from plexapi.exceptions import PlexApiException
import plexapi.server
import requests.exceptions import requests.exceptions
from homeassistant.components.update import UpdateEntity, UpdateEntityFeature from homeassistant.components.update import UpdateEntity, UpdateEntityFeature
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import CONF_SERVER_IDENTIFIER from .const import CONF_SERVER_IDENTIFIER, DOMAIN
from .helpers import get_plex_server from .helpers import get_plex_server
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -27,9 +27,8 @@ async def async_setup_entry(
"""Set up Plex update entities from a config entry.""" """Set up Plex update entities from a config entry."""
server_id = config_entry.data[CONF_SERVER_IDENTIFIER] server_id = config_entry.data[CONF_SERVER_IDENTIFIER]
server = get_plex_server(hass, server_id) server = get_plex_server(hass, server_id)
plex_server = server.plex_server can_update = await hass.async_add_executor_job(server.plex_server.canInstallUpdate)
can_update = await hass.async_add_executor_job(plex_server.canInstallUpdate) async_add_entities([PlexUpdate(server, can_update)], update_before_add=True)
async_add_entities([PlexUpdate(plex_server, can_update)], update_before_add=True)
class PlexUpdate(UpdateEntity): class PlexUpdate(UpdateEntity):
@ -37,22 +36,21 @@ class PlexUpdate(UpdateEntity):
_attr_supported_features = UpdateEntityFeature.RELEASE_NOTES _attr_supported_features = UpdateEntityFeature.RELEASE_NOTES
_release_notes: str | None = None _release_notes: str | None = None
_attr_translation_key: str = "server_update"
_attr_has_entity_name = True
def __init__( def __init__(self, plex_server, can_update: bool) -> None:
self, plex_server: plexapi.server.PlexServer, can_update: bool
) -> None:
"""Initialize the Update entity.""" """Initialize the Update entity."""
self.plex_server = plex_server self._server = plex_server
self._attr_name = f"Plex Media Server ({plex_server.friendlyName})" self._attr_unique_id = plex_server.machine_identifier
self._attr_unique_id = plex_server.machineIdentifier
if can_update: if can_update:
self._attr_supported_features |= UpdateEntityFeature.INSTALL self._attr_supported_features |= UpdateEntityFeature.INSTALL
def update(self) -> None: def update(self) -> None:
"""Update sync attributes.""" """Update sync attributes."""
self._attr_installed_version = self.plex_server.version self._attr_installed_version = self._server.version
try: try:
if (release := self.plex_server.checkForUpdate()) is None: if (release := self._server.plex_server.checkForUpdate()) is None:
self._attr_latest_version = self.installed_version self._attr_latest_version = self.installed_version
return return
except (requests.exceptions.RequestException, PlexApiException): except (requests.exceptions.RequestException, PlexApiException):
@ -73,6 +71,18 @@ class PlexUpdate(UpdateEntity):
def install(self, version: str | None, backup: bool, **kwargs: Any) -> None: def install(self, version: str | None, backup: bool, **kwargs: Any) -> None:
"""Install an update.""" """Install an update."""
try: try:
self.plex_server.installUpdate() self._server.plex_server.installUpdate()
except (requests.exceptions.RequestException, PlexApiException) as exc: except (requests.exceptions.RequestException, PlexApiException) as exc:
raise HomeAssistantError(str(exc)) from exc raise HomeAssistantError(str(exc)) from exc
@property
def device_info(self) -> DeviceInfo:
"""Return a device description for device registry."""
return DeviceInfo(
identifiers={(DOMAIN, self._server.machine_identifier)},
manufacturer="Plex",
model="Plex Media Server",
name=self._server.friendly_name,
sw_version=self._server.version,
configuration_url=f"{self._server.url_in_use}/web",
)

View File

@ -16,7 +16,7 @@ from homeassistant.util import dt as dt_util
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
UPDATE_ENTITY = "update.plex_media_server_plex_server_1" UPDATE_ENTITY = "update.plex_server_1_update"
async def test_plex_update( async def test_plex_update(