From ad8645baf4d7f44aa5594dc82ccbbaef3ce0b300 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 6 Nov 2016 00:58:29 +0100 Subject: [PATCH] Sonos fix for slow update (#4232) * Sonos fix for slow update * fix auto update on discovery * fix unittest --- .../components/media_player/sonos.py | 29 ++++++++++--------- tests/components/media_player/test_sonos.py | 23 ++++++++++----- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index 39b9559aa59..89f5d7b07ed 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -80,7 +80,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if player.is_visible: device = SonosDevice(hass, player) - add_devices([device]) + add_devices([device], True) if not DEVICES: register_services(hass) DEVICES.append(device) @@ -106,7 +106,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): return False DEVICES = [SonosDevice(hass, p) for p in players] - add_devices(DEVICES) + add_devices(DEVICES, True) register_services(hass) _LOGGER.info('Added %s Sonos speakers', len(players)) return True @@ -256,6 +256,7 @@ class SonosDevice(MediaPlayerDevice): self.hass = hass self.volume_increment = 5 + self._unique_id = player.uid self._player = player self._player_volume = None self._player_volume_muted = None @@ -278,7 +279,8 @@ class SonosDevice(MediaPlayerDevice): self._current_track_is_radio_stream = False self._queue = None self._last_avtransport_event = None - self.update() + self._is_playing_line_in = None + self._is_playing_tv = None self.soco_snapshot = Snapshot(self._player) @property @@ -286,14 +288,10 @@ class SonosDevice(MediaPlayerDevice): """Polling needed.""" return True - def update_sonos(self, now): - """Update state, called by track_utc_time_change.""" - self.update_ha_state(True) - @property def unique_id(self): """Return an unique ID.""" - return self._player.uid + return self._unique_id @property def name(self): @@ -354,6 +352,9 @@ class SonosDevice(MediaPlayerDevice): if is_available: + self._is_playing_tv = self._player.is_playing_tv + self._is_playing_line_in = self._player.is_playing_line_in + track_info = None if self._last_avtransport_event: variables = self._last_avtransport_event.variables @@ -511,10 +512,10 @@ class SonosDevice(MediaPlayerDevice): # update state of the whole group # pylint: disable=protected-access for device in [x for x in DEVICES if x._coordinator == self]: - if device.entity_id: - device.update_ha_state(False) + if device.entity_id is not self.entity_id: + self.hass.add_job(device.async_update_ha_state) - if self._queue is None and self.entity_id: + if self._queue is None: self._subscribe_to_player_events() else: self._player_volume = None @@ -534,6 +535,8 @@ class SonosDevice(MediaPlayerDevice): self._support_previous_track = False self._support_next_track = False self._support_pause = False + self._is_playing_tv = False + self._is_playing_line_in = False self._last_avtransport_event = None @@ -713,9 +716,9 @@ class SonosDevice(MediaPlayerDevice): @property def source(self): """Name of the current input source.""" - if self._player.is_playing_line_in: + if self._is_playing_line_in: return SUPPORT_SOURCE_LINEIN - if self._player.is_playing_tv: + if self._is_playing_tv: return SUPPORT_SOURCE_TV return None diff --git a/tests/components/media_player/test_sonos.py b/tests/components/media_player/test_sonos.py index dfd308d5459..b170f14c372 100644 --- a/tests/components/media_player/test_sonos.py +++ b/tests/components/media_player/test_sonos.py @@ -92,6 +92,13 @@ class SoCoMock(): return "RINCON_XXXXXXXXXXXXXXXXX" +def fake_add_device(devices, update_befor_add=False): + """Fake add device / update.""" + if update_befor_add: + for speaker in devices: + speaker.update() + + class TestSonosMediaPlayer(unittest.TestCase): """Test the media_player module.""" @@ -117,7 +124,7 @@ class TestSonosMediaPlayer(unittest.TestCase): @mock.patch('socket.create_connection', side_effect=socket.error()) def test_ensure_setup_discovery(self, *args): """Test a single device using the autodiscovery provided by HASS.""" - sonos.setup_platform(self.hass, {}, mock.MagicMock(), '192.0.2.1') + sonos.setup_platform(self.hass, {}, fake_add_device, '192.0.2.1') # Ensure registration took place (#2558) self.assertEqual(len(sonos.DEVICES), 1) @@ -129,7 +136,7 @@ class TestSonosMediaPlayer(unittest.TestCase): """Test a single address config'd by the HASS config file.""" sonos.setup_platform(self.hass, {'hosts': '192.0.2.1'}, - mock.MagicMock()) + fake_add_device) # Ensure registration took place (#2558) self.assertEqual(len(sonos.DEVICES), 1) @@ -140,7 +147,7 @@ class TestSonosMediaPlayer(unittest.TestCase): @mock.patch('socket.create_connection', side_effect=socket.error()) def test_ensure_setup_sonos_discovery(self, *args): """Test a single device using the autodiscovery provided by Sonos.""" - sonos.setup_platform(self.hass, {}, mock.MagicMock()) + sonos.setup_platform(self.hass, {}, fake_add_device) self.assertEqual(len(sonos.DEVICES), 1) self.assertEqual(sonos.DEVICES[0].name, 'Kitchen') @@ -149,7 +156,7 @@ class TestSonosMediaPlayer(unittest.TestCase): @mock.patch.object(SoCoMock, 'partymode') def test_sonos_group_players(self, partymodeMock, *args): """Ensuring soco methods called for sonos_group_players service.""" - sonos.setup_platform(self.hass, {}, mock.MagicMock(), '192.0.2.1') + sonos.setup_platform(self.hass, {}, fake_add_device, '192.0.2.1') device = sonos.DEVICES[-1] partymodeMock.return_value = True device.group_players() @@ -161,7 +168,7 @@ class TestSonosMediaPlayer(unittest.TestCase): @mock.patch.object(SoCoMock, 'unjoin') def test_sonos_unjoin(self, unjoinMock, *args): """Ensuring soco methods called for sonos_unjoin service.""" - sonos.setup_platform(self.hass, {}, mock.MagicMock(), '192.0.2.1') + sonos.setup_platform(self.hass, {}, fake_add_device, '192.0.2.1') device = sonos.DEVICES[-1] unjoinMock.return_value = True device.unjoin() @@ -173,7 +180,7 @@ class TestSonosMediaPlayer(unittest.TestCase): @mock.patch.object(SoCoMock, 'set_sleep_timer') def test_sonos_set_sleep_timer(self, set_sleep_timerMock, *args): """Ensuring soco methods called for sonos_set_sleep_timer service.""" - sonos.setup_platform(self.hass, {}, mock.MagicMock(), '192.0.2.1') + sonos.setup_platform(self.hass, {}, fake_add_device, '192.0.2.1') device = sonos.DEVICES[-1] device.set_sleep_timer(30) set_sleep_timerMock.assert_called_once_with(30) @@ -193,7 +200,7 @@ class TestSonosMediaPlayer(unittest.TestCase): @mock.patch.object(soco.snapshot.Snapshot, 'snapshot') def test_sonos_snapshot(self, snapshotMock, *args): """Ensuring soco methods called for sonos_snapshot service.""" - sonos.setup_platform(self.hass, {}, mock.MagicMock(), '192.0.2.1') + sonos.setup_platform(self.hass, {}, fake_add_device, '192.0.2.1') device = sonos.DEVICES[-1] snapshotMock.return_value = True device.snapshot() @@ -205,7 +212,7 @@ class TestSonosMediaPlayer(unittest.TestCase): @mock.patch.object(soco.snapshot.Snapshot, 'restore') def test_sonos_restore(self, restoreMock, *args): """Ensuring soco methods called for sonos_restor service.""" - sonos.setup_platform(self.hass, {}, mock.MagicMock(), '192.0.2.1') + sonos.setup_platform(self.hass, {}, fake_add_device, '192.0.2.1') device = sonos.DEVICES[-1] restoreMock.return_value = True device.restore()