Initial implementation of ESPHome media players (#72047)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com> Co-authored-by: Franck Nijhof <git@frenck.dev>pull/70938/head^2
parent
f4b252a51d
commit
8ff0ced846
homeassistant/components/esphome
|
@ -314,6 +314,7 @@ omit =
|
|||
homeassistant/components/esphome/fan.py
|
||||
homeassistant/components/esphome/light.py
|
||||
homeassistant/components/esphome/lock.py
|
||||
homeassistant/components/esphome/media_player.py
|
||||
homeassistant/components/esphome/number.py
|
||||
homeassistant/components/esphome/select.py
|
||||
homeassistant/components/esphome/sensor.py
|
||||
|
|
|
@ -20,6 +20,7 @@ from aioesphomeapi import (
|
|||
FanInfo,
|
||||
LightInfo,
|
||||
LockInfo,
|
||||
MediaPlayerInfo,
|
||||
NumberInfo,
|
||||
SelectInfo,
|
||||
SensorInfo,
|
||||
|
@ -46,6 +47,7 @@ INFO_TYPE_TO_PLATFORM: dict[type[EntityInfo], str] = {
|
|||
FanInfo: "fan",
|
||||
LightInfo: "light",
|
||||
LockInfo: "lock",
|
||||
MediaPlayerInfo: "media_player",
|
||||
NumberInfo: "number",
|
||||
SelectInfo: "select",
|
||||
SensorInfo: "sensor",
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
"""Support for ESPHome media players."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from aioesphomeapi import (
|
||||
MediaPlayerCommand,
|
||||
MediaPlayerEntityState,
|
||||
MediaPlayerInfo,
|
||||
MediaPlayerState,
|
||||
)
|
||||
|
||||
from homeassistant.components import media_source
|
||||
from homeassistant.components.media_player import (
|
||||
MediaPlayerDeviceClass,
|
||||
MediaPlayerEntity,
|
||||
)
|
||||
from homeassistant.components.media_player.browse_media import (
|
||||
BrowseMedia,
|
||||
async_process_play_media_url,
|
||||
)
|
||||
from homeassistant.components.media_player.const import MediaPlayerEntityFeature
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import STATE_IDLE, STATE_PAUSED, STATE_PLAYING
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import EsphomeEntity, EsphomeEnumMapper, platform_async_setup_entry
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up esphome media players based on a config entry."""
|
||||
await platform_async_setup_entry(
|
||||
hass,
|
||||
entry,
|
||||
async_add_entities,
|
||||
component_key="media_player",
|
||||
info_type=MediaPlayerInfo,
|
||||
entity_type=EsphomeMediaPlayer,
|
||||
state_type=MediaPlayerEntityState,
|
||||
)
|
||||
|
||||
|
||||
_STATES: EsphomeEnumMapper[MediaPlayerState, str] = EsphomeEnumMapper(
|
||||
{
|
||||
MediaPlayerState.IDLE: STATE_IDLE,
|
||||
MediaPlayerState.PLAYING: STATE_PLAYING,
|
||||
MediaPlayerState.PAUSED: STATE_PAUSED,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class EsphomeMediaPlayer(
|
||||
EsphomeEntity[MediaPlayerInfo, MediaPlayerEntityState], MediaPlayerEntity
|
||||
):
|
||||
"""A media player implementation for esphome."""
|
||||
|
||||
_attr_device_class = MediaPlayerDeviceClass.SPEAKER
|
||||
|
||||
@property
|
||||
def state(self) -> str | None:
|
||||
"""Return current state."""
|
||||
return _STATES.from_esphome(self._state.state)
|
||||
|
||||
@property
|
||||
def is_volume_muted(self) -> bool:
|
||||
"""Return true if volume is muted."""
|
||||
return self._state.muted
|
||||
|
||||
@property
|
||||
def volume_level(self) -> float | None:
|
||||
"""Volume level of the media player (0..1)."""
|
||||
return self._state.volume
|
||||
|
||||
@property
|
||||
def supported_features(self) -> int:
|
||||
"""Flag supported features."""
|
||||
flags = (
|
||||
MediaPlayerEntityFeature.PLAY_MEDIA
|
||||
| MediaPlayerEntityFeature.BROWSE_MEDIA
|
||||
| MediaPlayerEntityFeature.STOP
|
||||
| MediaPlayerEntityFeature.VOLUME_SET
|
||||
| MediaPlayerEntityFeature.VOLUME_MUTE
|
||||
)
|
||||
if self._static_info.supports_pause:
|
||||
flags |= MediaPlayerEntityFeature.PAUSE | MediaPlayerEntityFeature.PLAY
|
||||
return flags
|
||||
|
||||
async def async_play_media(
|
||||
self, media_type: str, media_id: str, **kwargs: Any
|
||||
) -> None:
|
||||
"""Send the play command with media url to the media player."""
|
||||
if media_source.is_media_source_id(media_id):
|
||||
sourced_media = await media_source.async_resolve_media(self.hass, media_id)
|
||||
media_id = sourced_media.url
|
||||
|
||||
media_id = async_process_play_media_url(self.hass, media_id)
|
||||
|
||||
await self._client.media_player_command(
|
||||
self._static_info.key,
|
||||
media_url=media_id,
|
||||
)
|
||||
|
||||
async def async_browse_media(
|
||||
self, media_content_type: str | None = None, media_content_id: str | None = None
|
||||
) -> BrowseMedia:
|
||||
"""Implement the websocket media browsing helper."""
|
||||
return await media_source.async_browse_media(
|
||||
self.hass,
|
||||
media_content_id,
|
||||
content_filter=lambda item: item.media_content_type.startswith("audio/"),
|
||||
)
|
||||
|
||||
async def async_set_volume_level(self, volume: float) -> None:
|
||||
"""Set volume level, range 0..1."""
|
||||
await self._client.media_player_command(
|
||||
self._static_info.key,
|
||||
volume=volume,
|
||||
)
|
||||
|
||||
async def async_media_pause(self) -> None:
|
||||
"""Send pause command."""
|
||||
await self._client.media_player_command(
|
||||
self._static_info.key,
|
||||
command=MediaPlayerCommand.PAUSE,
|
||||
)
|
||||
|
||||
async def async_media_play(self) -> None:
|
||||
"""Send play command."""
|
||||
await self._client.media_player_command(
|
||||
self._static_info.key,
|
||||
command=MediaPlayerCommand.PLAY,
|
||||
)
|
||||
|
||||
async def async_media_stop(self) -> None:
|
||||
"""Send stop command."""
|
||||
await self._client.media_player_command(
|
||||
self._static_info.key,
|
||||
command=MediaPlayerCommand.STOP,
|
||||
)
|
||||
|
||||
async def async_mute_volume(self, mute: bool) -> None:
|
||||
"""Mute the volume."""
|
||||
await self._client.media_player_command(
|
||||
self._static_info.key,
|
||||
command=MediaPlayerCommand.MUTE if mute else MediaPlayerCommand.UNMUTE,
|
||||
)
|
Loading…
Reference in New Issue