Add unique_id to MPD (#120495)

This commit is contained in:
Joost Lekkerkerker
2024-06-26 09:28:11 +02:00
committed by GitHub
parent bff9d12cc0
commit 5a0841155e

View File

@@ -31,6 +31,7 @@ from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_PORT
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
@@ -129,7 +130,7 @@ async def async_setup_entry(
entry.data[CONF_HOST],
entry.data[CONF_PORT],
entry.data.get(CONF_PASSWORD),
entry.title,
entry.entry_id,
)
],
True,
@@ -140,23 +141,26 @@ class MpdDevice(MediaPlayerEntity):
"""Representation of a MPD server."""
_attr_media_content_type = MediaType.MUSIC
_attr_has_entity_name = True
_attr_name = None
def __init__(self, server, port, password, name):
def __init__(
self, server: str, port: int, password: str | None, unique_id: str
) -> None:
"""Initialize the MPD device."""
self.server = server
self.port = port
self._name = name
self._attr_unique_id = unique_id
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)},
entry_type=DeviceEntryType.SERVICE,
)
self.password = password
self._status = {}
self._status: dict[str, Any] = {}
self._currentsong = None
self._playlists = None
self._currentplaylist = None
self._is_available = None
self._muted = False
self._current_playlist: str | None = None
self._muted_volume = None
self._media_position_updated_at = None
self._media_position = None
self._media_image_hash = None
# Track if the song changed so image doesn't have to be loaded every update.
self._media_image_file = None
@@ -188,7 +192,7 @@ class MpdDevice(MediaPlayerEntity):
raise TimeoutError("Connection attempt timed out") from error
if self.password is not None:
await self._client.password(self.password)
self._is_available = True
self._attr_available = True
yield
except (
TimeoutError,
@@ -199,12 +203,12 @@ class MpdDevice(MediaPlayerEntity):
# Log a warning during startup or when previously connected; for
# subsequent errors a debug message is sufficient.
log_level = logging.DEBUG
if self._is_available is not False:
if self._attr_available is not False:
log_level = logging.WARNING
LOGGER.log(
log_level, "Error connecting to '%s': %s", self.server, error
)
self._is_available = False
self._attr_available = False
self._status = {}
# Also yield on failure. Handling mpd.ConnectionErrors caused by
# attempting to control a disconnected client is the
@@ -228,24 +232,14 @@ class MpdDevice(MediaPlayerEntity):
if isinstance(position, str) and ":" in position:
position = position.split(":")[0]
if position is not None and self._media_position != position:
self._media_position_updated_at = dt_util.utcnow()
self._media_position = int(float(position))
if position is not None and self._attr_media_position != position:
self._attr_media_position_updated_at = dt_util.utcnow()
self._attr_media_position = int(float(position))
await self._update_playlists()
except (mpd.ConnectionError, ValueError) as error:
LOGGER.debug("Error updating status: %s", error)
@property
def available(self) -> bool:
"""Return true if MPD is available and connected."""
return self._is_available is True
@property
def name(self):
"""Return the name of the device."""
return self._name
@property
def state(self) -> MediaPlayerState:
"""Return the media state."""
@@ -260,11 +254,6 @@ class MpdDevice(MediaPlayerEntity):
return MediaPlayerState.OFF
@property
def is_volume_muted(self):
"""Boolean if volume is currently muted."""
return self._muted
@property
def media_content_id(self):
"""Return the content ID of current playing media."""
@@ -282,20 +271,6 @@ class MpdDevice(MediaPlayerEntity):
return None
@property
def media_position(self):
"""Position of current playing media in seconds.
This is returned as part of the mpd status rather than in the details
of the current song.
"""
return self._media_position
@property
def media_position_updated_at(self):
"""Last valid time of media position."""
return self._media_position_updated_at
@property
def media_title(self):
"""Return the title of current playing media."""
@@ -436,7 +411,7 @@ class MpdDevice(MediaPlayerEntity):
| MediaPlayerEntityFeature.VOLUME_STEP
| MediaPlayerEntityFeature.VOLUME_MUTE
)
if self._playlists is not None:
if self._attr_source_list is not None:
supported |= MediaPlayerEntityFeature.SELECT_SOURCE
return supported
@@ -444,7 +419,7 @@ class MpdDevice(MediaPlayerEntity):
@property
def source(self):
"""Name of the current input source."""
return self._currentplaylist
return self._current_playlist
@property
def source_list(self):
@@ -459,12 +434,12 @@ class MpdDevice(MediaPlayerEntity):
async def _update_playlists(self, **kwargs: Any) -> None:
"""Update available MPD playlists."""
try:
self._playlists = []
self._attr_source_list = []
with suppress(mpd.ConnectionError):
for playlist_data in await self._client.listplaylists():
self._playlists.append(playlist_data["playlist"])
self._attr_source_list.append(playlist_data["playlist"])
except mpd.CommandError as error:
self._playlists = None
self._attr_source_list = None
LOGGER.warning("Playlists could not be updated: %s:", error)
async def async_set_volume_level(self, volume: float) -> None:
@@ -527,7 +502,7 @@ class MpdDevice(MediaPlayerEntity):
await self.async_set_volume_level(0)
elif self._muted_volume is not None:
await self.async_set_volume_level(self._muted_volume)
self._muted = mute
self._attr_is_volume_muted = mute
async def async_play_media(
self, media_type: MediaType | str, media_id: str, **kwargs: Any
@@ -543,17 +518,17 @@ class MpdDevice(MediaPlayerEntity):
if media_type == MediaType.PLAYLIST:
LOGGER.debug("Playing playlist: %s", media_id)
if media_id in self._playlists:
self._currentplaylist = media_id
if self._attr_source_list and media_id in self._attr_source_list:
self._current_playlist = media_id
else:
self._currentplaylist = None
self._current_playlist = None
LOGGER.warning("Unknown playlist name %s", media_id)
await self._client.clear()
await self._client.load(media_id)
await self._client.play()
else:
await self._client.clear()
self._currentplaylist = None
self._current_playlist = None
await self._client.add(media_id)
await self._client.play()