ADD only_if_coordinator decorator to sonos

Currently we interact with players regardless of thir coordinator
role, hence soco.exceptions.SoCoSlaveException are thrown. The use
of the decorator for each interactive method should address this
This commit is contained in:
Alexander Fortin 2016-02-26 20:05:34 +01:00
parent 2ec141b5d4
commit 124a9b7a81

View File

@ -66,6 +66,26 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
return True return True
def only_if_coordinator(func):
"""
If used as decorator, avoid calling the decorated method if
player is not a coordinator.
If not, a grouped speaker (not in coordinator role)
will throw soco.exceptions.SoCoSlaveException
"""
def wrapper(*args, **kwargs):
""" Decorator wrapper """
if args[0].is_coordinator:
return func(*args, **kwargs)
else:
_LOGGER.debug('Ignore command "%s" for Sonos device "%s" '
'(not coordinator)',
func.__name__, args[0].name)
return wrapper
# pylint: disable=too-many-instance-attributes, too-many-public-methods # pylint: disable=too-many-instance-attributes, too-many-public-methods
# pylint: disable=abstract-method # pylint: disable=abstract-method
class SonosDevice(MediaPlayerDevice): class SonosDevice(MediaPlayerDevice):
@ -107,6 +127,11 @@ class SonosDevice(MediaPlayerDevice):
return STATE_IDLE return STATE_IDLE
return STATE_UNKNOWN return STATE_UNKNOWN
@property
def is_coordinator(self):
""" Returns true if player is a coordinator """
return self._player.is_coordinator
def update(self): def update(self):
""" Retrieve latest state. """ """ Retrieve latest state. """
self._name = self._player.get_speaker_info()['zone_name'].replace( self._name = self._player.get_speaker_info()['zone_name'].replace(
@ -170,46 +195,57 @@ class SonosDevice(MediaPlayerDevice):
""" Flags of media commands that are supported. """ """ Flags of media commands that are supported. """
return SUPPORT_SONOS return SUPPORT_SONOS
@only_if_coordinator
def turn_off(self): def turn_off(self):
""" Turn off media player. """ """ Turn off media player. """
self._player.pause() self._player.pause()
@only_if_coordinator
def volume_up(self): def volume_up(self):
""" Volume up media player. """ """ Volume up media player. """
self._player.volume += 1 self._player.volume += 1
@only_if_coordinator
def volume_down(self): def volume_down(self):
""" Volume down media player. """ """ Volume down media player. """
self._player.volume -= 1 self._player.volume -= 1
@only_if_coordinator
def set_volume_level(self, volume): def set_volume_level(self, volume):
""" Set volume level, range 0..1. """ """ Set volume level, range 0..1. """
self._player.volume = str(int(volume * 100)) self._player.volume = str(int(volume * 100))
@only_if_coordinator
def mute_volume(self, mute): def mute_volume(self, mute):
""" Mute (true) or unmute (false) media player. """ """ Mute (true) or unmute (false) media player. """
self._player.mute = mute self._player.mute = mute
@only_if_coordinator
def media_play(self): def media_play(self):
""" Send paly command. """ """ Send paly command. """
self._player.play() self._player.play()
@only_if_coordinator
def media_pause(self): def media_pause(self):
""" Send pause command. """ """ Send pause command. """
self._player.pause() self._player.pause()
@only_if_coordinator
def media_next_track(self): def media_next_track(self):
""" Send next track command. """ """ Send next track command. """
self._player.next() self._player.next()
@only_if_coordinator
def media_previous_track(self): def media_previous_track(self):
""" Send next track command. """ """ Send next track command. """
self._player.previous() self._player.previous()
@only_if_coordinator
def media_seek(self, position): def media_seek(self, position):
""" Send seek command. """ """ Send seek command. """
self._player.seek(str(datetime.timedelta(seconds=int(position)))) self._player.seek(str(datetime.timedelta(seconds=int(position))))
@only_if_coordinator
def turn_on(self): def turn_on(self):
""" Turn the media player on. """ """ Turn the media player on. """
self._player.play() self._player.play()