Ignore Sonos Boost devices during discovery v2 (#53358)

This commit is contained in:
jjlawren 2021-07-27 09:50:46 -05:00 committed by GitHub
parent 268ade6b76
commit 214920f486
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 22 deletions

View File

@ -12,7 +12,7 @@ from urllib.parse import urlparse
from soco import events_asyncio
import soco.config as soco_config
from soco.core import SoCo
from soco.exceptions import SoCoException
from soco.exceptions import NotSupportedException, SoCoException
import voluptuous as vol
from homeassistant import config_entries
@ -87,6 +87,7 @@ class SonosData:
self.alarms: dict[str, SonosAlarms] = {}
self.topology_condition = asyncio.Condition()
self.hosts_heartbeat = None
self.discovery_ignored: set[str] = set()
self.discovery_known: set[str] = set()
self.boot_counts: dict[str, int] = {}
@ -137,21 +138,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True
def _create_soco(ip_address: str, source: SoCoCreationSource) -> SoCo | None:
"""Create a soco instance and return if successful."""
try:
soco = SoCo(ip_address)
# Ensure that the player is available and UID is cached
_ = soco.uid
_ = soco.volume
return soco
except (OSError, SoCoException) as ex:
_LOGGER.warning(
"Failed to connect to %s player '%s': %s", source.value, ip_address, ex
)
return None
class SonosDiscoveryManager:
"""Manage sonos discovery."""
@ -165,6 +151,26 @@ class SonosDiscoveryManager:
self.hosts = hosts
self.discovery_lock = asyncio.Lock()
def _create_soco(self, ip_address: str, source: SoCoCreationSource) -> SoCo | None:
"""Create a soco instance and return if successful."""
if ip_address in self.data.discovery_ignored:
return None
try:
soco = SoCo(ip_address)
# Ensure that the player is available and UID is cached
uid = soco.uid
_ = soco.volume
return soco
except NotSupportedException as exc:
_LOGGER.debug("Device %s is not supported, ignoring: %s", uid, exc)
self.data.discovery_ignored.add(ip_address)
except (OSError, SoCoException) as ex:
_LOGGER.warning(
"Failed to connect to %s player '%s': %s", source.value, ip_address, ex
)
return None
async def _async_stop_event_listener(self, event: Event) -> None:
await asyncio.gather(
*(speaker.async_unsubscribe() for speaker in self.data.discovered.values()),
@ -213,7 +219,7 @@ class SonosDiscoveryManager:
if known_uid:
dispatcher_send(self.hass, f"{SONOS_SEEN}-{known_uid}")
else:
soco = _create_soco(ip_addr, SoCoCreationSource.CONFIGURED)
soco = self._create_soco(ip_addr, SoCoCreationSource.CONFIGURED)
if soco and soco.is_visible:
self._discovered_player(soco)
@ -222,7 +228,7 @@ class SonosDiscoveryManager:
)
def _discovered_ip(self, ip_address):
soco = _create_soco(ip_address, SoCoCreationSource.DISCOVERED)
soco = self._create_soco(ip_address, SoCoCreationSource.DISCOVERED)
if soco and soco.is_visible:
self._discovered_player(soco)
@ -238,7 +244,7 @@ class SonosDiscoveryManager:
if boot_seqnum and boot_seqnum > self.data.boot_counts[uid]:
self.data.boot_counts[uid] = boot_seqnum
if soco := await self.hass.async_add_executor_job(
_create_soco, discovered_ip, SoCoCreationSource.REBOOTED
self._create_soco, discovered_ip, SoCoCreationSource.REBOOTED
):
async_dispatcher_send(self.hass, f"{SONOS_REBOOTED}-{uid}", soco)
else:

View File

@ -3,7 +3,7 @@
"name": "Sonos",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/sonos",
"requirements": ["soco==0.23.1"],
"requirements": ["soco==0.23.2"],
"dependencies": ["ssdp"],
"after_dependencies": ["plex", "zeroconf"],
"zeroconf": ["_sonos._tcp.local."],

View File

@ -2148,7 +2148,7 @@ smhi-pkg==1.0.15
snapcast==2.1.3
# homeassistant.components.sonos
soco==0.23.1
soco==0.23.2
# homeassistant.components.solaredge_local
solaredge-local==0.2.0

View File

@ -1177,7 +1177,7 @@ smarthab==0.21
smhi-pkg==1.0.15
# homeassistant.components.sonos
soco==0.23.1
soco==0.23.2
# homeassistant.components.solaredge
solaredge==0.0.2

View File

@ -1,5 +1,8 @@
"""Tests for the Sonos Media Player platform."""
from unittest.mock import PropertyMock
import pytest
from soco.exceptions import NotSupportedException
from homeassistant.components.sonos import DATA_SONOS, DOMAIN, media_player
from homeassistant.const import STATE_IDLE
@ -40,6 +43,16 @@ async def test_async_setup_entry_discover(hass, config_entry, discover):
assert media_player.state == STATE_IDLE
async def test_discovery_ignore_unsupported_device(hass, config_entry, soco, caplog):
"""Test discovery setup."""
message = f"GetVolume not supported on {soco.ip_address}"
type(soco).volume = PropertyMock(side_effect=NotSupportedException(message))
await setup_platform(hass, config_entry, {})
assert message in caplog.text
assert not hass.data[DATA_SONOS].discovered
async def test_services(hass, config_entry, config, hass_read_only_user):
"""Test join/unjoin requires control access."""
await setup_platform(hass, config_entry, config)