Sonos: better handling of offline players (#1829)
When a sonos player goes offline an endless stream of exceptions is raised. That happens because homeassistant keeps trying to refresh its status. This can happen even when a sonos player has gone offline **before** homeassistant is started. The sonos players take some time before realizing one of their mates is no longer online, leading to the same stream of exceptions inside of homeassistant. Three types of exceptions of can be raised: - `requests.packages.urllib3.exceptions.MaxRetryError` - `requests.packages.urllib3.exceptions.NewConnectionError` - `TimeoutError` It's not possible to handle all of them with a single `except` block because they are raised in a random order and after some delays. That means a 2nd or 3rd exception can take place while handling the 1st one. The only solution is to check whether a a player is actually reachable by attempting to connect to a service that must be running on it. Also all the players in a 'unknown' state should not be polled by homeassistant (despite of their brand). I'm going to upstream the `_is_reachable` method I added to the `sonos.py` file into `SoCo`. In the meantime we must ship this piece of code with homeassistant. Signed-off-by: Flavio Castelli <fcastelli@suse.com>
This commit is contained in:
parent
a482c4b2a1
commit
b5f1c1332a
1 changed files with 22 additions and 5 deletions
|
@ -6,6 +6,7 @@ https://home-assistant.io/components/media_player.sonos/
|
|||
"""
|
||||
import datetime
|
||||
import logging
|
||||
import socket
|
||||
|
||||
from homeassistant.components.media_player import (
|
||||
MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE,
|
||||
|
@ -13,7 +14,7 @@ from homeassistant.components.media_player import (
|
|||
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET,
|
||||
MediaPlayerDevice)
|
||||
from homeassistant.const import (
|
||||
STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN)
|
||||
STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_OFF)
|
||||
|
||||
REQUIREMENTS = ['SoCo==0.11.1']
|
||||
|
||||
|
@ -36,7 +37,6 @@ SUPPORT_SONOS = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE |\
|
|||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Sonos platform."""
|
||||
import soco
|
||||
import socket
|
||||
|
||||
if discovery_info:
|
||||
add_devices([SonosDevice(hass, soco.SoCo(discovery_info))])
|
||||
|
@ -138,9 +138,14 @@ class SonosDevice(MediaPlayerDevice):
|
|||
"""Retrieve latest state."""
|
||||
self._name = self._player.get_speaker_info()['zone_name'].replace(
|
||||
' (R)', '').replace(' (L)', '')
|
||||
self._status = self._player.get_current_transport_info().get(
|
||||
'current_transport_state')
|
||||
self._trackinfo = self._player.get_current_track_info()
|
||||
|
||||
if self.available:
|
||||
self._status = self._player.get_current_transport_info().get(
|
||||
'current_transport_state')
|
||||
self._trackinfo = self._player.get_current_track_info()
|
||||
else:
|
||||
self._status = STATE_OFF
|
||||
self._trackinfo = {}
|
||||
|
||||
@property
|
||||
def volume_level(self):
|
||||
|
@ -253,3 +258,15 @@ class SonosDevice(MediaPlayerDevice):
|
|||
def play_media(self, media_type, media_id):
|
||||
"""Send the play_media command to the media player."""
|
||||
self._player.play_uri(media_id)
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return True if player is reachable, False otherwise."""
|
||||
try:
|
||||
sock = socket.create_connection(
|
||||
address=(self._player.ip_address, 1443),
|
||||
timeout=3)
|
||||
sock.close()
|
||||
return True
|
||||
except socket.error:
|
||||
return False
|
||||
|
|
Loading…
Add table
Reference in a new issue