Cleanup regroup handling in Sonos (#53241)

Check event before creating coroutine
Remove unnecessary regrouping dispatcher
Update typing to reflect actual behavior
Add optimizations for polling mode
This commit is contained in:
jjlawren 2021-07-20 13:21:48 -05:00 committed by GitHub
parent 8c43e5c736
commit a2fbc4218d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 39 deletions

View file

@ -19,11 +19,7 @@ from homeassistant import config_entries
from homeassistant.components import ssdp
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_HOSTS,
EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP,
)
from homeassistant.const import CONF_HOSTS, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send, dispatcher_send
@ -35,7 +31,6 @@ from .const import (
DISCOVERY_INTERVAL,
DOMAIN,
PLATFORMS,
SONOS_GROUP_UPDATE,
SONOS_REBOOTED,
SONOS_SEEN,
UPNP_ST,
@ -226,10 +221,6 @@ class SonosDiscoveryManager:
DISCOVERY_INTERVAL.total_seconds(), self._manual_hosts
)
@callback
def _async_signal_update_groups(self, _event):
async_dispatcher_send(self.hass, SONOS_GROUP_UPDATE)
def _discovered_ip(self, ip_address):
soco = _create_soco(ip_address, SoCoCreationSource.DISCOVERED)
if soco and soco.is_visible:
@ -290,11 +281,6 @@ class SonosDiscoveryManager:
for platform in PLATFORMS
)
)
self.entry.async_on_unload(
self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, self._async_signal_update_groups
)
)
self.entry.async_on_unload(
self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_STOP, self._async_stop_event_listener

View file

@ -140,7 +140,6 @@ SONOS_CREATE_BATTERY = "sonos_create_battery"
SONOS_CREATE_MEDIA_PLAYER = "sonos_create_media_player"
SONOS_ENTITY_CREATED = "sonos_entity_created"
SONOS_POLL_UPDATE = "sonos_poll_update"
SONOS_GROUP_UPDATE = "sonos_group_update"
SONOS_ALARMS_UPDATED = "sonos_alarms_updated"
SONOS_FAVORITES_UPDATED = "sonos_favorites_updated"
SONOS_STATE_UPDATED = "sonos_state_updated"

View file

@ -46,7 +46,6 @@ from .const import (
SONOS_CREATE_BATTERY,
SONOS_CREATE_MEDIA_PLAYER,
SONOS_ENTITY_CREATED,
SONOS_GROUP_UPDATE,
SONOS_POLL_UPDATE,
SONOS_REBOOTED,
SONOS_SEEN,
@ -206,11 +205,6 @@ class SonosSpeaker:
f"{SONOS_ENTITY_CREATED}-{self.soco.uid}",
self.async_handle_new_entity,
)
self._group_dispatcher = dispatcher_connect(
self.hass,
SONOS_GROUP_UPDATE,
self.async_update_groups,
)
self._seen_dispatcher = dispatcher_connect(
self.hass, f"{SONOS_SEEN}-{self.soco.uid}", self.async_seen
)
@ -612,22 +606,18 @@ class SonosSpeaker:
#
# Group management
#
def update_groups(self, event: SonosEvent | None = None) -> None:
"""Handle callback for topology change event."""
coro = self.create_update_groups_coro(event)
if coro:
self.hass.add_job(coro) # type: ignore
def update_groups(self) -> None:
"""Update group topology when polling."""
self.hass.add_job(self.create_update_groups_coro())
@callback
def async_update_groups(self, event: SonosEvent | None = None) -> None:
def async_update_groups(self, event: SonosEvent) -> None:
"""Handle callback for topology change event."""
coro = self.create_update_groups_coro(event)
if coro:
self.hass.async_add_job(coro) # type: ignore
if not hasattr(event, "zone_player_uui_ds_in_group"):
return None
self.hass.async_add_job(self.create_update_groups_coro(event))
def create_update_groups_coro(
self, event: SonosEvent | None = None
) -> Coroutine | None:
def create_update_groups_coro(self, event: SonosEvent | None = None) -> Coroutine:
"""Handle callback for topology change event."""
def _get_soco_group() -> list[str]:
@ -646,7 +636,7 @@ class SonosSpeaker:
return [coordinator_uid] + slave_uids
async def _async_extract_group(event: SonosEvent) -> list[str]:
async def _async_extract_group(event: SonosEvent | None) -> list[str]:
"""Extract group layout from a topology event."""
group = event and event.zone_player_uui_ds_in_group
if group:
@ -658,6 +648,10 @@ class SonosSpeaker:
@callback
def _async_regroup(group: list[str]) -> None:
"""Rebuild internal group layout."""
if group == [self.soco.uid] and self.sonos_group == [self]:
# Skip updating existing single speakers in polling mode
return
entity_registry = ent_reg.async_get(self.hass)
sonos_group = []
sonos_group_entities = []
@ -671,6 +665,11 @@ class SonosSpeaker:
)
sonos_group_entities.append(entity_id)
if self.sonos_group_entities == sonos_group_entities:
# Useful in polling mode for speakers with stereo pairs or surrounds
# as those "invisible" speakers will bypass the single speaker check
return
self.coordinator = None
self.sonos_group = sonos_group
self.sonos_group_entities = sonos_group_entities
@ -684,7 +683,9 @@ class SonosSpeaker:
slave.sonos_group_entities = sonos_group_entities
slave.async_write_entity_states()
async def _async_handle_group_event(event: SonosEvent) -> None:
_LOGGER.debug("Regrouped %s: %s", self.zone_name, self.sonos_group_entities)
async def _async_handle_group_event(event: SonosEvent | None) -> None:
"""Get async lock and handle event."""
async with self.hass.data[DATA_SONOS].topology_condition:
@ -695,9 +696,6 @@ class SonosSpeaker:
self.hass.data[DATA_SONOS].topology_condition.notify_all()
if event and not hasattr(event, "zone_player_uui_ds_in_group"):
return None
return _async_handle_group_event(event)
@soco_error()