mirror of
https://github.com/home-assistant/core.git
synced 2025-07-08 22:07:10 +00:00
Improve handling of unavailable Sonos speakers (#23472)
This commit is contained in:
parent
b6a13262da
commit
5efe089699
@ -3,7 +3,7 @@
|
|||||||
"name": "Sonos",
|
"name": "Sonos",
|
||||||
"documentation": "https://www.home-assistant.io/components/sonos",
|
"documentation": "https://www.home-assistant.io/components/sonos",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pysonos==0.0.10"
|
"pysonos==0.0.11"
|
||||||
],
|
],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
|
@ -7,9 +7,12 @@ import socket
|
|||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
import async_timeout
|
import async_timeout
|
||||||
import requests
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import pysonos
|
||||||
|
import pysonos.snapshot
|
||||||
|
from pysonos.exceptions import SoCoUPnPException, SoCoException
|
||||||
|
|
||||||
from homeassistant.components.media_player import MediaPlayerDevice
|
from homeassistant.components.media_player import MediaPlayerDevice
|
||||||
from homeassistant.components.media_player.const import (
|
from homeassistant.components.media_player.const import (
|
||||||
ATTR_MEDIA_ENQUEUE, DOMAIN, MEDIA_TYPE_MUSIC, SUPPORT_CLEAR_PLAYLIST,
|
ATTR_MEDIA_ENQUEUE, DOMAIN, MEDIA_TYPE_MUSIC, SUPPORT_CLEAR_PLAYLIST,
|
||||||
@ -122,8 +125,6 @@ async def async_setup_platform(hass,
|
|||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up Sonos from a config entry."""
|
"""Set up Sonos from a config entry."""
|
||||||
import pysonos
|
|
||||||
|
|
||||||
if DATA_SONOS not in hass.data:
|
if DATA_SONOS not in hass.data:
|
||||||
hass.data[DATA_SONOS] = SonosData(hass)
|
hass.data[DATA_SONOS] = SonosData(hass)
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
for host in hosts:
|
for host in hosts:
|
||||||
try:
|
try:
|
||||||
players.append(pysonos.SoCo(socket.gethostbyname(host)))
|
players.append(pysonos.SoCo(socket.gethostbyname(host)))
|
||||||
except OSError:
|
except (OSError, SoCoException):
|
||||||
_LOGGER.warning("Failed to initialize '%s'", host)
|
_LOGGER.warning("Failed to initialize '%s'", host)
|
||||||
else:
|
else:
|
||||||
players = pysonos.discover(
|
players = pysonos.discover(
|
||||||
@ -260,8 +261,6 @@ def soco_error(errorcodes=None):
|
|||||||
@ft.wraps(funct)
|
@ft.wraps(funct)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
"""Wrap for all soco UPnP exception."""
|
"""Wrap for all soco UPnP exception."""
|
||||||
from pysonos.exceptions import SoCoUPnPException, SoCoException
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return funct(*args, **kwargs)
|
return funct(*args, **kwargs)
|
||||||
except SoCoUPnPException as err:
|
except SoCoUPnPException as err:
|
||||||
@ -472,7 +471,7 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
self._subscribe_to_player_events()
|
self._subscribe_to_player_events()
|
||||||
else:
|
else:
|
||||||
for subscription in self._subscriptions:
|
for subscription in self._subscriptions:
|
||||||
self.hass.async_add_executor_job(subscription.unsubscribe)
|
subscription.unsubscribe()
|
||||||
self._subscriptions = []
|
self._subscriptions = []
|
||||||
|
|
||||||
self._player_volume = None
|
self._player_volume = None
|
||||||
@ -488,10 +487,13 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
self._media_title = None
|
self._media_title = None
|
||||||
self._source_name = None
|
self._source_name = None
|
||||||
elif available and not self._receives_events:
|
elif available and not self._receives_events:
|
||||||
self.update_groups()
|
try:
|
||||||
self.update_volume()
|
self.update_groups()
|
||||||
if self.is_coordinator:
|
self.update_volume()
|
||||||
self.update_media()
|
if self.is_coordinator:
|
||||||
|
self.update_media()
|
||||||
|
except SoCoException:
|
||||||
|
pass
|
||||||
|
|
||||||
def update_media(self, event=None):
|
def update_media(self, event=None):
|
||||||
"""Update information about currently playing media."""
|
"""Update information about currently playing media."""
|
||||||
@ -574,7 +576,6 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
current_uri_metadata = media_info["CurrentURIMetaData"]
|
current_uri_metadata = media_info["CurrentURIMetaData"]
|
||||||
if current_uri_metadata not in ('', 'NOT_IMPLEMENTED', None):
|
if current_uri_metadata not in ('', 'NOT_IMPLEMENTED', None):
|
||||||
# currently soco does not have an API for this
|
# currently soco does not have an API for this
|
||||||
import pysonos
|
|
||||||
current_uri_metadata = pysonos.xml.XML.fromstring(
|
current_uri_metadata = pysonos.xml.XML.fromstring(
|
||||||
pysonos.utils.really_utf8(current_uri_metadata))
|
pysonos.utils.really_utf8(current_uri_metadata))
|
||||||
|
|
||||||
@ -678,7 +679,7 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
coordinator_uid = self.soco.group.coordinator.uid
|
coordinator_uid = self.soco.group.coordinator.uid
|
||||||
slave_uids = [p.uid for p in self.soco.group.members
|
slave_uids = [p.uid for p in self.soco.group.members
|
||||||
if p.uid != coordinator_uid]
|
if p.uid != coordinator_uid]
|
||||||
except requests.exceptions.RequestException:
|
except SoCoException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return [coordinator_uid] + slave_uids
|
return [coordinator_uid] + slave_uids
|
||||||
@ -933,7 +934,6 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
If ATTR_MEDIA_ENQUEUE is True, add `media_id` to the queue.
|
If ATTR_MEDIA_ENQUEUE is True, add `media_id` to the queue.
|
||||||
"""
|
"""
|
||||||
if kwargs.get(ATTR_MEDIA_ENQUEUE):
|
if kwargs.get(ATTR_MEDIA_ENQUEUE):
|
||||||
from pysonos.exceptions import SoCoUPnPException
|
|
||||||
try:
|
try:
|
||||||
self.soco.add_uri_to_queue(media_id)
|
self.soco.add_uri_to_queue(media_id)
|
||||||
except SoCoUPnPException:
|
except SoCoUPnPException:
|
||||||
@ -994,9 +994,7 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
@soco_error()
|
@soco_error()
|
||||||
def snapshot(self, with_group):
|
def snapshot(self, with_group):
|
||||||
"""Snapshot the state of a player."""
|
"""Snapshot the state of a player."""
|
||||||
from pysonos.snapshot import Snapshot
|
self._soco_snapshot = pysonos.snapshot.Snapshot(self.soco)
|
||||||
|
|
||||||
self._soco_snapshot = Snapshot(self.soco)
|
|
||||||
self._soco_snapshot.snapshot()
|
self._soco_snapshot.snapshot()
|
||||||
if with_group:
|
if with_group:
|
||||||
self._snapshot_group = self._sonos_group.copy()
|
self._snapshot_group = self._sonos_group.copy()
|
||||||
@ -1025,8 +1023,6 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
@soco_error()
|
@soco_error()
|
||||||
def restore(self):
|
def restore(self):
|
||||||
"""Restore a snapshotted state to a player."""
|
"""Restore a snapshotted state to a player."""
|
||||||
from pysonos.exceptions import SoCoException
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
self._soco_snapshot.restore()
|
self._soco_snapshot.restore()
|
||||||
|
@ -1288,7 +1288,7 @@ pysmartthings==0.6.7
|
|||||||
pysnmp==4.4.8
|
pysnmp==4.4.8
|
||||||
|
|
||||||
# homeassistant.components.sonos
|
# homeassistant.components.sonos
|
||||||
pysonos==0.0.10
|
pysonos==0.0.11
|
||||||
|
|
||||||
# homeassistant.components.spc
|
# homeassistant.components.spc
|
||||||
pyspcwebgw==0.4.0
|
pyspcwebgw==0.4.0
|
||||||
|
@ -258,7 +258,7 @@ pysmartapp==0.3.2
|
|||||||
pysmartthings==0.6.7
|
pysmartthings==0.6.7
|
||||||
|
|
||||||
# homeassistant.components.sonos
|
# homeassistant.components.sonos
|
||||||
pysonos==0.0.10
|
pysonos==0.0.11
|
||||||
|
|
||||||
# homeassistant.components.spc
|
# homeassistant.components.spc
|
||||||
pyspcwebgw==0.4.0
|
pyspcwebgw==0.4.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user