mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Add media_player support to SmartThings integration (#141296)
* Initial soundbar support * Soundbar support * Add SAMSUNG_VD_AUDIO_INPUT_SOURCE capability * Adjust setting input source * Add unit tests for media_player platform * Adjust code after merge * Adjust code after merge * Adjust code style * Adjust code style * Fix * Fix --------- Co-authored-by: Piotr Machowski <PiotrMachowski@users.noreply.github.com> Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
parent
0ddf3c794b
commit
f00fb1d9a3
@ -89,6 +89,7 @@ PLATFORMS = [
|
|||||||
Platform.FAN,
|
Platform.FAN,
|
||||||
Platform.LIGHT,
|
Platform.LIGHT,
|
||||||
Platform.LOCK,
|
Platform.LOCK,
|
||||||
|
Platform.MEDIA_PLAYER,
|
||||||
Platform.NUMBER,
|
Platform.NUMBER,
|
||||||
Platform.SCENE,
|
Platform.SCENE,
|
||||||
Platform.SELECT,
|
Platform.SELECT,
|
||||||
|
348
homeassistant/components/smartthings/media_player.py
Normal file
348
homeassistant/components/smartthings/media_player.py
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
"""Support for media players through the SmartThings cloud API."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from pysmartthings import Attribute, Capability, Category, Command, SmartThings
|
||||||
|
|
||||||
|
from homeassistant.components.media_player import (
|
||||||
|
MediaPlayerDeviceClass,
|
||||||
|
MediaPlayerEntity,
|
||||||
|
MediaPlayerEntityFeature,
|
||||||
|
MediaPlayerState,
|
||||||
|
RepeatMode,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
|
from . import FullDevice, SmartThingsConfigEntry
|
||||||
|
from .const import MAIN
|
||||||
|
from .entity import SmartThingsEntity
|
||||||
|
|
||||||
|
MEDIA_PLAYER_CAPABILITIES = (
|
||||||
|
Capability.AUDIO_MUTE,
|
||||||
|
Capability.AUDIO_TRACK_DATA,
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
)
|
||||||
|
|
||||||
|
CONTROLLABLE_SOURCES = ["bluetooth", "wifi"]
|
||||||
|
|
||||||
|
DEVICE_CLASS_MAP: dict[Category | str, MediaPlayerDeviceClass] = {
|
||||||
|
Category.NETWORK_AUDIO: MediaPlayerDeviceClass.SPEAKER,
|
||||||
|
Category.SPEAKER: MediaPlayerDeviceClass.SPEAKER,
|
||||||
|
Category.TELEVISION: MediaPlayerDeviceClass.TV,
|
||||||
|
Category.RECEIVER: MediaPlayerDeviceClass.RECEIVER,
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE_TO_STATE = {
|
||||||
|
"buffering": MediaPlayerState.BUFFERING,
|
||||||
|
"paused": MediaPlayerState.PAUSED,
|
||||||
|
"playing": MediaPlayerState.PLAYING,
|
||||||
|
"stopped": MediaPlayerState.IDLE,
|
||||||
|
"fast forwarding": MediaPlayerState.BUFFERING,
|
||||||
|
"rewinding": MediaPlayerState.BUFFERING,
|
||||||
|
}
|
||||||
|
|
||||||
|
REPEAT_MODE_TO_HA = {
|
||||||
|
"all": RepeatMode.ALL,
|
||||||
|
"one": RepeatMode.ONE,
|
||||||
|
"off": RepeatMode.OFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
HA_REPEAT_MODE_TO_SMARTTHINGS = {v: k for k, v in REPEAT_MODE_TO_HA.items()}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: SmartThingsConfigEntry,
|
||||||
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Add media players for a config entry."""
|
||||||
|
entry_data = entry.runtime_data
|
||||||
|
|
||||||
|
async_add_entities(
|
||||||
|
SmartThingsMediaPlayer(entry_data.client, device)
|
||||||
|
for device in entry_data.devices.values()
|
||||||
|
if all(
|
||||||
|
capability in device.status[MAIN]
|
||||||
|
for capability in MEDIA_PLAYER_CAPABILITIES
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SmartThingsMediaPlayer(SmartThingsEntity, MediaPlayerEntity):
|
||||||
|
"""Define a SmartThings media player."""
|
||||||
|
|
||||||
|
_attr_name = None
|
||||||
|
|
||||||
|
def __init__(self, client: SmartThings, device: FullDevice) -> None:
|
||||||
|
"""Initialize the media_player class."""
|
||||||
|
super().__init__(
|
||||||
|
client,
|
||||||
|
device,
|
||||||
|
{
|
||||||
|
Capability.AUDIO_MUTE,
|
||||||
|
Capability.AUDIO_TRACK_DATA,
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Capability.MEDIA_INPUT_SOURCE,
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Capability.MEDIA_PLAYBACK_REPEAT,
|
||||||
|
Capability.MEDIA_PLAYBACK_SHUFFLE,
|
||||||
|
Capability.SAMSUNG_VD_AUDIO_INPUT_SOURCE,
|
||||||
|
Capability.SWITCH,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self._attr_supported_features = self._determine_features()
|
||||||
|
self._attr_device_class = DEVICE_CLASS_MAP.get(
|
||||||
|
device.device.components[MAIN].user_category
|
||||||
|
or device.device.components[MAIN].manufacturer_category,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _determine_features(self) -> MediaPlayerEntityFeature:
|
||||||
|
flags = MediaPlayerEntityFeature(0)
|
||||||
|
playback_commands = self.get_attribute_value(
|
||||||
|
Capability.MEDIA_PLAYBACK, Attribute.SUPPORTED_PLAYBACK_COMMANDS
|
||||||
|
)
|
||||||
|
if "play" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.PLAY
|
||||||
|
if "pause" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.PAUSE
|
||||||
|
if "stop" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.STOP
|
||||||
|
if "rewind" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.PREVIOUS_TRACK
|
||||||
|
if "fastForward" in playback_commands:
|
||||||
|
flags |= MediaPlayerEntityFeature.NEXT_TRACK
|
||||||
|
if self.supports_capability(Capability.AUDIO_VOLUME):
|
||||||
|
flags |= (
|
||||||
|
MediaPlayerEntityFeature.VOLUME_SET
|
||||||
|
| MediaPlayerEntityFeature.VOLUME_STEP
|
||||||
|
)
|
||||||
|
if self.supports_capability(Capability.AUDIO_MUTE):
|
||||||
|
flags |= MediaPlayerEntityFeature.VOLUME_MUTE
|
||||||
|
if self.supports_capability(Capability.SWITCH):
|
||||||
|
flags |= (
|
||||||
|
MediaPlayerEntityFeature.TURN_ON | MediaPlayerEntityFeature.TURN_OFF
|
||||||
|
)
|
||||||
|
if self.supports_capability(Capability.MEDIA_INPUT_SOURCE):
|
||||||
|
flags |= MediaPlayerEntityFeature.SELECT_SOURCE
|
||||||
|
if self.supports_capability(Capability.MEDIA_PLAYBACK_SHUFFLE):
|
||||||
|
flags |= MediaPlayerEntityFeature.SHUFFLE_SET
|
||||||
|
if self.supports_capability(Capability.MEDIA_PLAYBACK_REPEAT):
|
||||||
|
flags |= MediaPlayerEntityFeature.REPEAT_SET
|
||||||
|
return flags
|
||||||
|
|
||||||
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
|
"""Turn the media player off."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.SWITCH,
|
||||||
|
Command.OFF,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
|
"""Turn the media player on."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.SWITCH,
|
||||||
|
Command.ON,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_mute_volume(self, mute: bool) -> None:
|
||||||
|
"""Mute volume."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.AUDIO_MUTE,
|
||||||
|
Command.SET_MUTE,
|
||||||
|
argument="muted" if mute else "unmuted",
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_set_volume_level(self, volume: float) -> None:
|
||||||
|
"""Set volume level."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Command.SET_VOLUME,
|
||||||
|
argument=int(volume * 100),
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_volume_up(self) -> None:
|
||||||
|
"""Increase volume."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Command.VOLUME_UP,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_volume_down(self) -> None:
|
||||||
|
"""Decrease volume."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Command.VOLUME_DOWN,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_media_play(self) -> None:
|
||||||
|
"""Play media."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.PLAY,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_media_pause(self) -> None:
|
||||||
|
"""Pause media."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.PAUSE,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_media_stop(self) -> None:
|
||||||
|
"""Stop media."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.STOP,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_media_previous_track(self) -> None:
|
||||||
|
"""Previous track."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.REWIND,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_media_next_track(self) -> None:
|
||||||
|
"""Next track."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.FAST_FORWARD,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_select_source(self, source: str) -> None:
|
||||||
|
"""Select source."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_INPUT_SOURCE,
|
||||||
|
Command.SET_INPUT_SOURCE,
|
||||||
|
argument=source,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_set_shuffle(self, shuffle: bool) -> None:
|
||||||
|
"""Set shuffle mode."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_PLAYBACK_SHUFFLE,
|
||||||
|
Command.SET_PLAYBACK_SHUFFLE,
|
||||||
|
argument="enabled" if shuffle else "disabled",
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_set_repeat(self, repeat: RepeatMode) -> None:
|
||||||
|
"""Set repeat mode."""
|
||||||
|
await self.execute_device_command(
|
||||||
|
Capability.MEDIA_PLAYBACK_REPEAT,
|
||||||
|
Command.SET_PLAYBACK_REPEAT_MODE,
|
||||||
|
argument=HA_REPEAT_MODE_TO_SMARTTHINGS[repeat],
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_title(self) -> str | None:
|
||||||
|
"""Title of current playing media."""
|
||||||
|
if (
|
||||||
|
track_data := self.get_attribute_value(
|
||||||
|
Capability.AUDIO_TRACK_DATA, Attribute.AUDIO_TRACK_DATA
|
||||||
|
)
|
||||||
|
) is None:
|
||||||
|
return None
|
||||||
|
return track_data.get("title", None)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_artist(self) -> str | None:
|
||||||
|
"""Artist of current playing media."""
|
||||||
|
if (
|
||||||
|
track_data := self.get_attribute_value(
|
||||||
|
Capability.AUDIO_TRACK_DATA, Attribute.AUDIO_TRACK_DATA
|
||||||
|
)
|
||||||
|
) is None:
|
||||||
|
return None
|
||||||
|
return track_data.get("artist")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self) -> MediaPlayerState | None:
|
||||||
|
"""State of the media player."""
|
||||||
|
if self.supports_capability(Capability.SWITCH):
|
||||||
|
if self.get_attribute_value(Capability.SWITCH, Attribute.SWITCH) == "on":
|
||||||
|
if (
|
||||||
|
self.source is not None
|
||||||
|
and self.source in CONTROLLABLE_SOURCES
|
||||||
|
and self.get_attribute_value(
|
||||||
|
Capability.MEDIA_PLAYBACK, Attribute.PLAYBACK_STATUS
|
||||||
|
)
|
||||||
|
in VALUE_TO_STATE
|
||||||
|
):
|
||||||
|
return VALUE_TO_STATE[
|
||||||
|
self.get_attribute_value(
|
||||||
|
Capability.MEDIA_PLAYBACK, Attribute.PLAYBACK_STATUS
|
||||||
|
)
|
||||||
|
]
|
||||||
|
return MediaPlayerState.ON
|
||||||
|
return MediaPlayerState.OFF
|
||||||
|
return VALUE_TO_STATE[
|
||||||
|
self.get_attribute_value(
|
||||||
|
Capability.MEDIA_PLAYBACK, Attribute.PLAYBACK_STATUS
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_volume_muted(self) -> bool:
|
||||||
|
"""Returns if the volume is muted."""
|
||||||
|
return (
|
||||||
|
self.get_attribute_value(Capability.AUDIO_MUTE, Attribute.MUTE) == "muted"
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def volume_level(self) -> float:
|
||||||
|
"""Volume level."""
|
||||||
|
return self.get_attribute_value(Capability.AUDIO_VOLUME, Attribute.VOLUME) / 100
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source(self) -> str | None:
|
||||||
|
"""Input source."""
|
||||||
|
if self.supports_capability(Capability.MEDIA_INPUT_SOURCE):
|
||||||
|
return self.get_attribute_value(
|
||||||
|
Capability.MEDIA_INPUT_SOURCE, Attribute.INPUT_SOURCE
|
||||||
|
)
|
||||||
|
if self.supports_capability(Capability.SAMSUNG_VD_AUDIO_INPUT_SOURCE):
|
||||||
|
return self.get_attribute_value(
|
||||||
|
Capability.SAMSUNG_VD_AUDIO_INPUT_SOURCE, Attribute.INPUT_SOURCE
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source_list(self) -> list[str] | None:
|
||||||
|
"""List of input sources."""
|
||||||
|
if self.supports_capability(Capability.MEDIA_INPUT_SOURCE):
|
||||||
|
return self.get_attribute_value(
|
||||||
|
Capability.MEDIA_INPUT_SOURCE, Attribute.SUPPORTED_INPUT_SOURCES
|
||||||
|
)
|
||||||
|
if self.supports_capability(Capability.SAMSUNG_VD_AUDIO_INPUT_SOURCE):
|
||||||
|
return self.get_attribute_value(
|
||||||
|
Capability.SAMSUNG_VD_AUDIO_INPUT_SOURCE,
|
||||||
|
Attribute.SUPPORTED_INPUT_SOURCES,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def shuffle(self) -> bool | None:
|
||||||
|
"""Returns if shuffle mode is set."""
|
||||||
|
if self.supports_capability(Capability.MEDIA_PLAYBACK_SHUFFLE):
|
||||||
|
return (
|
||||||
|
self.get_attribute_value(
|
||||||
|
Capability.MEDIA_PLAYBACK_SHUFFLE, Attribute.PLAYBACK_SHUFFLE
|
||||||
|
)
|
||||||
|
== "enabled"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def repeat(self) -> RepeatMode | None:
|
||||||
|
"""Returns if repeat mode is set."""
|
||||||
|
if self.supports_capability(Capability.MEDIA_PLAYBACK_REPEAT):
|
||||||
|
return REPEAT_MODE_TO_HA[
|
||||||
|
self.get_attribute_value(
|
||||||
|
Capability.MEDIA_PLAYBACK_REPEAT, Attribute.PLAYBACK_REPEAT_MODE
|
||||||
|
)
|
||||||
|
]
|
||||||
|
return None
|
@ -140,6 +140,7 @@ def mock_smartthings() -> Generator[AsyncMock]:
|
|||||||
"tplink_p110",
|
"tplink_p110",
|
||||||
"ikea_kadrilj",
|
"ikea_kadrilj",
|
||||||
"aux_ac",
|
"aux_ac",
|
||||||
|
"hw_q80r_soundbar",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
def device_fixture(
|
def device_fixture(
|
||||||
|
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"main": {
|
||||||
|
"mediaPlayback": {
|
||||||
|
"supportedPlaybackCommands": {
|
||||||
|
"value": ["play", "pause", "stop"],
|
||||||
|
"timestamp": "2025-03-23T01:10:02.207Z"
|
||||||
|
},
|
||||||
|
"playbackStatus": {
|
||||||
|
"value": "playing",
|
||||||
|
"timestamp": "2025-03-23T01:19:44.622Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungvd.groupInfo": {
|
||||||
|
"role": {
|
||||||
|
"value": "none",
|
||||||
|
"timestamp": "2025-03-23T01:17:10.965Z"
|
||||||
|
},
|
||||||
|
"channel": {
|
||||||
|
"value": "all",
|
||||||
|
"timestamp": "2025-03-23T01:17:10.965Z"
|
||||||
|
},
|
||||||
|
"masterName": {
|
||||||
|
"value": "",
|
||||||
|
"timestamp": "2025-03-23T01:17:10.965Z"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"value": "single",
|
||||||
|
"timestamp": "2025-03-23T01:17:10.965Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"audioVolume": {
|
||||||
|
"volume": {
|
||||||
|
"value": 1,
|
||||||
|
"unit": "%",
|
||||||
|
"timestamp": "2025-03-23T01:17:13.754Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ocf": {
|
||||||
|
"st": {
|
||||||
|
"value": "NONE",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mndt": {
|
||||||
|
"value": "2018-01-01",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnfv": {
|
||||||
|
"value": "HW-Q80RWWB-1012.6",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnhw": {
|
||||||
|
"value": "0-0",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"di": {
|
||||||
|
"value": "afcf3b91-48fe-4c3b-ab44-ddff2a0a6577",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnsl": {
|
||||||
|
"value": "http://www.samsung.com/sec/audio-video/",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"dmv": {
|
||||||
|
"value": "res.1.1.0,sh.1.1.0",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"n": {
|
||||||
|
"value": "[AV] Samsung Soundbar Q80R",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnmo": {
|
||||||
|
"value": "Q80R",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"vid": {
|
||||||
|
"value": "VD-NetworkAudio-001S",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnmn": {
|
||||||
|
"value": "Samsung Electronics",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnml": {
|
||||||
|
"value": "http://www.samsung.com",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnpv": {
|
||||||
|
"value": "Tizen 4.0",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"mnos": {
|
||||||
|
"value": "4.1.10",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"pi": {
|
||||||
|
"value": "afcf3b91-48fe-4c3b-ab44-ddff2a0a6577",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
},
|
||||||
|
"icv": {
|
||||||
|
"value": "core.1.1.0",
|
||||||
|
"timestamp": "2024-12-18T21:07:25.406Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mediaInputSource": {
|
||||||
|
"supportedInputSources": {
|
||||||
|
"value": ["wifi", "bluetooth", "HDMI1", "HDMI2", "digital"],
|
||||||
|
"timestamp": "2025-03-23T01:18:01.663Z"
|
||||||
|
},
|
||||||
|
"inputSource": {
|
||||||
|
"value": "wifi",
|
||||||
|
"timestamp": "2025-03-23T01:18:01.663Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"refresh": {},
|
||||||
|
"audioNotification": {},
|
||||||
|
"audioMute": {
|
||||||
|
"mute": {
|
||||||
|
"value": "unmuted",
|
||||||
|
"timestamp": "2025-03-23T01:17:11.024Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"execute": {
|
||||||
|
"data": {
|
||||||
|
"value": {
|
||||||
|
"payload": {
|
||||||
|
"rt": ["x.com.samsung.networkaudio.soundmode"],
|
||||||
|
"if": ["oic.if.a", "oic.if.baseline"],
|
||||||
|
"x.com.samsung.networkaudio.soundmode": "standard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"href": "/sec/networkaudio/soundmode"
|
||||||
|
},
|
||||||
|
"timestamp": "2023-07-16T23:16:55.582Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"samsungvd.audioInputSource": {
|
||||||
|
"supportedInputSources": {
|
||||||
|
"value": ["wifi", "bluetooth", "HDMI1", "HDMI2", "digital"],
|
||||||
|
"timestamp": "2025-03-23T01:18:01.663Z"
|
||||||
|
},
|
||||||
|
"inputSource": {
|
||||||
|
"value": "wificp",
|
||||||
|
"timestamp": "2025-03-23T01:18:01.663Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"switch": {
|
||||||
|
"value": "on",
|
||||||
|
"timestamp": "2025-03-23T01:19:44.837Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"audioTrackData": {
|
||||||
|
"totalTime": {
|
||||||
|
"value": null,
|
||||||
|
"timestamp": "2020-07-30T16:09:09.109Z"
|
||||||
|
},
|
||||||
|
"audioTrackData": {
|
||||||
|
"value": {
|
||||||
|
"title": "Never Gonna Give You Up",
|
||||||
|
"artist": "Rick Astley"
|
||||||
|
},
|
||||||
|
"timestamp": "2025-03-23T01:19:15.067Z"
|
||||||
|
},
|
||||||
|
"elapsedTime": {
|
||||||
|
"value": null,
|
||||||
|
"timestamp": "2020-07-30T16:09:09.109Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"deviceId": "afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
"name": "[AV] Samsung Soundbar Q80R",
|
||||||
|
"label": "Soundbar",
|
||||||
|
"manufacturerName": "Samsung Electronics",
|
||||||
|
"presentationId": "VD-NetworkAudio-001S",
|
||||||
|
"deviceManufacturerCode": "Samsung Electronics",
|
||||||
|
"locationId": "c7f8e400-0000-1111-2222-76463f4eb484",
|
||||||
|
"ownerId": "bd0d9288-0000-1111-2222-68310a42a709",
|
||||||
|
"roomId": "be09ff51-0000-1111-2222-e48e2dab37fd",
|
||||||
|
"deviceTypeName": "Samsung OCF Network Audio Player",
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"id": "main",
|
||||||
|
"label": "Soundbar",
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"id": "ocf",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "execute",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "refresh",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "switch",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audioVolume",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audioMute",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audioTrackData",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mediaInputSource",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungvd.audioInputSource",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mediaPlayback",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "audioNotification",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "samsungvd.groupInfo",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "NetworkAudio",
|
||||||
|
"categoryType": "manufacturer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"createTime": "2020-10-19T01:35:08Z",
|
||||||
|
"profile": {
|
||||||
|
"id": "c1036d88-000-1111-2222-a361463fd53f"
|
||||||
|
},
|
||||||
|
"ocf": {
|
||||||
|
"ocfDeviceType": "oic.d.networkaudio",
|
||||||
|
"name": "[AV] Samsung Soundbar Q80R",
|
||||||
|
"specVersion": "core.1.1.0",
|
||||||
|
"verticalDomainSpecVersion": "res.1.1.0,sh.1.1.0",
|
||||||
|
"manufacturerName": "Samsung Electronics",
|
||||||
|
"modelNumber": "Q80R",
|
||||||
|
"platformVersion": "Tizen 4.0",
|
||||||
|
"platformOS": "4.1.10",
|
||||||
|
"hwVersion": "0-0",
|
||||||
|
"firmwareVersion": "HW-Q80RWWB-1012.6",
|
||||||
|
"vendorId": "VD-NetworkAudio-001S",
|
||||||
|
"vendorResourceClientServerVersion": "1.2",
|
||||||
|
"locale": "KO",
|
||||||
|
"lastSignupTime": "2021-01-16T07:05:02.184545Z",
|
||||||
|
"transferCandidate": false,
|
||||||
|
"additionalAuthCodeRequired": false
|
||||||
|
},
|
||||||
|
"type": "OCF",
|
||||||
|
"restrictionTier": 0,
|
||||||
|
"allowed": null,
|
||||||
|
"executionContext": "CLOUD",
|
||||||
|
"relationships": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_links": {}
|
||||||
|
}
|
@ -1157,6 +1157,39 @@
|
|||||||
'via_device_id': None,
|
'via_device_id': None,
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_devices[hw_q80r_soundbar]
|
||||||
|
DeviceRegistryEntrySnapshot({
|
||||||
|
'area_id': None,
|
||||||
|
'config_entries': <ANY>,
|
||||||
|
'config_entries_subentries': <ANY>,
|
||||||
|
'configuration_url': 'https://account.smartthings.com',
|
||||||
|
'connections': set({
|
||||||
|
}),
|
||||||
|
'disabled_by': None,
|
||||||
|
'entry_type': None,
|
||||||
|
'hw_version': '0-0',
|
||||||
|
'id': <ANY>,
|
||||||
|
'identifiers': set({
|
||||||
|
tuple(
|
||||||
|
'smartthings',
|
||||||
|
'afcf3b91-0000-1111-2222-ddff2a0a6577',
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
'is_new': False,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'manufacturer': 'Samsung Electronics',
|
||||||
|
'model': 'Q80R',
|
||||||
|
'model_id': None,
|
||||||
|
'name': 'Soundbar',
|
||||||
|
'name_by_user': None,
|
||||||
|
'primary_config_entry': <ANY>,
|
||||||
|
'serial_number': None,
|
||||||
|
'suggested_area': None,
|
||||||
|
'sw_version': 'HW-Q80RWWB-1012.6',
|
||||||
|
'via_device_id': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_devices[ikea_kadrilj]
|
# name: test_devices[ikea_kadrilj]
|
||||||
DeviceRegistryEntrySnapshot({
|
DeviceRegistryEntrySnapshot({
|
||||||
'area_id': None,
|
'area_id': None,
|
||||||
|
233
tests/components/smartthings/snapshots/test_media_player.ambr
Normal file
233
tests/components/smartthings/snapshots/test_media_player.ambr
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
# serializer version: 1
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][media_player.soundbar-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'source_list': list([
|
||||||
|
'wifi',
|
||||||
|
'bluetooth',
|
||||||
|
'HDMI1',
|
||||||
|
'HDMI2',
|
||||||
|
'digital',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'media_player',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'media_player.soundbar',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <MediaPlayerDeviceClass.SPEAKER: 'speaker'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': None,
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 23949>,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': 'afcf3b91-0000-1111-2222-ddff2a0a6577',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][media_player.soundbar-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'speaker',
|
||||||
|
'friendly_name': 'Soundbar',
|
||||||
|
'is_volume_muted': False,
|
||||||
|
'media_artist': 'Rick Astley',
|
||||||
|
'media_title': 'Never Gonna Give You Up',
|
||||||
|
'source': 'wifi',
|
||||||
|
'source_list': list([
|
||||||
|
'wifi',
|
||||||
|
'bluetooth',
|
||||||
|
'HDMI1',
|
||||||
|
'HDMI2',
|
||||||
|
'digital',
|
||||||
|
]),
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 23949>,
|
||||||
|
'volume_level': 0.01,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'media_player.soundbar',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'playing',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[im_speaker_ai_0001][media_player.galaxy_home_mini-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'media_player',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'media_player.galaxy_home_mini',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <MediaPlayerDeviceClass.SPEAKER: 'speaker'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': None,
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 318477>,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': 'c9276e43-fe3c-88c3-1dcc-2eb79e292b8c',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[im_speaker_ai_0001][media_player.galaxy_home_mini-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'speaker',
|
||||||
|
'friendly_name': 'Galaxy Home Mini',
|
||||||
|
'is_volume_muted': False,
|
||||||
|
'repeat': <RepeatMode.OFF: 'off'>,
|
||||||
|
'shuffle': False,
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 318477>,
|
||||||
|
'volume_level': 0.52,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'media_player.galaxy_home_mini',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'idle',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[sonos_player][media_player.elliots_rum-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'media_player',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'media_player.elliots_rum',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <MediaPlayerDeviceClass.SPEAKER: 'speaker'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': None,
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 21517>,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': 'c85fced9-c474-4a47-93c2-037cc7829536',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[sonos_player][media_player.elliots_rum-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'speaker',
|
||||||
|
'friendly_name': 'Elliots Rum',
|
||||||
|
'is_volume_muted': False,
|
||||||
|
'media_artist': 'David Guetta',
|
||||||
|
'media_title': 'Forever Young',
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 21517>,
|
||||||
|
'volume_level': 0.15,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'media_player.elliots_rum',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'playing',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[vd_network_audio_002s][media_player.soundbar_living-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'media_player',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'media_player.soundbar_living',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <MediaPlayerDeviceClass.SPEAKER: 'speaker'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': None,
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 21901>,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': '0d94e5db-8501-2355-eb4f-214163702cac',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[vd_network_audio_002s][media_player.soundbar_living-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'speaker',
|
||||||
|
'friendly_name': 'Soundbar Living',
|
||||||
|
'is_volume_muted': False,
|
||||||
|
'media_artist': '',
|
||||||
|
'media_title': '',
|
||||||
|
'source': 'HDMI1',
|
||||||
|
'supported_features': <MediaPlayerEntityFeature: 21901>,
|
||||||
|
'volume_level': 0.17,
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'media_player.soundbar_living',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'on',
|
||||||
|
})
|
||||||
|
# ---
|
@ -7193,6 +7193,182 @@
|
|||||||
'state': '19.0',
|
'state': '19.0',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][sensor.soundbar_media_input_source-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'options': list([
|
||||||
|
'wifi',
|
||||||
|
'bluetooth',
|
||||||
|
'hdmi1',
|
||||||
|
'hdmi2',
|
||||||
|
'digital',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.soundbar_media_input_source',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Media input source',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'media_input_source',
|
||||||
|
'unique_id': 'afcf3b91-0000-1111-2222-ddff2a0a6577.inputSource',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][sensor.soundbar_media_input_source-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'enum',
|
||||||
|
'friendly_name': 'Soundbar Media input source',
|
||||||
|
'options': list([
|
||||||
|
'wifi',
|
||||||
|
'bluetooth',
|
||||||
|
'hdmi1',
|
||||||
|
'hdmi2',
|
||||||
|
'digital',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.soundbar_media_input_source',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'wifi',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][sensor.soundbar_media_playback_status-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'options': list([
|
||||||
|
'paused',
|
||||||
|
'playing',
|
||||||
|
'stopped',
|
||||||
|
'fast_forwarding',
|
||||||
|
'rewinding',
|
||||||
|
'buffering',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.soundbar_media_playback_status',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Media playback status',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'media_playback_status',
|
||||||
|
'unique_id': 'afcf3b91-0000-1111-2222-ddff2a0a6577.playbackStatus',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][sensor.soundbar_media_playback_status-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'enum',
|
||||||
|
'friendly_name': 'Soundbar Media playback status',
|
||||||
|
'options': list([
|
||||||
|
'paused',
|
||||||
|
'playing',
|
||||||
|
'stopped',
|
||||||
|
'fast_forwarding',
|
||||||
|
'rewinding',
|
||||||
|
'buffering',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.soundbar_media_playback_status',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'playing',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][sensor.soundbar_volume-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'sensor.soundbar_volume',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': None,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'Volume',
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'audio_volume',
|
||||||
|
'unique_id': 'afcf3b91-0000-1111-2222-ddff2a0a6577.volume',
|
||||||
|
'unit_of_measurement': '%',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][sensor.soundbar_volume-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Soundbar Volume',
|
||||||
|
'unit_of_measurement': '%',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.soundbar_volume',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': '1',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_all_entities[ikea_kadrilj][sensor.kitchen_ikea_kadrilj_window_blind_battery-entry]
|
# name: test_all_entities[ikea_kadrilj][sensor.kitchen_ikea_kadrilj_window_blind_battery-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
|
@ -610,6 +610,53 @@
|
|||||||
'state': 'off',
|
'state': 'off',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][switch.soundbar-entry]
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'config_subentry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'switch',
|
||||||
|
'entity_category': None,
|
||||||
|
'entity_id': 'switch.soundbar',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'labels': set({
|
||||||
|
}),
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': None,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': None,
|
||||||
|
'platform': 'smartthings',
|
||||||
|
'previous_unique_id': None,
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': 'afcf3b91-0000-1111-2222-ddff2a0a6577',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
# name: test_all_entities[hw_q80r_soundbar][switch.soundbar-state]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'friendly_name': 'Soundbar',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'switch.soundbar',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_reported': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'on',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_all_entities[sensibo_airconditioner_1][switch.office-entry]
|
# name: test_all_entities[sensibo_airconditioner_1][switch.office-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
|
432
tests/components/smartthings/test_media_player.py
Normal file
432
tests/components/smartthings/test_media_player.py
Normal file
@ -0,0 +1,432 @@
|
|||||||
|
"""Test for the SmartThings media player platform."""
|
||||||
|
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
|
from pysmartthings import Attribute, Capability, Command, Status
|
||||||
|
import pytest
|
||||||
|
from syrupy import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.media_player import (
|
||||||
|
ATTR_INPUT_SOURCE,
|
||||||
|
ATTR_MEDIA_REPEAT,
|
||||||
|
ATTR_MEDIA_SHUFFLE,
|
||||||
|
ATTR_MEDIA_VOLUME_LEVEL,
|
||||||
|
ATTR_MEDIA_VOLUME_MUTED,
|
||||||
|
DOMAIN as MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_SELECT_SOURCE,
|
||||||
|
RepeatMode,
|
||||||
|
)
|
||||||
|
from homeassistant.components.smartthings.const import MAIN
|
||||||
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID,
|
||||||
|
SERVICE_MEDIA_NEXT_TRACK,
|
||||||
|
SERVICE_MEDIA_PAUSE,
|
||||||
|
SERVICE_MEDIA_PLAY,
|
||||||
|
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||||
|
SERVICE_MEDIA_STOP,
|
||||||
|
SERVICE_REPEAT_SET,
|
||||||
|
SERVICE_SHUFFLE_SET,
|
||||||
|
SERVICE_TURN_OFF,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
SERVICE_VOLUME_DOWN,
|
||||||
|
SERVICE_VOLUME_MUTE,
|
||||||
|
SERVICE_VOLUME_SET,
|
||||||
|
SERVICE_VOLUME_UP,
|
||||||
|
STATE_OFF,
|
||||||
|
STATE_PLAYING,
|
||||||
|
Platform,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_registry as er
|
||||||
|
|
||||||
|
from . import setup_integration, snapshot_smartthings_entities, trigger_update
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
|
||||||
|
async def test_all_entities(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test all entities."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
snapshot_smartthings_entities(
|
||||||
|
hass, entity_registry, snapshot, Platform.MEDIA_PLAYER
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("action", "command"),
|
||||||
|
[
|
||||||
|
(SERVICE_TURN_ON, Command.ON),
|
||||||
|
(SERVICE_TURN_OFF, Command.OFF),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_turn_on_off(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
action: str,
|
||||||
|
command: Command,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player turn on and off command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
action,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577", Capability.SWITCH, command, MAIN
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("muted", "argument"),
|
||||||
|
[
|
||||||
|
(True, "muted"),
|
||||||
|
(False, "unmuted"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_mute_unmute(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
muted: bool,
|
||||||
|
argument: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player mute and unmute command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_VOLUME_MUTE,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar", ATTR_MEDIA_VOLUME_MUTED: muted},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.AUDIO_MUTE,
|
||||||
|
Command.SET_MUTE,
|
||||||
|
MAIN,
|
||||||
|
argument=argument,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_set_volume_level(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player set volume level command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_VOLUME_SET,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar", ATTR_MEDIA_VOLUME_LEVEL: 0.31},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Command.SET_VOLUME,
|
||||||
|
MAIN,
|
||||||
|
argument=31,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_volume_up(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player increase volume level command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_VOLUME_UP,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Command.VOLUME_UP,
|
||||||
|
MAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_volume_down(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player decrease volume level command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_VOLUME_DOWN,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.AUDIO_VOLUME,
|
||||||
|
Command.VOLUME_DOWN,
|
||||||
|
MAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_media_play(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player play command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_MEDIA_PLAY,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.PLAY,
|
||||||
|
MAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_media_pause(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player pause command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_MEDIA_PAUSE,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.PAUSE,
|
||||||
|
MAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_media_stop(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player stop command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_MEDIA_STOP,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.STOP,
|
||||||
|
MAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_media_previous_track(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player previous track command."""
|
||||||
|
devices.get_device_status.return_value[MAIN][Capability.MEDIA_PLAYBACK] = {
|
||||||
|
Attribute.SUPPORTED_PLAYBACK_COMMANDS: Status(["rewind"])
|
||||||
|
}
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.REWIND,
|
||||||
|
MAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_media_next_track(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player next track command."""
|
||||||
|
devices.get_device_status.return_value[MAIN][Capability.MEDIA_PLAYBACK] = {
|
||||||
|
Attribute.SUPPORTED_PLAYBACK_COMMANDS: Status(["fastForward"])
|
||||||
|
}
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_MEDIA_NEXT_TRACK,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_PLAYBACK,
|
||||||
|
Command.FAST_FORWARD,
|
||||||
|
MAIN,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_select_source(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player stop command."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_SELECT_SOURCE,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar", ATTR_INPUT_SOURCE: "digital"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_INPUT_SOURCE,
|
||||||
|
Command.SET_INPUT_SOURCE,
|
||||||
|
MAIN,
|
||||||
|
"digital",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("shuffle", "argument"),
|
||||||
|
[
|
||||||
|
(True, "enabled"),
|
||||||
|
(False, "disabled"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_media_shuffle_on_off(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
shuffle: bool,
|
||||||
|
argument: bool,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player media shuffle command."""
|
||||||
|
devices.get_device_status.return_value[MAIN][Capability.MEDIA_PLAYBACK_SHUFFLE] = {
|
||||||
|
Attribute.PLAYBACK_SHUFFLE: Status(True)
|
||||||
|
}
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_SHUFFLE_SET,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar", ATTR_MEDIA_SHUFFLE: shuffle},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_PLAYBACK_SHUFFLE,
|
||||||
|
Command.SET_PLAYBACK_SHUFFLE,
|
||||||
|
MAIN,
|
||||||
|
argument=argument,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("repeat", "argument"),
|
||||||
|
[
|
||||||
|
(RepeatMode.OFF, "off"),
|
||||||
|
(RepeatMode.ONE, "one"),
|
||||||
|
(RepeatMode.ALL, "all"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_media_repeat_mode(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
repeat: RepeatMode,
|
||||||
|
argument: bool,
|
||||||
|
) -> None:
|
||||||
|
"""Test media player repeat mode command."""
|
||||||
|
devices.get_device_status.return_value[MAIN][Capability.MEDIA_PLAYBACK_REPEAT] = {
|
||||||
|
Attribute.REPEAT_MODE: Status("one")
|
||||||
|
}
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
MEDIA_PLAYER_DOMAIN,
|
||||||
|
SERVICE_REPEAT_SET,
|
||||||
|
{ATTR_ENTITY_ID: "media_player.soundbar", ATTR_MEDIA_REPEAT: repeat},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
devices.execute_device_command.assert_called_once_with(
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.MEDIA_PLAYBACK_REPEAT,
|
||||||
|
Command.SET_PLAYBACK_REPEAT_MODE,
|
||||||
|
MAIN,
|
||||||
|
argument=argument,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("device_fixture", ["hw_q80r_soundbar"])
|
||||||
|
async def test_state_update(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
devices: AsyncMock,
|
||||||
|
mock_config_entry: MockConfigEntry,
|
||||||
|
) -> None:
|
||||||
|
"""Test state update."""
|
||||||
|
await setup_integration(hass, mock_config_entry)
|
||||||
|
|
||||||
|
assert hass.states.get("media_player.soundbar").state == STATE_PLAYING
|
||||||
|
|
||||||
|
await trigger_update(
|
||||||
|
hass,
|
||||||
|
devices,
|
||||||
|
"afcf3b91-0000-1111-2222-ddff2a0a6577",
|
||||||
|
Capability.SWITCH,
|
||||||
|
Attribute.SWITCH,
|
||||||
|
"off",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hass.states.get("media_player.soundbar").state == STATE_OFF
|
Loading…
x
Reference in New Issue
Block a user