Add HEOS entity service to remove queue items (#141495)

* Add remove queue items service

* Tests

* Correct casing of ID

* Match docs
This commit is contained in:
Andrew Sayre 2025-03-28 11:09:01 -05:00 committed by GitHub
parent 2121b943a3
commit ba00707d89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 0 deletions

View File

@ -2,11 +2,13 @@
ATTR_PASSWORD = "password"
ATTR_USERNAME = "username"
ATTR_QUEUE_IDS = "queue_ids"
DOMAIN = "heos"
ENTRY_TITLE = "HEOS System"
SERVICE_GET_QUEUE = "get_queue"
SERVICE_GROUP_VOLUME_SET = "group_volume_set"
SERVICE_GROUP_VOLUME_DOWN = "group_volume_down"
SERVICE_GROUP_VOLUME_UP = "group_volume_up"
SERVICE_REMOVE_FROM_QUEUE = "remove_from_queue"
SERVICE_SIGN_IN = "sign_in"
SERVICE_SIGN_OUT = "sign_out"

View File

@ -3,6 +3,9 @@
"get_queue": {
"service": "mdi:playlist-music"
},
"remove_from_queue": {
"service": "mdi:playlist-remove"
},
"group_volume_set": {
"service": "mdi:volume-medium"
},

View File

@ -61,11 +61,13 @@ 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 .coordinator import HeosConfigEntry, HeosCoordinator
@ -145,6 +147,17 @@ async def async_setup_entry(
"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},
@ -509,6 +522,10 @@ class HeosMediaPlayer(CoordinatorEntity[HeosCoordinator], MediaPlayerEntity):
await self.coordinator.heos.set_group(new_members)
return
async def async_remove_from_queue(self, queue_ids: list[int]) -> None:
"""Remove items from the queue."""
await self._player.remove_from_queue(queue_ids)
@property
def available(self) -> bool:
"""Return True if the device is available."""

View File

@ -4,6 +4,19 @@ get_queue:
integration: heos
domain: media_player
remove_from_queue:
target:
entity:
integration: heos
domain: media_player
fields:
queue_ids:
required: true
selector:
text:
multiple: true
type: number
group_volume_set:
target:
entity:

View File

@ -90,6 +90,16 @@
"name": "Get queue",
"description": "Retrieves the queue of the media player."
},
"remove_from_queue": {
"name": "Remove from queue",
"description": "Removes items from the play queue.",
"fields": {
"queue_ids": {
"name": "Queue IDs",
"description": "The IDs (indexes) of the items in the queue to remove."
}
}
},
"group_volume_down": {
"name": "Turn down group volume",
"description": "Turns down the group volume."

View File

@ -43,6 +43,7 @@ class MockHeos(Heos):
self.player_play_previous: AsyncMock = AsyncMock()
self.player_play_queue: AsyncMock = AsyncMock()
self.player_play_quick_select: AsyncMock = AsyncMock()
self.player_remove_from_queue: AsyncMock = AsyncMock()
self.player_set_mute: AsyncMock = AsyncMock()
self.player_set_play_mode: AsyncMock = AsyncMock()
self.player_set_play_state: AsyncMock = AsyncMock()

View File

@ -27,11 +27,13 @@ from syrupy.assertion import SnapshotAssertion
from syrupy.filters import props
from homeassistant.components.heos.const import (
ATTR_QUEUE_IDS,
DOMAIN,
SERVICE_GET_QUEUE,
SERVICE_GROUP_VOLUME_DOWN,
SERVICE_GROUP_VOLUME_SET,
SERVICE_GROUP_VOLUME_UP,
SERVICE_REMOVE_FROM_QUEUE,
)
from homeassistant.components.media_player import (
ATTR_GROUP_MEMBERS,
@ -1767,3 +1769,18 @@ async def test_get_queue(
)
controller.player_get_queue.assert_called_once_with(1, None, None)
assert response == snapshot
async def test_remove_from_queue(
hass: HomeAssistant, config_entry: MockConfigEntry, controller: MockHeos
) -> None:
"""Test the get queue service."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.services.async_call(
DOMAIN,
SERVICE_REMOVE_FROM_QUEUE,
{ATTR_ENTITY_ID: "media_player.test_player", ATTR_QUEUE_IDS: [1, "2"]},
blocking=True,
)
controller.player_remove_from_queue.assert_called_once_with(1, [1, 2])