Fix bluesound_group attribute in bluesound integration (#130815)

Co-authored-by: Robert Resch <robert@resch.dev>
pull/131696/head
Louis Christ 2024-11-27 09:40:20 +01:00 committed by GitHub
parent 507bb4a685
commit 96eae1221c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 68 additions and 24 deletions

View File

@ -292,14 +292,6 @@ class BluesoundPlayer(MediaPlayerEntity):
self._last_status_update = dt_util.utcnow()
self._status = status
group_name = status.group_name
if group_name != self._group_name:
_LOGGER.debug("Group name change detected on device: %s", self.id)
self._group_name = group_name
# rebuild ordered list of entity_ids that are in the group, master is first
self._group_list = self.rebuild_bluesound_group()
self.async_write_ha_state()
except PlayerUnreachableError:
self._attr_available = False
@ -323,6 +315,8 @@ class BluesoundPlayer(MediaPlayerEntity):
self._sync_status = sync_status
self._group_list = self.rebuild_bluesound_group()
if sync_status.master is not None:
self._is_master = False
master_id = f"{sync_status.master.ip}:{sync_status.master.port}"
@ -619,21 +613,32 @@ class BluesoundPlayer(MediaPlayerEntity):
def rebuild_bluesound_group(self) -> list[str]:
"""Rebuild the list of entities in speaker group."""
if self._group_name is None:
if self.sync_status.master is None and self.sync_status.slaves is None:
return []
device_group = self._group_name.split("+")
player_entities: list[BluesoundPlayer] = self.hass.data[DATA_BLUESOUND]
sorted_entities: list[BluesoundPlayer] = sorted(
self.hass.data[DATA_BLUESOUND],
key=lambda entity: entity.is_master,
reverse=True,
)
return [
entity.sync_status.name
for entity in sorted_entities
if entity.bluesound_device_name in device_group
leader_sync_status: SyncStatus | None = None
if self.sync_status.master is None:
leader_sync_status = self.sync_status
else:
required_id = f"{self.sync_status.master.ip}:{self.sync_status.master.port}"
for x in player_entities:
if x.sync_status.id == required_id:
leader_sync_status = x.sync_status
break
if leader_sync_status is None or leader_sync_status.slaves is None:
return []
follower_ids = [f"{x.ip}:{x.port}" for x in leader_sync_status.slaves]
follower_names = [
x.sync_status.name
for x in player_entities
if x.sync_status.id in follower_ids
]
follower_names.insert(0, leader_sync_status.name)
return follower_names
async def async_unjoin(self) -> None:
"""Unjoin the player from a group."""

View File

@ -325,17 +325,17 @@ async def test_attr_bluesound_group(
setup_config_entry_secondary: None,
player_mocks: PlayerMocks,
) -> None:
"""Test the media player grouping."""
"""Test the media player grouping for leader."""
attr_bluesound_group = hass.states.get(
"media_player.player_name1111"
).attributes.get("bluesound_group")
assert attr_bluesound_group is None
updated_status = dataclasses.replace(
player_mocks.player_data.status_long_polling_mock.get(),
group_name="player-name1111+player-name2222",
updated_sync_status = dataclasses.replace(
player_mocks.player_data.sync_status_long_polling_mock.get(),
slaves=[PairedPlayer("2.2.2.2", 11000)],
)
player_mocks.player_data.status_long_polling_mock.set(updated_status)
player_mocks.player_data.sync_status_long_polling_mock.set(updated_sync_status)
# give the long polling loop a chance to update the state; this could be any async call
await hass.async_block_till_done()
@ -347,6 +347,45 @@ async def test_attr_bluesound_group(
assert attr_bluesound_group == ["player-name1111", "player-name2222"]
async def test_attr_bluesound_group_for_follower(
hass: HomeAssistant,
setup_config_entry: None,
setup_config_entry_secondary: None,
player_mocks: PlayerMocks,
) -> None:
"""Test the media player grouping for follower."""
attr_bluesound_group = hass.states.get(
"media_player.player_name2222"
).attributes.get("bluesound_group")
assert attr_bluesound_group is None
updated_sync_status = dataclasses.replace(
player_mocks.player_data.sync_status_long_polling_mock.get(),
slaves=[PairedPlayer("2.2.2.2", 11000)],
)
player_mocks.player_data.sync_status_long_polling_mock.set(updated_sync_status)
# give the long polling loop a chance to update the state; this could be any async call
await hass.async_block_till_done()
updated_sync_status = dataclasses.replace(
player_mocks.player_data_secondary.sync_status_long_polling_mock.get(),
master=PairedPlayer("1.1.1.1", 11000),
)
player_mocks.player_data_secondary.sync_status_long_polling_mock.set(
updated_sync_status
)
# give the long polling loop a chance to update the state; this could be any async call
await hass.async_block_till_done()
attr_bluesound_group = hass.states.get(
"media_player.player_name2222"
).attributes.get("bluesound_group")
assert attr_bluesound_group == ["player-name1111", "player-name2222"]
async def test_volume_up_from_6_to_7(
hass: HomeAssistant,
setup_config_entry: None,