Refactor registration of HEOS media player entity services (#141666)

Refactor entity service registration
This commit is contained in:
Andrew Sayre 2025-03-30 07:10:05 -05:00 committed by GitHub
parent eb90958341
commit a48dd05035
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 77 additions and 54 deletions

View File

@ -24,12 +24,10 @@ from pyheos import (
const as heos_const,
)
from pyheos.util import mediauri as heos_source
import voluptuous as vol
from homeassistant.components import media_source
from homeassistant.components.media_player import (
ATTR_MEDIA_ENQUEUE,
ATTR_MEDIA_VOLUME_LEVEL,
BrowseError,
BrowseMedia,
MediaClass,
@ -43,32 +41,16 @@ from homeassistant.components.media_player import (
)
from homeassistant.components.media_source import BrowseMediaSource
from homeassistant.const import Platform
from homeassistant.core import (
HomeAssistant,
ServiceResponse,
SupportsResponse,
callback,
)
from homeassistant.core import HomeAssistant, ServiceResponse, callback
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import (
config_validation as cv,
entity_platform,
entity_registry as er,
)
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util.dt import utcnow
from .const import (
ATTR_QUEUE_IDS,
DOMAIN as HEOS_DOMAIN,
SERVICE_GET_QUEUE,
SERVICE_GROUP_VOLUME_DOWN,
SERVICE_GROUP_VOLUME_SET,
SERVICE_GROUP_VOLUME_UP,
SERVICE_REMOVE_FROM_QUEUE,
)
from . import services
from .const import DOMAIN as HEOS_DOMAIN
from .coordinator import HeosConfigEntry, HeosCoordinator
PARALLEL_UPDATES = 0
@ -139,36 +121,7 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add media players for a config entry."""
# Register custom entity services
platform = entity_platform.async_get_current_platform()
platform.async_register_entity_service(
SERVICE_GET_QUEUE,
None,
"async_get_queue",
supports_response=SupportsResponse.ONLY,
)
platform.async_register_entity_service(
SERVICE_REMOVE_FROM_QUEUE,
{
vol.Required(ATTR_QUEUE_IDS): vol.All(
cv.ensure_list,
[vol.All(cv.positive_int, vol.Range(min=1))],
vol.Unique(),
)
},
"async_remove_from_queue",
)
platform.async_register_entity_service(
SERVICE_GROUP_VOLUME_SET,
{vol.Required(ATTR_MEDIA_VOLUME_LEVEL): cv.small_float},
"async_set_group_volume_level",
)
platform.async_register_entity_service(
SERVICE_GROUP_VOLUME_DOWN, None, "async_group_volume_down"
)
platform.async_register_entity_service(
SERVICE_GROUP_VOLUME_UP, None, "async_group_volume_up"
)
services.register_media_player_services()
def add_entities_callback(players: Sequence[HeosPlayer]) -> None:
"""Add entities for each player."""

View File

@ -1,19 +1,33 @@
"""Services for the HEOS integration."""
from dataclasses import dataclass
import logging
from typing import Final
from pyheos import CommandAuthenticationError, Heos, HeosError
import voluptuous as vol
from homeassistant.components.media_player import ATTR_MEDIA_VOLUME_LEVEL
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import HomeAssistant, ServiceCall, SupportsResponse
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import config_validation as cv, issue_registry as ir
from homeassistant.helpers import (
config_validation as cv,
entity_platform,
issue_registry as ir,
)
from homeassistant.helpers.typing import VolDictType, VolSchemaType
from .const import (
ATTR_PASSWORD,
ATTR_QUEUE_IDS,
ATTR_USERNAME,
DOMAIN,
SERVICE_GET_QUEUE,
SERVICE_GROUP_VOLUME_DOWN,
SERVICE_GROUP_VOLUME_SET,
SERVICE_GROUP_VOLUME_UP,
SERVICE_REMOVE_FROM_QUEUE,
SERVICE_SIGN_IN,
SERVICE_SIGN_OUT,
)
@ -44,6 +58,62 @@ def register(hass: HomeAssistant) -> None:
)
@dataclass(frozen=True)
class EntityServiceDescription:
"""Describe an entity service."""
name: str
method_name: str
schema: VolDictType | VolSchemaType | None = None
supports_response: SupportsResponse = SupportsResponse.NONE
def async_register(self, platform: entity_platform.EntityPlatform) -> None:
"""Register the service with the platform."""
platform.async_register_entity_service(
self.name,
self.schema,
self.method_name,
supports_response=self.supports_response,
)
REMOVE_FROM_QUEUE_SCHEMA: Final[VolDictType] = {
vol.Required(ATTR_QUEUE_IDS): vol.All(
cv.ensure_list,
[vol.All(cv.positive_int, vol.Range(min=1))],
vol.Unique(),
)
}
GROUP_VOLUME_SET_SCHEMA: Final[VolDictType] = {
vol.Required(ATTR_MEDIA_VOLUME_LEVEL): cv.small_float
}
MEDIA_PLAYER_ENTITY_SERVICES: Final = (
# Player queue services
EntityServiceDescription(
SERVICE_GET_QUEUE, "async_get_queue", supports_response=SupportsResponse.ONLY
),
EntityServiceDescription(
SERVICE_REMOVE_FROM_QUEUE, "async_remove_from_queue", REMOVE_FROM_QUEUE_SCHEMA
),
# Group volume services
EntityServiceDescription(
SERVICE_GROUP_VOLUME_SET,
"async_set_group_volume_level",
GROUP_VOLUME_SET_SCHEMA,
),
EntityServiceDescription(SERVICE_GROUP_VOLUME_DOWN, "async_group_volume_down"),
EntityServiceDescription(SERVICE_GROUP_VOLUME_UP, "async_group_volume_up"),
)
def register_media_player_services() -> None:
"""Register media_player entity services."""
platform = entity_platform.async_get_current_platform()
for service in MEDIA_PLAYER_ENTITY_SERVICES:
service.async_register(platform)
def _get_controller(hass: HomeAssistant) -> Heos:
"""Get the HEOS controller instance."""
_LOGGER.warning(