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, const as heos_const,
) )
from pyheos.util import mediauri as heos_source from pyheos.util import mediauri as heos_source
import voluptuous as vol
from homeassistant.components import media_source from homeassistant.components import media_source
from homeassistant.components.media_player import ( from homeassistant.components.media_player import (
ATTR_MEDIA_ENQUEUE, ATTR_MEDIA_ENQUEUE,
ATTR_MEDIA_VOLUME_LEVEL,
BrowseError, BrowseError,
BrowseMedia, BrowseMedia,
MediaClass, MediaClass,
@ -43,32 +41,16 @@ from homeassistant.components.media_player import (
) )
from homeassistant.components.media_source import BrowseMediaSource from homeassistant.components.media_source import BrowseMediaSource
from homeassistant.const import Platform from homeassistant.const import Platform
from homeassistant.core import ( from homeassistant.core import HomeAssistant, ServiceResponse, callback
HomeAssistant,
ServiceResponse,
SupportsResponse,
callback,
)
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import ( from homeassistant.helpers import entity_registry as er
config_validation as cv,
entity_platform,
entity_registry as er,
)
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util.dt import utcnow from homeassistant.util.dt import utcnow
from .const import ( from . import services
ATTR_QUEUE_IDS, from .const import DOMAIN as HEOS_DOMAIN
DOMAIN as HEOS_DOMAIN,
SERVICE_GET_QUEUE,
SERVICE_GROUP_VOLUME_DOWN,
SERVICE_GROUP_VOLUME_SET,
SERVICE_GROUP_VOLUME_UP,
SERVICE_REMOVE_FROM_QUEUE,
)
from .coordinator import HeosConfigEntry, HeosCoordinator from .coordinator import HeosConfigEntry, HeosCoordinator
PARALLEL_UPDATES = 0 PARALLEL_UPDATES = 0
@ -139,36 +121,7 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Add media players for a config entry.""" """Add media players for a config entry."""
# Register custom entity services services.register_media_player_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"
)
def add_entities_callback(players: Sequence[HeosPlayer]) -> None: def add_entities_callback(players: Sequence[HeosPlayer]) -> None:
"""Add entities for each player.""" """Add entities for each player."""

View File

@ -1,19 +1,33 @@
"""Services for the HEOS integration.""" """Services for the HEOS integration."""
from dataclasses import dataclass
import logging import logging
from typing import Final
from pyheos import CommandAuthenticationError, Heos, HeosError from pyheos import CommandAuthenticationError, Heos, HeosError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.media_player import ATTR_MEDIA_VOLUME_LEVEL
from homeassistant.config_entries import ConfigEntryState 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.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 ( from .const import (
ATTR_PASSWORD, ATTR_PASSWORD,
ATTR_QUEUE_IDS,
ATTR_USERNAME, ATTR_USERNAME,
DOMAIN, 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_IN,
SERVICE_SIGN_OUT, 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: def _get_controller(hass: HomeAssistant) -> Heos:
"""Get the HEOS controller instance.""" """Get the HEOS controller instance."""
_LOGGER.warning( _LOGGER.warning(