Proxy requests to the media player's media image (#2693)
This is needed when the media server and UI client are not on the same network.
This commit is contained in:
parent
e36c6b24ee
commit
bb22ad3064
2 changed files with 92 additions and 7 deletions
|
@ -6,6 +6,7 @@ https://home-assistant.io/components/media_player/
|
|||
"""
|
||||
import logging
|
||||
import os
|
||||
import requests
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -13,6 +14,7 @@ from homeassistant.config import load_yaml_config_file
|
|||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
|
||||
from homeassistant.components.http import HomeAssistantView
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.const import (
|
||||
STATE_OFF, STATE_UNKNOWN, STATE_PLAYING, STATE_IDLE,
|
||||
|
@ -25,10 +27,13 @@ from homeassistant.const import (
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = 'media_player'
|
||||
DEPENDENCIES = ['http']
|
||||
SCAN_INTERVAL = 10
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
|
||||
ENTITY_IMAGE_URL = '/api/media_player_proxy/{0}?token={1}'
|
||||
|
||||
SERVICE_PLAY_MEDIA = 'play_media'
|
||||
SERVICE_SELECT_SOURCE = 'select_source'
|
||||
SERVICE_CLEAR_PLAYLIST = 'clear_playlist'
|
||||
|
@ -286,6 +291,8 @@ def setup(hass, config):
|
|||
component = EntityComponent(
|
||||
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
|
||||
|
||||
hass.wsgi.register_view(MediaPlayerImageView(hass, component.entities))
|
||||
|
||||
component.setup(config)
|
||||
|
||||
descriptions = load_yaml_config_file(
|
||||
|
@ -398,6 +405,11 @@ class MediaPlayerDevice(Entity):
|
|||
"""State of the player."""
|
||||
return STATE_UNKNOWN
|
||||
|
||||
@property
|
||||
def access_token(self):
|
||||
"""Access token for this media player."""
|
||||
return str(id(self))
|
||||
|
||||
@property
|
||||
def volume_level(self):
|
||||
"""Volume level of the media player (0..1)."""
|
||||
|
@ -633,7 +645,8 @@ class MediaPlayerDevice(Entity):
|
|||
@property
|
||||
def entity_picture(self):
|
||||
"""Return image of the media playing."""
|
||||
return None if self.state == STATE_OFF else self.media_image_url
|
||||
return None if self.state == STATE_OFF else \
|
||||
ENTITY_IMAGE_URL.format(self.entity_id, self.access_token)
|
||||
|
||||
@property
|
||||
def state_attributes(self):
|
||||
|
@ -649,3 +662,35 @@ class MediaPlayerDevice(Entity):
|
|||
}
|
||||
|
||||
return state_attr
|
||||
|
||||
|
||||
class MediaPlayerImageView(HomeAssistantView):
|
||||
"""Media player view to serve an image."""
|
||||
|
||||
url = "/api/media_player_proxy/<entity(domain=media_player):entity_id>"
|
||||
name = "api:media_player:image"
|
||||
|
||||
def __init__(self, hass, entities):
|
||||
"""Initialize a media player view."""
|
||||
super().__init__(hass)
|
||||
self.entities = entities
|
||||
|
||||
def get(self, request, entity_id):
|
||||
"""Start a get request."""
|
||||
player = self.entities.get(entity_id)
|
||||
|
||||
if player is None:
|
||||
return self.Response(status=404)
|
||||
|
||||
authenticated = (request.authenticated or
|
||||
request.args.get('token') == player.access_token)
|
||||
|
||||
if not authenticated:
|
||||
return self.Response(status=401)
|
||||
|
||||
response = requests.get(player.media_image_url)
|
||||
|
||||
if response is None:
|
||||
return self.Response(status=500)
|
||||
|
||||
return self.Response(response)
|
||||
|
|
|
@ -1,23 +1,50 @@
|
|||
"""The tests for the Demo Media player platform."""
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from homeassistant import bootstrap
|
||||
import homeassistant.components.media_player as mp
|
||||
import homeassistant.components.http as http
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
import requests
|
||||
import requests_mock
|
||||
import time
|
||||
|
||||
from tests.common import get_test_home_assistant, get_test_instance_port
|
||||
|
||||
SERVER_PORT = get_test_instance_port()
|
||||
HTTP_BASE_URL = 'http://127.0.0.1:{}'.format(SERVER_PORT)
|
||||
|
||||
hass = None
|
||||
|
||||
entity_id = 'media_player.walkman'
|
||||
|
||||
|
||||
def setUpModule(): # pylint: disable=invalid-name
|
||||
"""Initalize a Home Assistant server."""
|
||||
global hass
|
||||
|
||||
hass = get_test_home_assistant()
|
||||
bootstrap.setup_component(hass, http.DOMAIN, {
|
||||
http.DOMAIN: {
|
||||
http.CONF_SERVER_PORT: SERVER_PORT
|
||||
},
|
||||
})
|
||||
|
||||
hass.start()
|
||||
time.sleep(0.05)
|
||||
|
||||
|
||||
def tearDownModule(): # pylint: disable=invalid-name
|
||||
"""Stop the Home Assistant server."""
|
||||
hass.stop()
|
||||
|
||||
|
||||
class TestDemoMediaPlayer(unittest.TestCase):
|
||||
"""Test the media_player module."""
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
self.hass = hass
|
||||
|
||||
def test_source_select(self):
|
||||
"""Test the input source service."""
|
||||
|
@ -175,6 +202,19 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
assert 0 == (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
|
||||
@requests_mock.Mocker(real_http=True)
|
||||
def test_media_image_proxy(self, m):
|
||||
"""Test the media server image proxy server ."""
|
||||
fake_picture_data = 'test.test'
|
||||
m.get('https://graph.facebook.com/v2.5/107771475912710/'
|
||||
'picture?type=large', text=fake_picture_data)
|
||||
assert mp.setup(self.hass, {'media_player': {'platform': 'demo'}})
|
||||
assert self.hass.states.is_state(entity_id, 'playing')
|
||||
state = self.hass.states.get(entity_id)
|
||||
req = requests.get(HTTP_BASE_URL +
|
||||
state.attributes.get('entity_picture'))
|
||||
assert req.text == fake_picture_data
|
||||
|
||||
@patch('homeassistant.components.media_player.demo.DemoYoutubePlayer.'
|
||||
'media_seek')
|
||||
def test_play_media(self, mock_seek):
|
||||
|
|
Loading…
Add table
Reference in a new issue