Formalize supported_features as entity property (#5794)
* Formalize supported_features as entity property * Remove extra emulated_hue conditions * Generate log message in executor
This commit is contained in:
parent
4fa4d7347f
commit
ecfe8e0a9a
49 changed files with 193 additions and 165 deletions
|
@ -8,14 +8,13 @@ from homeassistant import core
|
|||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_SET,
|
||||
SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, STATE_ON, STATE_OFF,
|
||||
HTTP_BAD_REQUEST, HTTP_NOT_FOUND,
|
||||
HTTP_BAD_REQUEST, HTTP_NOT_FOUND, ATTR_SUPPORTED_FEATURES,
|
||||
)
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS, ATTR_SUPPORTED_FEATURES, SUPPORT_BRIGHTNESS
|
||||
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS
|
||||
)
|
||||
from homeassistant.components.media_player import (
|
||||
ATTR_MEDIA_VOLUME_LEVEL, ATTR_SUPPORTED_MEDIA_COMMANDS,
|
||||
SUPPORT_VOLUME_SET,
|
||||
ATTR_MEDIA_VOLUME_LEVEL, SUPPORT_VOLUME_SET,
|
||||
)
|
||||
from homeassistant.components.fan import (
|
||||
ATTR_SPEED, SUPPORT_SET_SPEED, SPEED_OFF, SPEED_LOW,
|
||||
|
@ -178,11 +177,10 @@ class HueOneLightChangeView(HomeAssistantView):
|
|||
# Make sure the entity actually supports brightness
|
||||
entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||
|
||||
if (entity_features &
|
||||
SUPPORT_BRIGHTNESS &
|
||||
(entity.domain == "light")) == SUPPORT_BRIGHTNESS:
|
||||
if brightness is not None:
|
||||
data[ATTR_BRIGHTNESS] = brightness
|
||||
if entity.domain == "light":
|
||||
if entity_features & SUPPORT_BRIGHTNESS:
|
||||
if brightness is not None:
|
||||
data[ATTR_BRIGHTNESS] = brightness
|
||||
|
||||
# If the requested entity is a script add some variables
|
||||
elif entity.domain == "script":
|
||||
|
@ -195,9 +193,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
|||
|
||||
# If the requested entity is a media player, convert to volume
|
||||
elif entity.domain == "media_player":
|
||||
media_commands = entity.attributes.get(
|
||||
ATTR_SUPPORTED_MEDIA_COMMANDS, 0)
|
||||
if media_commands & SUPPORT_VOLUME_SET == SUPPORT_VOLUME_SET:
|
||||
if entity_features & SUPPORT_VOLUME_SET:
|
||||
if brightness is not None:
|
||||
turn_on_needed = True
|
||||
domain = entity.domain
|
||||
|
@ -215,9 +211,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
|||
|
||||
# If the requested entity is a fan, convert to speed
|
||||
elif entity.domain == "fan":
|
||||
functions = entity.attributes.get(
|
||||
ATTR_SUPPORTED_FEATURES, 0)
|
||||
if (functions & SUPPORT_SET_SPEED) == SUPPORT_SET_SPEED:
|
||||
if entity_features & SUPPORT_SET_SPEED:
|
||||
if brightness is not None:
|
||||
domain = entity.domain
|
||||
# Convert 0-100 to a fan speed
|
||||
|
@ -288,9 +282,10 @@ def parse_hue_api_put_light_body(request_json, entity):
|
|||
# Make sure the entity actually supports brightness
|
||||
entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||
|
||||
if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS:
|
||||
report_brightness = True
|
||||
result = (brightness > 0)
|
||||
if entity.domain == "light":
|
||||
if entity_features & SUPPORT_BRIGHTNESS:
|
||||
report_brightness = True
|
||||
result = (brightness > 0)
|
||||
|
||||
elif (entity.domain == "script" or
|
||||
entity.domain == "media_player" or
|
||||
|
@ -316,8 +311,9 @@ def get_entity_state(config, entity):
|
|||
# Make sure the entity actually supports brightness
|
||||
entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||
|
||||
if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS:
|
||||
pass
|
||||
if entity.domain == "light":
|
||||
if entity_features & SUPPORT_BRIGHTNESS:
|
||||
pass
|
||||
|
||||
elif entity.domain == "media_player":
|
||||
level = entity.attributes.get(
|
||||
|
|
|
@ -34,7 +34,6 @@ ENTITY_ID_ALL_FANS = group.ENTITY_ID_FORMAT.format(GROUP_NAME_ALL_FANS)
|
|||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
|
||||
# Bitfield of features supported by the fan entity
|
||||
ATTR_SUPPORTED_FEATURES = 'supported_features'
|
||||
SUPPORT_SET_SPEED = 1
|
||||
SUPPORT_OSCILLATE = 2
|
||||
SUPPORT_DIRECTION = 4
|
||||
|
@ -60,7 +59,6 @@ PROP_TO_ATTR = {
|
|||
'speed': ATTR_SPEED,
|
||||
'speed_list': ATTR_SPEED_LIST,
|
||||
'oscillating': ATTR_OSCILLATING,
|
||||
'supported_features': ATTR_SUPPORTED_FEATURES,
|
||||
'direction': ATTR_DIRECTION,
|
||||
} # type: dict
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ ENTITY_ID_ALL_LIGHTS = group.ENTITY_ID_FORMAT.format('all_lights')
|
|||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
|
||||
# Bitfield of features supported by the light entity
|
||||
ATTR_SUPPORTED_FEATURES = 'supported_features'
|
||||
SUPPORT_BRIGHTNESS = 1
|
||||
SUPPORT_COLOR_TEMP = 2
|
||||
SUPPORT_EFFECT = 4
|
||||
|
@ -85,7 +84,6 @@ PROP_TO_ATTR = {
|
|||
'white_value': ATTR_WHITE_VALUE,
|
||||
'effect_list': ATTR_EFFECT_LIST,
|
||||
'effect': ATTR_EFFECT,
|
||||
'supported_features': ATTR_SUPPORTED_FEATURES,
|
||||
}
|
||||
|
||||
# Service call validation schemas
|
||||
|
@ -364,8 +362,6 @@ class Light(ToggleEntity):
|
|||
data[ATTR_RGB_COLOR] = color_util.color_xy_brightness_to_RGB(
|
||||
data[ATTR_XY_COLOR][0], data[ATTR_XY_COLOR][1],
|
||||
data[ATTR_BRIGHTNESS])
|
||||
else:
|
||||
data[ATTR_SUPPORTED_FEATURES] = self.supported_features
|
||||
|
||||
return data
|
||||
|
||||
|
|
|
@ -77,7 +77,6 @@ ATTR_MEDIA_CHANNEL = 'media_channel'
|
|||
ATTR_MEDIA_PLAYLIST = 'media_playlist'
|
||||
ATTR_APP_ID = 'app_id'
|
||||
ATTR_APP_NAME = 'app_name'
|
||||
ATTR_SUPPORTED_MEDIA_COMMANDS = 'supported_media_commands'
|
||||
ATTR_INPUT_SOURCE = 'source'
|
||||
ATTR_INPUT_SOURCE_LIST = 'source_list'
|
||||
ATTR_MEDIA_ENQUEUE = 'enqueue'
|
||||
|
@ -183,7 +182,6 @@ ATTR_TO_PROPERTY = [
|
|||
ATTR_MEDIA_PLAYLIST,
|
||||
ATTR_APP_ID,
|
||||
ATTR_APP_NAME,
|
||||
ATTR_SUPPORTED_MEDIA_COMMANDS,
|
||||
ATTR_INPUT_SOURCE,
|
||||
ATTR_INPUT_SOURCE_LIST,
|
||||
]
|
||||
|
@ -523,7 +521,39 @@ class MediaPlayerDevice(Entity):
|
|||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag media commands that are supported."""
|
||||
"""Flag media commands that are supported.
|
||||
|
||||
DEPRECATED: Included for temporary custom platform compatibility.
|
||||
"""
|
||||
return None
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
# Begin temporary transition logic
|
||||
|
||||
if self.supported_media_commands is not None:
|
||||
# If this platform is still using supported_media_commands, issue
|
||||
# a logger warning once with instructions on how to fix it.
|
||||
if not getattr(self, '_supported_features_warned', False):
|
||||
def show_warning():
|
||||
"""Show a deprecation warning in the log for this class."""
|
||||
import inspect
|
||||
_LOGGER.warning(
|
||||
"supported_media_commands is deprecated. Please "
|
||||
"rename supported_media_commands to "
|
||||
"supported_features in '%s' to ensure future support.",
|
||||
inspect.getfile(self.__class__))
|
||||
# This is a temporary attribute. We don't want to pollute
|
||||
# __init__ so it can be easily removed.
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
self._supported_features_warned = True
|
||||
self.hass.add_job(show_warning)
|
||||
|
||||
# Return the old property
|
||||
return self.supported_media_commands
|
||||
|
||||
# End temporary transition logic
|
||||
return 0
|
||||
|
||||
def turn_on(self):
|
||||
|
@ -686,57 +716,57 @@ class MediaPlayerDevice(Entity):
|
|||
@property
|
||||
def support_play(self):
|
||||
"""Boolean if play is supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_PLAY)
|
||||
return bool(self.supported_features & SUPPORT_PLAY)
|
||||
|
||||
@property
|
||||
def support_pause(self):
|
||||
"""Boolean if pause is supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_PAUSE)
|
||||
return bool(self.supported_features & SUPPORT_PAUSE)
|
||||
|
||||
@property
|
||||
def support_stop(self):
|
||||
"""Boolean if stop is supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_STOP)
|
||||
return bool(self.supported_features & SUPPORT_STOP)
|
||||
|
||||
@property
|
||||
def support_seek(self):
|
||||
"""Boolean if seek is supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_SEEK)
|
||||
return bool(self.supported_features & SUPPORT_SEEK)
|
||||
|
||||
@property
|
||||
def support_volume_set(self):
|
||||
"""Boolean if setting volume is supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_VOLUME_SET)
|
||||
return bool(self.supported_features & SUPPORT_VOLUME_SET)
|
||||
|
||||
@property
|
||||
def support_volume_mute(self):
|
||||
"""Boolean if muting volume is supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_VOLUME_MUTE)
|
||||
return bool(self.supported_features & SUPPORT_VOLUME_MUTE)
|
||||
|
||||
@property
|
||||
def support_previous_track(self):
|
||||
"""Boolean if previous track command supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_PREVIOUS_TRACK)
|
||||
return bool(self.supported_features & SUPPORT_PREVIOUS_TRACK)
|
||||
|
||||
@property
|
||||
def support_next_track(self):
|
||||
"""Boolean if next track command supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_NEXT_TRACK)
|
||||
return bool(self.supported_features & SUPPORT_NEXT_TRACK)
|
||||
|
||||
@property
|
||||
def support_play_media(self):
|
||||
"""Boolean if play media command supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_PLAY_MEDIA)
|
||||
return bool(self.supported_features & SUPPORT_PLAY_MEDIA)
|
||||
|
||||
@property
|
||||
def support_select_source(self):
|
||||
"""Boolean if select source command supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_SELECT_SOURCE)
|
||||
return bool(self.supported_features & SUPPORT_SELECT_SOURCE)
|
||||
|
||||
@property
|
||||
def support_clear_playlist(self):
|
||||
"""Boolean if clear playlist command supported."""
|
||||
return bool(self.supported_media_commands & SUPPORT_CLEAR_PLAYLIST)
|
||||
return bool(self.supported_features & SUPPORT_CLEAR_PLAYLIST)
|
||||
|
||||
def toggle(self):
|
||||
"""Toggle the power on the media player."""
|
||||
|
@ -821,14 +851,12 @@ class MediaPlayerDevice(Entity):
|
|||
def state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
if self.state == STATE_OFF:
|
||||
state_attr = {
|
||||
ATTR_SUPPORTED_MEDIA_COMMANDS: self.supported_media_commands,
|
||||
}
|
||||
else:
|
||||
state_attr = {
|
||||
attr: getattr(self, attr) for attr
|
||||
in ATTR_TO_PROPERTY if getattr(self, attr) is not None
|
||||
}
|
||||
return None
|
||||
|
||||
state_attr = {
|
||||
attr: getattr(self, attr) for attr
|
||||
in ATTR_TO_PROPERTY if getattr(self, attr) is not None
|
||||
}
|
||||
|
||||
return state_attr
|
||||
|
||||
|
|
|
@ -79,8 +79,8 @@ class AnthemAVR(MediaPlayerDevice):
|
|||
return getattr(self.avr.protocol, propname, dval)
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Return flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_ANTHEMAV
|
||||
|
||||
@property
|
||||
|
|
|
@ -184,8 +184,8 @@ class AppleTvDevice(MediaPlayerDevice):
|
|||
return title if title else "No title"
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self._playing is not None:
|
||||
if self.state != STATE_IDLE:
|
||||
return SUPPORT_PAUSE | SUPPORT_PLAY | \
|
||||
|
|
|
@ -191,8 +191,8 @@ class SharpAquosTVDevice(MediaPlayerDevice):
|
|||
return self._muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_SHARPTV
|
||||
|
||||
@_retry
|
||||
|
|
|
@ -316,8 +316,8 @@ class BraviaTVDevice(MediaPlayerDevice):
|
|||
return self._muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_BRAVIA
|
||||
|
||||
@property
|
||||
|
|
|
@ -226,8 +226,8 @@ class CastDevice(MediaPlayerDevice):
|
|||
return self.cast.app_display_name
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_CAST
|
||||
|
||||
@property
|
||||
|
|
|
@ -151,8 +151,8 @@ class CmusDevice(MediaPlayerDevice):
|
|||
return int(volume)/100
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_CMUS
|
||||
|
||||
def turn_off(self):
|
||||
|
|
|
@ -155,8 +155,8 @@ class DemoYoutubePlayer(AbstractDemoPlayer):
|
|||
return "YouTube"
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return YOUTUBE_PLAYER_SUPPORT
|
||||
|
||||
@property
|
||||
|
@ -269,8 +269,8 @@ class DemoMusicPlayer(AbstractDemoPlayer):
|
|||
return self._cur_track + 1
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
support = MUSIC_PLAYER_SUPPORT
|
||||
|
||||
if self._cur_track > 0:
|
||||
|
@ -364,8 +364,8 @@ class DemoTVShowPlayer(AbstractDemoPlayer):
|
|||
return self._source
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
support = NETFLIX_PLAYER_SUPPORT
|
||||
|
||||
if self._cur_episode > 1:
|
||||
|
|
|
@ -193,8 +193,8 @@ class DenonDevice(MediaPlayerDevice):
|
|||
return self._mediainfo
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self._mediasource in MEDIA_MODES.values():
|
||||
return SUPPORT_DENON | SUPPORT_MEDIA_MODES
|
||||
else:
|
||||
|
|
|
@ -167,8 +167,8 @@ class DenonDevice(MediaPlayerDevice):
|
|||
return self._source_list
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self._current_source in self._receiver.netaudio_func_list:
|
||||
return SUPPORT_DENON | SUPPORT_MEDIA_MODES
|
||||
else:
|
||||
|
|
|
@ -133,8 +133,8 @@ class DirecTvDevice(MediaPlayerDevice):
|
|||
return None
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_DTV
|
||||
|
||||
@property
|
||||
|
|
|
@ -97,8 +97,8 @@ class DuneHDPlayerEntity(MediaPlayerDevice):
|
|||
return list(self._sources.keys())
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return DUNEHD_PLAYER_SUPPORT
|
||||
|
||||
def volume_up(self):
|
||||
|
|
|
@ -309,8 +309,8 @@ class EmbyClient(MediaPlayerDevice):
|
|||
return self.now_playing_item['IndexNumber']
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self.supports_remote_control:
|
||||
return SUPPORT_EMBY
|
||||
else:
|
||||
|
|
|
@ -122,8 +122,8 @@ class FireTVDevice(MediaPlayerDevice):
|
|||
return True
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_FIRETV
|
||||
|
||||
@property
|
||||
|
|
|
@ -295,8 +295,8 @@ class GPMDP(MediaPlayerDevice):
|
|||
return self._name
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_GPMDP
|
||||
|
||||
def media_next_track(self):
|
||||
|
|
|
@ -158,8 +158,8 @@ class CecPlayerDevice(CecDevice, MediaPlayerDevice):
|
|||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
from pycec.const import TYPE_RECORDER, TYPE_PLAYBACK, TYPE_TUNER, \
|
||||
TYPE_AUDIO
|
||||
if self.type_id == TYPE_RECORDER or self.type == TYPE_PLAYBACK:
|
||||
|
|
|
@ -306,8 +306,8 @@ class ItunesDevice(MediaPlayerDevice):
|
|||
return self.current_playlist
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_ITUNES
|
||||
|
||||
def set_volume_level(self, volume):
|
||||
|
@ -425,8 +425,8 @@ class AirPlayDevice(MediaPlayerDevice):
|
|||
return MEDIA_TYPE_MUSIC
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_AIRPLAY
|
||||
|
||||
def set_volume_level(self, volume):
|
||||
|
|
|
@ -228,14 +228,14 @@ class KodiDevice(MediaPlayerDevice):
|
|||
self._item.get('label', self._item.get('file', 'unknown')))
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
supported_media_commands = SUPPORT_KODI
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
supported_features = SUPPORT_KODI
|
||||
|
||||
if self._turn_off_action in TURN_OFF_ACTION:
|
||||
supported_media_commands |= SUPPORT_TURN_OFF
|
||||
supported_features |= SUPPORT_TURN_OFF
|
||||
|
||||
return supported_media_commands
|
||||
return supported_features
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_turn_off(self):
|
||||
|
|
|
@ -163,8 +163,8 @@ class LgTVDevice(MediaPlayerDevice):
|
|||
return self._program_name
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_LGTV
|
||||
|
||||
@property
|
||||
|
|
|
@ -133,8 +133,8 @@ class LiveboxPlayTvDevice(MediaPlayerDevice):
|
|||
self._current_program)
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_LIVEBOXPLAYTV
|
||||
|
||||
def refresh_channel_list(self):
|
||||
|
|
|
@ -126,8 +126,8 @@ class MpcHcDevice(MediaPlayerDevice):
|
|||
int(duration[2])
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_MPCHC
|
||||
|
||||
def volume_up(self):
|
||||
|
|
|
@ -184,8 +184,8 @@ class MpdDevice(MediaPlayerDevice):
|
|||
return int(self.status['volume'])/100
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_MPD
|
||||
|
||||
@property
|
||||
|
|
|
@ -136,8 +136,8 @@ class NAD(MediaPlayerDevice):
|
|||
return self._mute
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_NAD
|
||||
|
||||
def turn_off(self):
|
||||
|
|
|
@ -150,8 +150,8 @@ class OnkyoDevice(MediaPlayerDevice):
|
|||
return self._muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_ONKYO
|
||||
|
||||
@property
|
||||
|
|
|
@ -123,8 +123,8 @@ class PanasonicVieraTVDevice(MediaPlayerDevice):
|
|||
return self._muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self._mac:
|
||||
return SUPPORT_VIERATV | SUPPORT_TURN_ON
|
||||
return SUPPORT_VIERATV
|
||||
|
|
|
@ -158,8 +158,8 @@ class PandoraMediaPlayer(MediaPlayerDevice):
|
|||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Show what this supports."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return PANDORA_SUPPORT
|
||||
|
||||
@property
|
||||
|
|
|
@ -86,8 +86,8 @@ class PhilipsTV(MediaPlayerDevice):
|
|||
return True
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self._watching_tv:
|
||||
return SUPPORT_PHILIPS_JS_TV
|
||||
else:
|
||||
|
|
|
@ -176,8 +176,8 @@ class PioneerDevice(MediaPlayerDevice):
|
|||
return self._muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_PIONEER
|
||||
|
||||
@property
|
||||
|
|
|
@ -334,8 +334,8 @@ class PlexClient(MediaPlayerDevice):
|
|||
return self._convert_na_to_none(self.session.index)
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_PLEX
|
||||
|
||||
def set_volume_level(self, volume):
|
||||
|
|
|
@ -142,8 +142,8 @@ class RokuDevice(MediaPlayerDevice):
|
|||
return STATE_UNKNOWN
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_ROKU
|
||||
|
||||
@property
|
||||
|
|
|
@ -95,8 +95,8 @@ class RussoundRNETDevice(MediaPlayerDevice):
|
|||
return self._state
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_RUSSOUND
|
||||
|
||||
@property
|
||||
|
|
|
@ -156,8 +156,8 @@ class SamsungTVDevice(MediaPlayerDevice):
|
|||
return self._muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_SAMSUNGTV
|
||||
|
||||
def turn_off(self):
|
||||
|
|
|
@ -72,8 +72,8 @@ class SnapcastDevice(MediaPlayerDevice):
|
|||
return self._client.muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_SNAPCAST
|
||||
|
||||
@property
|
||||
|
|
|
@ -761,10 +761,10 @@ class SonosDevice(MediaPlayerDevice):
|
|||
return self._media_title
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self._coordinator:
|
||||
return self._coordinator.supported_media_commands
|
||||
return self._coordinator.supported_features
|
||||
|
||||
supported = SUPPORT_SONOS
|
||||
|
||||
|
|
|
@ -287,8 +287,8 @@ class SoundTouchDevice(MediaPlayerDevice):
|
|||
return self._volume.muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_SOUNDTOUCH
|
||||
|
||||
def turn_off(self):
|
||||
|
|
|
@ -302,8 +302,8 @@ class SqueezeBoxDevice(MediaPlayerDevice):
|
|||
return self._status['album']
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_SQUEEZEBOX
|
||||
|
||||
def async_turn_off(self):
|
||||
|
|
|
@ -17,7 +17,7 @@ from homeassistant.components.media_player import (
|
|||
ATTR_MEDIA_PLAYLIST, ATTR_MEDIA_SEASON, ATTR_MEDIA_SEEK_POSITION,
|
||||
ATTR_MEDIA_SERIES_TITLE, ATTR_MEDIA_TITLE, ATTR_MEDIA_TRACK,
|
||||
ATTR_MEDIA_VOLUME_LEVEL, ATTR_MEDIA_VOLUME_MUTED, ATTR_INPUT_SOURCE_LIST,
|
||||
ATTR_SUPPORTED_MEDIA_COMMANDS, ATTR_MEDIA_POSITION,
|
||||
ATTR_MEDIA_POSITION,
|
||||
ATTR_MEDIA_POSITION_UPDATED_AT, DOMAIN, SERVICE_PLAY_MEDIA,
|
||||
SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET,
|
||||
SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE, SUPPORT_CLEAR_PLAYLIST,
|
||||
|
@ -29,7 +29,7 @@ from homeassistant.const import (
|
|||
SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_SEEK, SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON, SERVICE_VOLUME_DOWN, SERVICE_VOLUME_MUTE,
|
||||
SERVICE_VOLUME_SET, SERVICE_VOLUME_UP, STATE_IDLE, STATE_OFF, STATE_ON,
|
||||
SERVICE_MEDIA_STOP)
|
||||
SERVICE_MEDIA_STOP, ATTR_SUPPORTED_FEATURES)
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
from homeassistant.helpers.service import async_call_from_config
|
||||
|
||||
|
@ -357,9 +357,9 @@ class UniversalMediaPlayer(MediaPlayerDevice):
|
|||
return self._override_or_child_attr(ATTR_INPUT_SOURCE_LIST)
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag media commands that are supported."""
|
||||
flags = self._child_attr(ATTR_SUPPORTED_MEDIA_COMMANDS) or 0
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
flags = self._child_attr(ATTR_SUPPORTED_FEATURES) or 0
|
||||
|
||||
if SERVICE_TURN_ON in self._cmds:
|
||||
flags |= SUPPORT_TURN_ON
|
||||
|
|
|
@ -97,8 +97,8 @@ class VlcDevice(MediaPlayerDevice):
|
|||
return self._muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return SUPPORT_VLC
|
||||
|
||||
@property
|
||||
|
|
|
@ -244,8 +244,8 @@ class LgWebOSDevice(MediaPlayerDevice):
|
|||
return None
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
if self._mac:
|
||||
return SUPPORT_WEBOSTV | SUPPORT_TURN_ON
|
||||
return SUPPORT_WEBOSTV
|
||||
|
|
|
@ -181,9 +181,9 @@ class YamahaDevice(MediaPlayerDevice):
|
|||
return self._source_list
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Flag of media commands that are supported."""
|
||||
supported_commands = SUPPORT_YAMAHA
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
supported_features = SUPPORT_YAMAHA
|
||||
|
||||
supports = self._playback_support
|
||||
mapping = {'play': (SUPPORT_PLAY | SUPPORT_PLAY_MEDIA),
|
||||
|
@ -193,8 +193,8 @@ class YamahaDevice(MediaPlayerDevice):
|
|||
'skip_r': SUPPORT_PREVIOUS_TRACK}
|
||||
for attr, feature in mapping.items():
|
||||
if getattr(supports, attr, False):
|
||||
supported_commands |= feature
|
||||
return supported_commands
|
||||
supported_features |= feature
|
||||
return supported_features
|
||||
|
||||
def turn_off(self):
|
||||
"""Turn off media player."""
|
||||
|
|
|
@ -286,6 +286,9 @@ ATTR_STATE = 'state'
|
|||
|
||||
ATTR_OPTION = 'option'
|
||||
|
||||
# Bitfield of supported component features for the entity
|
||||
ATTR_SUPPORTED_FEATURES = 'supported_features'
|
||||
|
||||
# #### SERVICES ####
|
||||
SERVICE_HOMEASSISTANT_STOP = 'stop'
|
||||
SERVICE_HOMEASSISTANT_RESTART = 'restart'
|
||||
|
|
|
@ -10,7 +10,7 @@ from homeassistant.const import (
|
|||
ATTR_ASSUMED_STATE, ATTR_FRIENDLY_NAME, ATTR_HIDDEN, ATTR_ICON,
|
||||
ATTR_UNIT_OF_MEASUREMENT, DEVICE_DEFAULT_NAME, STATE_OFF, STATE_ON,
|
||||
STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||
ATTR_ENTITY_PICTURE)
|
||||
ATTR_ENTITY_PICTURE, ATTR_SUPPORTED_FEATURES)
|
||||
from homeassistant.core import HomeAssistant, DOMAIN as CORE_DOMAIN
|
||||
from homeassistant.exceptions import NoEntitySpecifiedError
|
||||
from homeassistant.util import ensure_unique_string, slugify
|
||||
|
@ -148,6 +148,11 @@ class Entity(object):
|
|||
"""
|
||||
return False
|
||||
|
||||
@property
|
||||
def supported_features(self) -> int:
|
||||
"""Flag supported features."""
|
||||
return None
|
||||
|
||||
def update(self):
|
||||
"""Retrieve latest state.
|
||||
|
||||
|
@ -231,6 +236,8 @@ class Entity(object):
|
|||
self._attr_setter('entity_picture', str, ATTR_ENTITY_PICTURE, attr)
|
||||
self._attr_setter('hidden', bool, ATTR_HIDDEN, attr)
|
||||
self._attr_setter('assumed_state', bool, ATTR_ASSUMED_STATE, attr)
|
||||
self._attr_setter('supported_features', int, ATTR_SUPPORTED_FEATURES,
|
||||
attr)
|
||||
|
||||
end = timer()
|
||||
|
||||
|
|
|
@ -301,7 +301,7 @@ def test_put_light_state_fan(hass_hue, hue_client):
|
|||
blocking=True)
|
||||
|
||||
# Emulated hue converts 0-100% to 0-255.
|
||||
level = 23
|
||||
level = 43
|
||||
brightness = round(level * 255 / 100)
|
||||
|
||||
fan_result = yield from perform_put_light_state(
|
||||
|
|
|
@ -155,28 +155,28 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
state = self.hass.states.get(entity_id)
|
||||
assert 1 == state.attributes.get('media_track')
|
||||
assert 0 == (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
|
||||
mp.media_next_track(self.hass, entity_id)
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(entity_id)
|
||||
assert 2 == state.attributes.get('media_track')
|
||||
assert 0 < (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
|
||||
mp.media_next_track(self.hass, entity_id)
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(entity_id)
|
||||
assert 3 == state.attributes.get('media_track')
|
||||
assert 0 < (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
|
||||
mp.media_previous_track(self.hass, entity_id)
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(entity_id)
|
||||
assert 2 == state.attributes.get('media_track')
|
||||
assert 0 < (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
|
||||
assert setup_component(
|
||||
self.hass, mp.DOMAIN,
|
||||
|
@ -185,21 +185,21 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
state = self.hass.states.get(ent_id)
|
||||
assert 1 == state.attributes.get('media_episode')
|
||||
assert 0 == (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
|
||||
mp.media_next_track(self.hass, ent_id)
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 2 == state.attributes.get('media_episode')
|
||||
assert 0 < (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
|
||||
mp.media_previous_track(self.hass, ent_id)
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 1 == state.attributes.get('media_episode')
|
||||
assert 0 == (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
|
||||
@patch('homeassistant.components.media_player.demo.DemoYoutubePlayer.'
|
||||
'media_seek', autospec=True)
|
||||
|
@ -211,21 +211,21 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
ent_id = 'media_player.living_room'
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 0 < (mp.SUPPORT_PLAY_MEDIA &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
assert state.attributes.get('media_content_id') is not None
|
||||
|
||||
mp.play_media(self.hass, None, 'some_id', ent_id)
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 0 < (mp.SUPPORT_PLAY_MEDIA &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
assert not 'some_id' == state.attributes.get('media_content_id')
|
||||
|
||||
mp.play_media(self.hass, 'youtube', 'some_id', ent_id)
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 0 < (mp.SUPPORT_PLAY_MEDIA &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
state.attributes.get('supported_features'))
|
||||
assert 'some_id' == state.attributes.get('media_content_id')
|
||||
|
||||
assert not mock_seek.called
|
||||
|
|
|
@ -318,7 +318,7 @@ class TestSoundtouchMediaPlayer(unittest.TestCase):
|
|||
default_component(),
|
||||
mock.MagicMock())
|
||||
self.assertEqual(mocked_sountouch_device.call_count, 1)
|
||||
self.assertEqual(soundtouch.DEVICES[0].supported_media_commands, 17853)
|
||||
self.assertEqual(soundtouch.DEVICES[0].supported_features, 17853)
|
||||
|
||||
@mock.patch('libsoundtouch.device.SoundTouchDevice.power_off')
|
||||
@mock.patch('libsoundtouch.device.SoundTouchDevice.volume')
|
||||
|
|
|
@ -27,7 +27,7 @@ class MockMediaPlayer(media_player.MediaPlayerDevice):
|
|||
self._volume_level = 0
|
||||
self._is_volume_muted = False
|
||||
self._media_title = None
|
||||
self._supported_media_commands = 0
|
||||
self._supported_features = 0
|
||||
self._source = None
|
||||
self._tracks = 12
|
||||
self._media_image_url = None
|
||||
|
@ -91,9 +91,9 @@ class MockMediaPlayer(media_player.MediaPlayerDevice):
|
|||
return self._is_volume_muted
|
||||
|
||||
@property
|
||||
def supported_media_commands(self):
|
||||
"""Supported media commands flag."""
|
||||
return self._supported_media_commands
|
||||
def supported_features(self):
|
||||
"""Flag media player features that are supported."""
|
||||
return self._supported_features
|
||||
|
||||
@property
|
||||
def media_image_url(self):
|
||||
|
@ -502,7 +502,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.hass.states.set(self.mock_mute_switch_id, STATE_ON)
|
||||
self.assertTrue(ump.is_volume_muted)
|
||||
|
||||
def test_supported_media_commands_children_only(self):
|
||||
def test_supported_features_children_only(self):
|
||||
"""Test supported media commands with only children."""
|
||||
config = self.config_children_only
|
||||
universal.validate_config(config)
|
||||
|
@ -511,15 +511,15 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
|
||||
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
|
||||
|
||||
self.assertEqual(0, ump.supported_media_commands)
|
||||
self.assertEqual(0, ump.supported_features)
|
||||
|
||||
self.mock_mp_1._supported_media_commands = 512
|
||||
self.mock_mp_1._supported_features = 512
|
||||
self.mock_mp_1._state = STATE_PLAYING
|
||||
self.mock_mp_1.update_ha_state()
|
||||
run_coroutine_threadsafe(ump.async_update(), self.hass.loop).result()
|
||||
self.assertEqual(512, ump.supported_media_commands)
|
||||
self.assertEqual(512, ump.supported_features)
|
||||
|
||||
def test_supported_media_commands_children_and_cmds(self):
|
||||
def test_supported_features_children_and_cmds(self):
|
||||
"""Test supported media commands with children and attrs."""
|
||||
config = self.config_children_and_attr
|
||||
universal.validate_config(config)
|
||||
|
@ -543,7 +543,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
| universal.SUPPORT_VOLUME_STEP | universal.SUPPORT_VOLUME_MUTE \
|
||||
| universal.SUPPORT_SELECT_SOURCE
|
||||
|
||||
self.assertEqual(check_flags, ump.supported_media_commands)
|
||||
self.assertEqual(check_flags, ump.supported_features)
|
||||
|
||||
def test_service_call_no_active_child(self):
|
||||
"""Test a service call to children with no active child."""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue