mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 19:57:07 +00:00
Use DataUpdateCoordinator for Spotify devices (#66314)
This commit is contained in:
parent
57624347e6
commit
acf2033734
@ -1,9 +1,12 @@
|
||||
"""The spotify integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
import aiohttp
|
||||
import requests
|
||||
from spotipy import Spotify, SpotifyException
|
||||
import voluptuous as vol
|
||||
|
||||
@ -22,10 +25,11 @@ from homeassistant.helpers.config_entry_oauth2_flow import (
|
||||
async_get_config_entry_implementation,
|
||||
)
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from . import config_flow
|
||||
from .browse_media import async_browse_media
|
||||
from .const import DOMAIN, SPOTIFY_SCOPES
|
||||
from .const import DOMAIN, LOGGER, SPOTIFY_SCOPES
|
||||
from .util import is_spotify_media_type, resolve_spotify_media_type
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
@ -57,6 +61,7 @@ class HomeAssistantSpotifyData:
|
||||
|
||||
client: Spotify
|
||||
current_user: dict[str, Any]
|
||||
devices: DataUpdateCoordinator
|
||||
session: OAuth2Session
|
||||
|
||||
|
||||
@ -101,10 +106,35 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
if not current_user:
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
async def _update_devices() -> list[dict[str, Any]]:
|
||||
try:
|
||||
devices: dict[str, Any] | None = await hass.async_add_executor_job(
|
||||
spotify.devices
|
||||
)
|
||||
except (requests.RequestException, SpotifyException) as err:
|
||||
raise UpdateFailed from err
|
||||
|
||||
if devices is None:
|
||||
return []
|
||||
|
||||
return devices.get("devices", [])
|
||||
|
||||
device_coordinator: DataUpdateCoordinator[
|
||||
list[dict[str, Any]]
|
||||
] = DataUpdateCoordinator(
|
||||
hass,
|
||||
LOGGER,
|
||||
name=f"{entry.title} Devices",
|
||||
update_interval=timedelta(minutes=5),
|
||||
update_method=_update_devices,
|
||||
)
|
||||
await device_coordinator.async_config_entry_first_refresh()
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN][entry.entry_id] = HomeAssistantSpotifyData(
|
||||
client=spotify,
|
||||
current_user=current_user,
|
||||
devices=device_coordinator,
|
||||
session=session,
|
||||
)
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
"""Define constants for the Spotify integration."""
|
||||
|
||||
import logging
|
||||
|
||||
from homeassistant.components.media_player.const import (
|
||||
MEDIA_TYPE_ALBUM,
|
||||
MEDIA_TYPE_ARTIST,
|
||||
@ -9,6 +12,8 @@ from homeassistant.components.media_player.const import (
|
||||
|
||||
DOMAIN = "spotify"
|
||||
|
||||
LOGGER = logging.getLogger(__package__)
|
||||
|
||||
SPOTIFY_SCOPES = [
|
||||
# Needed to be able to control playback
|
||||
"user-modify-playback-state",
|
||||
|
@ -33,7 +33,7 @@ from homeassistant.components.media_player.const import (
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_ID, STATE_IDLE, STATE_PAUSED, STATE_PLAYING
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
@ -147,7 +147,6 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
SPOTIFY_SCOPES
|
||||
)
|
||||
self._currently_playing: dict | None = {}
|
||||
self._devices: list[dict] | None = []
|
||||
self._playlist: dict | None = None
|
||||
|
||||
@property
|
||||
@ -258,9 +257,7 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
@property
|
||||
def source_list(self) -> list[str] | None:
|
||||
"""Return a list of source devices."""
|
||||
if not self._devices:
|
||||
return None
|
||||
return [device["name"] for device in self._devices]
|
||||
return [device["name"] for device in self.data.devices.data]
|
||||
|
||||
@property
|
||||
def shuffle(self) -> bool | None:
|
||||
@ -332,19 +329,16 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
if (
|
||||
self._currently_playing
|
||||
and not self._currently_playing.get("device")
|
||||
and self._devices
|
||||
and self.data.devices.data
|
||||
):
|
||||
kwargs["device_id"] = self._devices[0].get("id")
|
||||
kwargs["device_id"] = self.data.devices.data[0].get("id")
|
||||
|
||||
self.data.client.start_playback(**kwargs)
|
||||
|
||||
@spotify_exception_handler
|
||||
def select_source(self, source: str) -> None:
|
||||
"""Select playback device."""
|
||||
if not self._devices:
|
||||
return
|
||||
|
||||
for device in self._devices:
|
||||
for device in self.data.devices.data:
|
||||
if device["name"] == source:
|
||||
self.data.client.transfer_playback(
|
||||
device["id"], self.state == STATE_PLAYING
|
||||
@ -386,9 +380,6 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
if context["type"] == MEDIA_TYPE_PLAYLIST:
|
||||
self._playlist = self.data.client.playlist(current["context"]["uri"])
|
||||
|
||||
devices = self.data.client.devices() or {}
|
||||
self._devices = devices.get("devices", [])
|
||||
|
||||
async def async_browse_media(
|
||||
self, media_content_type: str | None = None, media_content_id: str | None = None
|
||||
) -> BrowseMedia:
|
||||
@ -408,3 +399,17 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
media_content_type,
|
||||
media_content_id,
|
||||
)
|
||||
|
||||
@callback
|
||||
def _handle_devices_update(self) -> None:
|
||||
"""Handle updated data from the coordinator."""
|
||||
if not self.enabled:
|
||||
return
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""When entity is added to hass."""
|
||||
await super().async_added_to_hass()
|
||||
self.async_on_remove(
|
||||
self.data.devices.async_add_listener(self._handle_devices_update)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user