Define media_player entity attributes as class variables (#51192)

This commit is contained in:
Franck Nijhof 2021-05-28 12:32:31 +02:00 committed by GitHub
parent 39e62f9c90
commit 17b2678aee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 106 deletions

View File

@ -31,7 +31,7 @@ from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from .const import ATTR_MANUFACTURER, DEFAULT_NAME, DOMAIN
@ -100,7 +100,7 @@ class DuneHDPlayerEntity(MediaPlayerEntity):
return True
@property
def state(self) -> StateType:
def state(self) -> str | None:
"""Return player state."""
state = STATE_OFF
if "playback_position" in self._state:

View File

@ -1,7 +1,6 @@
"""Denon HEOS Media Player."""
from __future__ import annotations
from collections.abc import Sequence
from functools import reduce, wraps
import logging
from operator import ior
@ -362,7 +361,7 @@ class HeosMediaPlayer(MediaPlayerEntity):
return self._source_manager.get_current_source(self._player.now_playing_media)
@property
def source_list(self) -> Sequence[str]:
def source_list(self) -> list[str]:
"""List of available input sources."""
return self._source_manager.source_list

View File

@ -5,7 +5,7 @@ import asyncio
import base64
import collections
from contextlib import suppress
from datetime import timedelta
import datetime as dt
import functools as ft
import hashlib
import logging
@ -57,6 +57,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
datetime,
)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
@ -137,7 +138,7 @@ CACHE_URL = "url"
CACHE_CONTENT = "content"
ENTITY_IMAGE_CACHE = {CACHE_IMAGES: collections.OrderedDict(), CACHE_MAXSIZE: 16}
SCAN_INTERVAL = timedelta(seconds=10)
SCAN_INTERVAL = dt.timedelta(seconds=10)
DEVICE_CLASS_TV = "tv"
DEVICE_CLASS_SPEAKER = "speaker"
@ -371,11 +372,43 @@ class MediaPlayerEntity(Entity):
_access_token: str | None = None
_attr_app_id: str | None = None
_attr_app_name: str | None = None
_attr_group_members: list[str] | None = None
_attr_is_volume_muted: bool | None = None
_attr_media_album_artist: str | None = None
_attr_media_album_name: str | None = None
_attr_media_artist: str | None = None
_attr_media_channel: str | None = None
_attr_media_content_id: str | None = None
_attr_media_content_type: str | None = None
_attr_media_duration: int | None = None
_attr_media_episode: str | None = None
_attr_media_image_hash: str | None
_attr_media_image_remotely_accessible: bool = False
_attr_media_image_url: str | None = None
_attr_media_playlist: str | None = None
_attr_media_position_updated_at: dt.datetime | None = None
_attr_media_position: int | None = None
_attr_media_season: str | None = None
_attr_media_series_title: str | None = None
_attr_media_title: str | None = None
_attr_media_track: int | None = None
_attr_repeat: str | None = None
_attr_shuffle: bool | None = None
_attr_sound_mode_list: list[str] | None = None
_attr_sound_mode: str | None = None
_attr_source_list: list[str] | None = None
_attr_source: str | None = None
_attr_state: str | None = None
_attr_supported_features: int = 0
_attr_volume_level: float | None = None
# Implement these for your media player
@property
def state(self):
def state(self) -> str | None:
"""State of the player."""
return None
return self._attr_state
@property
def access_token(self) -> str:
@ -385,56 +418,59 @@ class MediaPlayerEntity(Entity):
return self._access_token
@property
def volume_level(self):
def volume_level(self) -> float | None:
"""Volume level of the media player (0..1)."""
return None
return self._attr_volume_level
@property
def is_volume_muted(self):
def is_volume_muted(self) -> bool | None:
"""Boolean if volume is currently muted."""
return None
return self._attr_is_volume_muted
@property
def media_content_id(self):
def media_content_id(self) -> str | None:
"""Content ID of current playing media."""
return None
return self._attr_media_content_id
@property
def media_content_type(self):
def media_content_type(self) -> str | None:
"""Content type of current playing media."""
return None
return self._attr_media_content_type
@property
def media_duration(self):
def media_duration(self) -> int | None:
"""Duration of current playing media in seconds."""
return None
return self._attr_media_duration
@property
def media_position(self):
def media_position(self) -> int | None:
"""Position of current playing media in seconds."""
return None
return self._attr_media_position
@property
def media_position_updated_at(self):
def media_position_updated_at(self) -> dt.datetime | None:
"""When was the position of the current playing media valid.
Returns value from homeassistant.util.dt.utcnow().
"""
return None
return self._attr_media_position_updated_at
@property
def media_image_url(self):
def media_image_url(self) -> str | None:
"""Image url of current playing media."""
return None
return self._attr_media_image_url
@property
def media_image_remotely_accessible(self) -> bool:
"""If the image url is remotely accessible."""
return False
return self._attr_media_image_remotely_accessible
@property
def media_image_hash(self):
def media_image_hash(self) -> str | None:
"""Hash value for media image."""
if hasattr(self, "_attr_media_image_hash"):
return self._attr_media_image_hash
url = self.media_image_url
if url is not None:
return hashlib.sha256(url.encode("utf-8")).hexdigest()[:16]
@ -463,104 +499,104 @@ class MediaPlayerEntity(Entity):
return None, None
@property
def media_title(self):
def media_title(self) -> str | None:
"""Title of current playing media."""
return None
return self._attr_media_title
@property
def media_artist(self):
def media_artist(self) -> str | None:
"""Artist of current playing media, music track only."""
return None
return self._attr_media_artist
@property
def media_album_name(self):
def media_album_name(self) -> str | None:
"""Album name of current playing media, music track only."""
return None
return self._attr_media_album_name
@property
def media_album_artist(self):
def media_album_artist(self) -> str | None:
"""Album artist of current playing media, music track only."""
return None
return self._attr_media_album_artist
@property
def media_track(self):
def media_track(self) -> int | None:
"""Track number of current playing media, music track only."""
return None
return self._attr_media_track
@property
def media_series_title(self):
def media_series_title(self) -> str | None:
"""Title of series of current playing media, TV show only."""
return None
return self._attr_media_series_title
@property
def media_season(self):
def media_season(self) -> str | None:
"""Season of current playing media, TV show only."""
return None
return self._attr_media_season
@property
def media_episode(self):
def media_episode(self) -> str | None:
"""Episode of current playing media, TV show only."""
return None
return self._attr_media_episode
@property
def media_channel(self):
def media_channel(self) -> str | None:
"""Channel currently playing."""
return None
return self._attr_media_channel
@property
def media_playlist(self):
def media_playlist(self) -> str | None:
"""Title of Playlist currently playing."""
return None
return self._attr_media_playlist
@property
def app_id(self):
def app_id(self) -> str | None:
"""ID of the current running app."""
return None
return self._attr_app_id
@property
def app_name(self):
def app_name(self) -> str | None:
"""Name of the current running app."""
return None
return self._attr_app_name
@property
def source(self):
def source(self) -> str | None:
"""Name of the current input source."""
return None
return self._attr_source
@property
def source_list(self):
def source_list(self) -> list[str] | None:
"""List of available input sources."""
return None
return self._attr_source_list
@property
def sound_mode(self):
def sound_mode(self) -> str | None:
"""Name of the current sound mode."""
return None
return self._attr_sound_mode
@property
def sound_mode_list(self):
def sound_mode_list(self) -> list[str] | None:
"""List of available sound modes."""
return None
return self._attr_sound_mode_list
@property
def shuffle(self):
def shuffle(self) -> bool | None:
"""Boolean if shuffle is enabled."""
return None
return self._attr_shuffle
@property
def repeat(self):
def repeat(self) -> str | None:
"""Return current repeat mode."""
return None
return self._attr_repeat
@property
def group_members(self):
def group_members(self) -> list[str] | None:
"""List of members which are currently grouped together."""
return None
return self._attr_group_members
@property
def supported_features(self):
def supported_features(self) -> int:
"""Flag media player features that are supported."""
return 0
return self._attr_supported_features
def turn_on(self):
"""Turn the media player on."""

View File

@ -67,8 +67,6 @@ from .const import (
_LOGGER = logging.getLogger(__name__)
ICON = "mdi:spotify"
SCAN_INTERVAL = timedelta(seconds=30)
SUPPORT_SPOTIFY = (
@ -211,12 +209,12 @@ def spotify_exception_handler(func):
def wrapper(self, *args, **kwargs):
try:
result = func(self, *args, **kwargs)
self.player_available = True
self._attr_available = True
return result
except requests.RequestException:
self.player_available = False
self._attr_available = False
except SpotifyException as exc:
self.player_available = False
self._attr_available = False
if exc.reason == "NO_ACTIVE_DEVICE":
raise HomeAssistantError("No active playback device found") from None
@ -226,6 +224,10 @@ def spotify_exception_handler(func):
class SpotifyMediaPlayer(MediaPlayerEntity):
"""Representation of a Spotify controller."""
_attr_icon = "mdi:spotify"
_attr_media_content_type = MEDIA_TYPE_MUSIC
_attr_media_image_remotely_accessible = False
def __init__(
self,
session: OAuth2Session,
@ -247,40 +249,22 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
self._currently_playing: dict | None = {}
self._devices: list[dict] | None = []
self._playlist: dict | None = None
self._spotify: Spotify = None
self.player_available = False
@property
def name(self) -> str:
"""Return the name."""
return self._name
@property
def icon(self) -> str:
"""Return the icon."""
return ICON
@property
def available(self) -> bool:
"""Return True if entity is available."""
return self.player_available
@property
def unique_id(self) -> str:
"""Return the unique ID."""
return self._id
self._attr_name = self._name
self._attr_unique_id = user_id
@property
def device_info(self) -> DeviceInfo:
"""Return device information about this entity."""
model = "Spotify Free"
if self._me is not None:
model = self._me["product"]
product = self._me["product"]
model = f"Spotify {product}"
return {
"identifiers": {(DOMAIN, self._id)},
"manufacturer": "Spotify AB",
"model": f"Spotify {model}".rstrip(),
"model": model,
"name": self._name,
}
@ -304,11 +288,6 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
item = self._currently_playing.get("item") or {}
return item.get("uri")
@property
def media_content_type(self) -> str | None:
"""Return the media type."""
return MEDIA_TYPE_MUSIC
@property
def media_duration(self) -> int | None:
"""Duration of current playing media in seconds."""
@ -340,11 +319,6 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
return None
return fetch_image_url(self._currently_playing["item"]["album"])
@property
def media_image_remotely_accessible(self) -> bool:
"""If the image url is remotely accessible."""
return False
@property
def media_title(self) -> str | None:
"""Return the media title."""
@ -357,7 +331,7 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
if self._currently_playing.get("item") is None:
return None
return ", ".join(
[artist["name"] for artist in self._currently_playing["item"]["artists"]]
artist["name"] for artist in self._currently_playing["item"]["artists"]
)
@property