mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 02:24:51 -05:00
Prevent Sonos from pinging disabled device (#176893)
This commit is contained in:
@@ -73,6 +73,12 @@ DISCOVERY_IGNORED_MODELS = ["Sonos Boost"]
|
||||
ZGS_SUBSCRIPTION_TIMEOUT = 2
|
||||
SHUTDOWN_TIMEOUT = 10
|
||||
|
||||
|
||||
def _get_soco_uid(soco: SoCo) -> str:
|
||||
"""Get SoCo uid as a typed helper for executor jobs."""
|
||||
return soco.uid
|
||||
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
@@ -531,9 +537,11 @@ class SonosDiscoveryManager:
|
||||
),
|
||||
None,
|
||||
)
|
||||
if not known_speaker:
|
||||
if known_speaker:
|
||||
uid = known_speaker.uid
|
||||
else:
|
||||
try:
|
||||
uid = await self.hass.async_add_executor_job(getattr, soco, "uid")
|
||||
uid = await self.hass.async_add_executor_job(_get_soco_uid, soco)
|
||||
except HTTPError as err:
|
||||
await self._process_http_connection_error(err, ip_addr)
|
||||
continue
|
||||
@@ -545,6 +553,14 @@ class SonosDiscoveryManager:
|
||||
) as ex:
|
||||
_LOGGER.warning("Could not get Sonos uid from %s: %s", ip_addr, ex)
|
||||
continue
|
||||
|
||||
if self.is_device_disabled(uid):
|
||||
_LOGGER.debug(
|
||||
"Skipping manual poll for disabled Sonos device: %s",
|
||||
uid,
|
||||
)
|
||||
continue
|
||||
if not known_speaker:
|
||||
try:
|
||||
await self._async_handle_discovery_message(
|
||||
uid,
|
||||
|
||||
@@ -8,6 +8,7 @@ import logging
|
||||
from typing import Any
|
||||
from unittest.mock import MagicMock, Mock, PropertyMock, patch
|
||||
|
||||
from freezegun import freeze_time
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
from requests import Response
|
||||
@@ -605,6 +606,67 @@ async def test_async_poll_manual_hosts_6(
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
|
||||
async def test_async_poll_manual_hosts_skips_ping_for_disabled_device(
|
||||
hass: HomeAssistant,
|
||||
soco_factory: SoCoMockFactory,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test disabled manual-host speakers are not pinged on heartbeat."""
|
||||
soco = soco_factory.cache_mock(MockSoCo(), "10.10.10.1", "Living Room")
|
||||
soco.renderingControl = Mock()
|
||||
soco.renderingControl.GetVolume = Mock()
|
||||
|
||||
await _setup_hass(hass)
|
||||
|
||||
assert "media_player.living_room" in entity_registry.entities
|
||||
|
||||
# Mark the speaker unavailable via ZGS event with VanishedDevices.
|
||||
async def fire_vanish_event():
|
||||
subscription = soco.zoneGroupTopology.subscribe.return_value
|
||||
sub_callback = await subscription.wait_for_callback_to_be_set()
|
||||
zgs_with_vanished = f"""<ZoneGroupState>
|
||||
<ZoneGroups>
|
||||
<ZoneGroup Coordinator="{soco.uid}" ID="{soco.uid}:1384750254">
|
||||
<ZoneGroupMember UUID="{soco.uid}" Location="http://192.168.4.2:1400/xml/device_description.xml" ZoneName="Living Room"/>
|
||||
</ZoneGroup>
|
||||
</ZoneGroups>
|
||||
<VanishedDevices>
|
||||
<ZoneGroupMember UUID="{soco.uid}" Reason="powered off" ZoneName="Living Room"/>
|
||||
</VanishedDevices>
|
||||
</ZoneGroupState>"""
|
||||
event = SonosMockEvent(
|
||||
soco, soco.zoneGroupTopology, {"ZoneGroupState": zgs_with_vanished}
|
||||
)
|
||||
sub_callback(event)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
await fire_vanish_event()
|
||||
|
||||
# Verify the speaker is marked unavailable.
|
||||
state = hass.states.get("media_player.living_room")
|
||||
assert state is not None
|
||||
assert state.state == "unavailable"
|
||||
|
||||
# Now disable the device.
|
||||
device = device_registry.async_get_device(identifiers={(sonos.DOMAIN, soco.uid)})
|
||||
assert device is not None
|
||||
device_registry.async_update_device(
|
||||
device.id,
|
||||
disabled_by=dr.DeviceEntryDisabler.USER,
|
||||
)
|
||||
|
||||
# SonosSpeaker.ping uses RenderingControl.GetVolume under the hood.
|
||||
soco.renderingControl.GetVolume.reset_mock()
|
||||
with freeze_time(dt_util.utcnow()) as freezer:
|
||||
freezer.tick(DISCOVERY_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
# The disabled speaker should not have been pinged.
|
||||
soco.renderingControl.GetVolume.assert_not_called()
|
||||
|
||||
|
||||
async def test_async_poll_manual_hosts_7(
|
||||
hass: HomeAssistant,
|
||||
soco_factory: SoCoMockFactory,
|
||||
|
||||
Reference in New Issue
Block a user