Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bluesound speaker group attribute #28142

Merged
47 changes: 44 additions & 3 deletions homeassistant/components/bluesound/media_player.py
Expand Up @@ -53,6 +53,7 @@

_LOGGER = logging.getLogger(__name__)

ATTR_BLUESOUND_GROUP = "bluesound_group"
ATTR_MASTER = "master"

DATA_BLUESOUND = "bluesound"
Expand Down Expand Up @@ -219,6 +220,8 @@ def __init__(self, hass, host, port=None, name=None, init_callback=None):
self._master = None
self._is_master = False
self._group_name = None
self._group_list = []
self._bluesound_device_name = None

self._init_callback = init_callback
if self.port is None:
Expand Down Expand Up @@ -247,6 +250,8 @@ async def force_update_sync_status(self, on_updated_cb=None, raise_timeout=False

if not self._name:
self._name = self._sync_status.get("@name", self.host)
if not self._bluesound_device_name:
self._bluesound_device_name = self._sync_status.get("@name", self.host)
if not self._icon:
self._icon = self._sync_status.get("@icon", self.host)

Expand Down Expand Up @@ -331,7 +336,6 @@ async def send_bluesound_command(
self, method, raise_timeout=False, allow_offline=False
):
"""Send command to the player."""

if not self._is_online and not allow_offline:
return

Expand Down Expand Up @@ -371,7 +375,6 @@ async def send_bluesound_command(

async def async_update_status(self):
"""Use the poll session to always get the status of the player."""

response = None

url = "Status"
Expand Down Expand Up @@ -402,6 +405,10 @@ async def async_update_status(self):
if group_name != self._group_name:
_LOGGER.debug("Group name change detected on device: %s", self.host)
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()

# the sleep is needed to make sure that the
# devices is synced
await asyncio.sleep(1)
Expand Down Expand Up @@ -659,6 +666,11 @@ def name(self):
"""Return the name of the device."""
return self._name

@property
def bluesound_device_name(self):
"""Return the device name as returned by the device."""
return self._bluesound_device_name

@property
def icon(self):
"""Return the icon of the device."""
Expand Down Expand Up @@ -690,7 +702,6 @@ def source_list(self):
@property
def source(self):
"""Name of the current input source."""

if self._status is None or (self.is_grouped and not self.is_master):
return None

Expand Down Expand Up @@ -831,6 +842,36 @@ async def async_join(self, master):
else:
_LOGGER.error("Master not found %s", master_device)

@property
def device_state_attributes(self):
"""List members in group."""
attributes = {}
if self._group_list:
attributes = {ATTR_BLUESOUND_GROUP: self._group_list}

attributes[ATTR_MASTER] = self._is_master

return attributes

def rebuild_bluesound_group(self):
"""Rebuild the list of entities in speaker group."""
bluesound_group = []

device_group = self._group_name.split("+")
MartinHjelmare marked this conversation as resolved.
Show resolved Hide resolved

sorted_entities = sorted(
self._hass.data[DATA_BLUESOUND],
key=lambda entity: entity.is_master,
reverse=True,
)
bluesound_group = [
entity.name
for entity in sorted_entities
if entity.bluesound_device_name in device_group
]

return bluesound_group

async def async_unjoin(self):
"""Unjoin the player from a group."""
if self._master is None:
Expand Down