176 lines
5.5 KiB
Python
176 lines
5.5 KiB
Python
"""Platform for update integration for squeezebox."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from datetime import datetime
|
|
import logging
|
|
from typing import Any
|
|
|
|
from homeassistant.components.update import (
|
|
UpdateEntity,
|
|
UpdateEntityDescription,
|
|
UpdateEntityFeature,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|
from homeassistant.helpers.event import async_call_later
|
|
|
|
from . import SqueezeboxConfigEntry
|
|
from .const import (
|
|
DOMAIN,
|
|
SERVER_MODEL,
|
|
STATUS_QUERY_VERSION,
|
|
STATUS_UPDATE_NEWPLUGINS,
|
|
STATUS_UPDATE_NEWVERSION,
|
|
UPDATE_PLUGINS_RELEASE_SUMMARY,
|
|
UPDATE_RELEASE_SUMMARY,
|
|
)
|
|
from .entity import LMSStatusEntity
|
|
|
|
newserver = UpdateEntityDescription(
|
|
key=STATUS_UPDATE_NEWVERSION,
|
|
)
|
|
|
|
newplugins = UpdateEntityDescription(
|
|
key=STATUS_UPDATE_NEWPLUGINS,
|
|
)
|
|
|
|
POLL_AFTER_INSTALL = 120
|
|
|
|
# Coordinator is used to centralize the data updates
|
|
PARALLEL_UPDATES = 0
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
entry: SqueezeboxConfigEntry,
|
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
) -> None:
|
|
"""Platform setup using common elements."""
|
|
|
|
async_add_entities(
|
|
[
|
|
ServerStatusUpdateLMS(entry.runtime_data.coordinator, newserver),
|
|
ServerStatusUpdatePlugins(entry.runtime_data.coordinator, newplugins),
|
|
]
|
|
)
|
|
|
|
|
|
class ServerStatusUpdate(LMSStatusEntity, UpdateEntity):
|
|
"""LMS Status update sensors via cooridnatior."""
|
|
|
|
@property
|
|
def latest_version(self) -> str:
|
|
"""LMS Status directly from coordinator data."""
|
|
return str(self.coordinator.data[self.entity_description.key])
|
|
|
|
|
|
class ServerStatusUpdateLMS(ServerStatusUpdate):
|
|
"""LMS Status update sensor from LMS via cooridnatior."""
|
|
|
|
title: str = SERVER_MODEL
|
|
|
|
@property
|
|
def installed_version(self) -> str:
|
|
"""LMS Status directly from coordinator data."""
|
|
return str(self.coordinator.data[STATUS_QUERY_VERSION])
|
|
|
|
@property
|
|
def release_url(self) -> str:
|
|
"""LMS Update info page."""
|
|
return str(self.coordinator.lms.generate_image_url("updateinfo.html"))
|
|
|
|
@property
|
|
def release_summary(self) -> None | str:
|
|
"""If install is supported give some info."""
|
|
return (
|
|
str(self.coordinator.data[UPDATE_RELEASE_SUMMARY])
|
|
if self.coordinator.data[UPDATE_RELEASE_SUMMARY]
|
|
else None
|
|
)
|
|
|
|
|
|
class ServerStatusUpdatePlugins(ServerStatusUpdate):
|
|
"""LMS Plugings update sensor from LMS via cooridnatior."""
|
|
|
|
auto_update = True
|
|
title: str = SERVER_MODEL + " Plugins"
|
|
installed_version = "Current"
|
|
restart_triggered = False
|
|
_cancel_update: Callable | None = None
|
|
|
|
@property
|
|
def supported_features(self) -> UpdateEntityFeature:
|
|
"""Support install if we can."""
|
|
return (
|
|
(UpdateEntityFeature.INSTALL | UpdateEntityFeature.PROGRESS)
|
|
if self.coordinator.can_server_restart
|
|
else UpdateEntityFeature(0)
|
|
)
|
|
|
|
@property
|
|
def release_summary(self) -> None | str:
|
|
"""If install is supported give some info."""
|
|
rs = self.coordinator.data[UPDATE_PLUGINS_RELEASE_SUMMARY]
|
|
return (
|
|
(rs or "")
|
|
+ "The Plugins will be updated on the next restart triggred by selecting the Install button. Allow enough time for the service to restart. It will become briefly unavailable."
|
|
if self.coordinator.can_server_restart
|
|
else rs
|
|
)
|
|
|
|
@property
|
|
def release_url(self) -> str:
|
|
"""LMS Plugins info page."""
|
|
return str(
|
|
self.coordinator.lms.generate_image_url(
|
|
"/settings/index.html?activePage=SETUP_PLUGINS"
|
|
)
|
|
)
|
|
|
|
@property
|
|
def in_progress(self) -> bool:
|
|
"""Are we restarting."""
|
|
if self.latest_version == self.installed_version and self.restart_triggered:
|
|
_LOGGER.debug("plugin progress reset %s", self.coordinator.lms.name)
|
|
if callable(self._cancel_update):
|
|
self._cancel_update()
|
|
self.restart_triggered = False
|
|
return self.restart_triggered
|
|
|
|
async def async_install(
|
|
self, version: str | None, backup: bool, **kwargs: Any
|
|
) -> None:
|
|
"""Install all plugin updates."""
|
|
_LOGGER.debug(
|
|
"server restart for plugin install on %s", self.coordinator.lms.name
|
|
)
|
|
self.restart_triggered = True
|
|
self.async_write_ha_state()
|
|
|
|
result = await self.coordinator.lms.async_query("restartserver")
|
|
_LOGGER.debug("restart server result %s", result)
|
|
if not result:
|
|
self._cancel_update = async_call_later(
|
|
self.hass, POLL_AFTER_INSTALL, self._async_update_catchall
|
|
)
|
|
else:
|
|
self.restart_triggered = False
|
|
self.async_write_ha_state()
|
|
raise HomeAssistantError(
|
|
translation_domain=DOMAIN,
|
|
translation_key="update_restart_failed",
|
|
)
|
|
|
|
async def _async_update_catchall(self, now: datetime | None = None) -> None:
|
|
"""Request update. clear restart catchall."""
|
|
if self.restart_triggered:
|
|
_LOGGER.debug("server restart catchall for %s", self.coordinator.lms.name)
|
|
self.restart_triggered = False
|
|
self.async_write_ha_state()
|
|
await self.async_update()
|