diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index c0f9133a3d0..70b7d911cca 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -66,6 +66,26 @@ def setup_platform(hass, config, add_devices, discovery_info=None): 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=abstract-method class SonosDevice(MediaPlayerDevice): @@ -107,6 +127,11 @@ class SonosDevice(MediaPlayerDevice): return STATE_IDLE return STATE_UNKNOWN + @property + def is_coordinator(self): + """ Returns true if player is a coordinator """ + return self._player.is_coordinator + def update(self): """ Retrieve latest state. """ self._name = self._player.get_speaker_info()['zone_name'].replace( @@ -170,46 +195,57 @@ class SonosDevice(MediaPlayerDevice): """ Flags of media commands that are supported. """ return SUPPORT_SONOS + @only_if_coordinator def turn_off(self): """ Turn off media player. """ self._player.pause() + @only_if_coordinator def volume_up(self): """ Volume up media player. """ self._player.volume += 1 + @only_if_coordinator def volume_down(self): """ Volume down media player. """ self._player.volume -= 1 + @only_if_coordinator def set_volume_level(self, volume): """ Set volume level, range 0..1. """ self._player.volume = str(int(volume * 100)) + @only_if_coordinator def mute_volume(self, mute): """ Mute (true) or unmute (false) media player. """ self._player.mute = mute + @only_if_coordinator def media_play(self): """ Send paly command. """ self._player.play() + @only_if_coordinator def media_pause(self): """ Send pause command. """ self._player.pause() + @only_if_coordinator def media_next_track(self): """ Send next track command. """ self._player.next() + @only_if_coordinator def media_previous_track(self): """ Send next track command. """ self._player.previous() + @only_if_coordinator def media_seek(self, position): """ Send seek command. """ self._player.seek(str(datetime.timedelta(seconds=int(position)))) + @only_if_coordinator def turn_on(self): """ Turn the media player on. """ self._player.play()