diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 143473e2fde..294fccbb1f5 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -31,6 +31,7 @@ DISCOVERY_PLATFORMS = { } SERVICE_YOUTUBE_VIDEO = 'play_youtube_video' +SERVICE_PLAY_MEDIA = 'play_media' ATTR_MEDIA_VOLUME_LEVEL = 'volume_level' ATTR_MEDIA_VOLUME_MUTED = 'is_volume_muted' @@ -46,6 +47,8 @@ ATTR_MEDIA_TRACK = 'media_track' ATTR_MEDIA_SERIES_TITLE = 'media_series_title' ATTR_MEDIA_SEASON = 'media_season' ATTR_MEDIA_EPISODE = 'media_episode' +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' @@ -53,6 +56,9 @@ ATTR_SUPPORTED_MEDIA_COMMANDS = 'supported_media_commands' MEDIA_TYPE_MUSIC = 'music' MEDIA_TYPE_TVSHOW = 'tvshow' MEDIA_TYPE_VIDEO = 'movie' +MEDIA_TYPE_EPISODE = 'episode' +MEDIA_TYPE_CHANNEL = 'channel' +MEDIA_TYPE_PLAYLIST = 'playlist' SUPPORT_PAUSE = 1 SUPPORT_SEEK = 2 @@ -63,6 +69,7 @@ SUPPORT_NEXT_TRACK = 32 SUPPORT_YOUTUBE = 64 SUPPORT_TURN_ON = 128 SUPPORT_TURN_OFF = 256 +SUPPORT_PLAY_MEDIA = 512 YOUTUBE_COVER_URL_FORMAT = 'https://img.youtube.com/vi/{}/1.jpg' @@ -76,6 +83,7 @@ SERVICE_TO_METHOD = { SERVICE_MEDIA_PAUSE: 'media_pause', SERVICE_MEDIA_NEXT_TRACK: 'media_next_track', SERVICE_MEDIA_PREVIOUS_TRACK: 'media_previous_track', + SERVICE_PLAY_MEDIA: 'play_media', } ATTR_TO_PROPERTY = [ @@ -92,6 +100,8 @@ ATTR_TO_PROPERTY = [ ATTR_MEDIA_SERIES_TITLE, ATTR_MEDIA_SEASON, ATTR_MEDIA_EPISODE, + ATTR_MEDIA_CHANNEL, + ATTR_MEDIA_PLAYLIST, ATTR_APP_ID, ATTR_APP_NAME, ATTR_SUPPORTED_MEDIA_COMMANDS, @@ -180,6 +190,16 @@ def media_previous_track(hass, entity_id=None): hass.services.call(DOMAIN, SERVICE_MEDIA_PREVIOUS_TRACK, data) +def play_media(hass, media_type, media_id, entity_id=None): + """ Send the media player the command for playing media. """ + data = {"media_type": media_type, "media_id": media_id} + + if entity_id: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_PLAY_MEDIA, data) + + def setup(hass, config): """ Track states and offer events for media_players. """ component = EntityComponent( @@ -275,6 +295,23 @@ def setup(hass, config): if player.should_poll: player.update_ha_state(True) + def play_media_service(service): + """ Plays specified media_id on the media player. """ + media_type = service.data.get('media_type') + media_id = service.data.get('media_id') + + if media_type is None: + return + + if media_id is None: + return + + for player in component.extract_from_service(service): + player.play_media(media_type, media_id) + + if player.should_poll: + player.update_ha_state(True) + hass.services.register( DOMAIN, "start_fireplace", lambda service: play_youtube_video_service(service, "eyU3bRy2x44"), @@ -289,6 +326,10 @@ def setup(hass, config): DOMAIN, SERVICE_YOUTUBE_VIDEO, play_youtube_video_service, descriptions.get(SERVICE_YOUTUBE_VIDEO)) + hass.services.register( + DOMAIN, SERVICE_PLAY_MEDIA, play_media_service, + descriptions.get(SERVICE_PLAY_MEDIA)) + return True @@ -373,6 +414,16 @@ class MediaPlayerDevice(Entity): """ Episode of current playing media. (TV Show only) """ return None + @property + def media_channel(self): + """ Channel currently playing. """ + return None + + @property + def media_playlist(self): + """ Title of Playlist currently playing. """ + return None + @property def app_id(self): """ ID of the current running app. """ @@ -433,6 +484,10 @@ class MediaPlayerDevice(Entity): """ Plays a YouTube media. """ raise NotImplementedError() + def play_media(self, media_type, media_id): + """ Plays a piece of media. """ + raise NotImplementedError() + # No need to overwrite these. @property def support_pause(self): @@ -469,6 +524,11 @@ class MediaPlayerDevice(Entity): """ Boolean if YouTube is supported. """ return bool(self.supported_media_commands & SUPPORT_YOUTUBE) + @property + def support_play_media(self): + """ Boolean if play media command supported. """ + return bool(self.supported_media_commands & SUPPORT_PLAY_MEDIA) + def volume_up(self): """ volume_up media player. """ if self.volume_level < 1: diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 61223446e5f..6f622c9e0cc 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -90,6 +90,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class CastDevice(MediaPlayerDevice): """ Represents a Cast device on the network. """ + # pylint: disable=abstract-method # pylint: disable=too-many-public-methods def __init__(self, host): diff --git a/homeassistant/components/notify/smtp.py b/homeassistant/components/notify/smtp.py index ee2413eda30..fbddd8d1d26 100644 --- a/homeassistant/components/notify/smtp.py +++ b/homeassistant/components/notify/smtp.py @@ -1,15 +1,15 @@ """ -homeassistant.components.notify.mail +homeassistant.components.notify.smtp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mail (SMTP) notification service. Configuration: -To use the Mail notifier you will need to add something like the following +To use the smtp notifier you will need to add something like the following to your configuration.yaml file. notify: - platform: mail + platform: smtp server: MAIL_SERVER port: YOUR_SMTP_PORT sender: SENDER_EMAIL_ADDRESS diff --git a/homeassistant/const.py b/homeassistant/const.py index 2d272ca3a0b..35e3e2c93ae 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """ Constants used by Home Assistant components. """ -__version__ = "0.7.4" +__version__ = "0.7.5dev0" # Can be used to specify a catch all when registering state or event listeners. MATCH_ALL = '*' diff --git a/homeassistant/helpers/state.py b/homeassistant/helpers/state.py index 909b86a67ed..6526fe2d90b 100644 --- a/homeassistant/helpers/state.py +++ b/homeassistant/helpers/state.py @@ -13,6 +13,8 @@ from homeassistant.const import ( SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PAUSE, STATE_PLAYING, STATE_PAUSED, ATTR_ENTITY_ID) +from homeassistant.components.media_player import (SERVICE_PLAY_MEDIA) + _LOGGER = logging.getLogger(__name__) @@ -61,6 +63,10 @@ def reproduce_state(hass, states, blocking=False): service = SERVICE_MEDIA_PAUSE elif state.domain == 'media_player' and state.state == STATE_PLAYING: service = SERVICE_MEDIA_PLAY + elif state.domain == 'media_player' and state.attributes and \ + 'media_type' in state.attributes and \ + 'media_id' in state.attributes: + service = SERVICE_PLAY_MEDIA elif state.state == STATE_ON: service = SERVICE_TURN_ON elif state.state == STATE_OFF: diff --git a/tests/components/test_media_player.py b/tests/components/test_media_player.py index 28d39206c47..211626ea3fb 100644 --- a/tests/components/test_media_player.py +++ b/tests/components/test_media_player.py @@ -40,7 +40,7 @@ class TestMediaPlayer(unittest.TestCase): def test_services(self): """ - Test if the call service methods conver to correct service calls. + Test if the call service methods convert to correct service calls. """ services = { SERVICE_TURN_ON: media_player.turn_on,