)
return queue_tracks
- def _check_clear_queue(self, queue: PlayerQueue) -> None:
+ async def _check_clear_queue(self, queue: PlayerQueue) -> None:
"""Check if the queue should be cleared after the current item."""
- if queue.state != PlayerState.IDLE:
- return
- if queue.next_item is not None:
- return
- if queue.current_index >= len(self._queue_items[queue.queue_id]) - 1:
- self.logger.info("End of queue reached, clearing items")
- self.clear(queue.queue_id)
+ for _ in range(5):
+ await asyncio.sleep(1)
+ if queue.state != PlayerState.IDLE:
+ return
+ if queue.next_item is not None:
+ return
+ if not (queue.current_index >= len(self._queue_items[queue.queue_id]) - 1):
+ return
+ self.logger.info("End of queue reached, clearing items")
+ self.clear(queue.queue_id)
def _get_flow_queue_stream_index(
self, queue: PlayerQueue, player: Player
from typing import TYPE_CHECKING
import shortuuid
+from aiohttp.client_exceptions import ClientConnectorError
from aiosonos.api.models import ContainerType, MusicService, SonosCapability
from aiosonos.api.models import PlayBackState as SonosPlayBackState
from aiosonos.client import SonosLocalApiClient
async def setup(self) -> None:
"""Handle setup of the player."""
# connect the player first so we can fail early
- await self._connect()
+ await self._connect(False)
# collect supported features
supported_features = set(PLAYER_FEATURES_BASE)
"""Reconnect the player."""
# use a task_id to prevent multiple reconnects
task_id = f"sonos_reconnect_{self.player_id}"
- self.mass.call_later(delay, self._connect, task_id=task_id)
+ self.mass.call_later(delay, self._connect, delay, task_id=task_id)
async def cmd_stop(self) -> None:
"""Send STOP command to given player."""
self.mass_player.current_media = current_media
- async def _connect(self) -> None:
+ async def _connect(self, retry_on_fail: int = 0) -> None:
"""Connect to the Sonos player."""
if self._listen_task and not self._listen_task.done():
self.logger.debug("Already connected to Sonos player: %s", self.player_id)
return
- await self.client.connect()
+ try:
+ await self.client.connect()
+ except (ConnectionFailed, ClientConnectorError) as err:
+ self.logger.warning("Failed to connect to Sonos player: %s", err)
+ self.mass_player.available = False
+ self.mass.players.update(self.player_id)
+ if not retry_on_fail:
+ raise
+ self.reconnect(min(retry_on_fail + 30), 3600)
+ return
self.connected = True
self.logger.debug("Connected to player API")
init_ready = asyncio.Event()
sonos_player.reconnect()
self.mass.players.update(player_id)
return
- # handle new player
- await self._setup_player(player_id, name, info)
+ # handle new player setup in a delayed task because mdns announcements
+ # can arrive in (duplicated) bursts
+ task_id = f"setup_sonos_{player_id}"
+ self.mass.call_later(5, self._setup_player(player_id, name, info), task_id=task_id)
async def get_player_config_entries(
self,