core/homeassistant/components/media_player/firetv.py

189 lines
6.1 KiB
Python
Raw Normal View History

2015-10-09 01:07:36 +00:00
"""
2016-03-08 09:34:33 +00:00
Support for functionality to interact with FireTV devices.
2015-10-09 01:07:36 +00:00
2015-10-23 17:01:19 +00:00
For more details about this platform, please refer to the documentation at
2015-11-09 12:12:18 +00:00
https://home-assistant.io/components/media_player.firetv/
2015-10-09 01:07:36 +00:00
"""
2015-10-10 20:45:13 +00:00
import logging
2015-10-09 01:07:36 +00:00
2016-02-19 05:27:50 +00:00
import requests
2016-09-05 15:40:57 +00:00
import voluptuous as vol
2015-10-09 01:07:36 +00:00
from homeassistant.components.media_player import (
2016-09-05 15:40:57 +00:00
SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, PLATFORM_SCHEMA,
SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_VOLUME_SET, SUPPORT_PLAY,
MediaPlayerDevice)
2016-02-19 05:27:50 +00:00
from homeassistant.const import (
STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING, STATE_STANDBY,
STATE_UNKNOWN, CONF_HOST, CONF_PORT, CONF_SSL, CONF_NAME, CONF_DEVICE,
CONF_DEVICES)
2016-09-05 15:40:57 +00:00
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
2015-10-09 01:07:36 +00:00
SUPPORT_FIRETV = SUPPORT_PAUSE | \
SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PREVIOUS_TRACK | \
SUPPORT_NEXT_TRACK | SUPPORT_VOLUME_SET | SUPPORT_PLAY
2015-10-09 01:07:36 +00:00
DEFAULT_SSL = False
2016-09-05 15:40:57 +00:00
DEFAULT_DEVICE = 'default'
DEFAULT_HOST = 'localhost'
DEFAULT_NAME = 'Amazon Fire TV'
DEFAULT_PORT = 5556
DEVICE_ACTION_URL = '{0}://{1}:{2}/devices/action/{3}/{4}'
DEVICE_LIST_URL = '{0}://{1}:{2}/devices/list'
DEVICE_STATE_URL = '{0}://{1}:{2}/devices/state/{3}'
2015-10-10 20:45:13 +00:00
2016-09-05 15:40:57 +00:00
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_DEVICE, default=DEFAULT_DEVICE): cv.string,
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
2016-09-05 15:40:57 +00:00
})
2015-10-09 01:07:36 +00:00
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the FireTV platform."""
2016-09-05 15:40:57 +00:00
name = config.get(CONF_NAME)
ssl = config.get(CONF_SSL)
proto = 'https' if ssl else 'http'
2016-09-05 15:40:57 +00:00
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
device_id = config.get(CONF_DEVICE)
2015-10-10 20:45:13 +00:00
try:
response = requests.get(
DEVICE_LIST_URL.format(proto, host, port)).json()
2016-09-05 15:40:57 +00:00
if device_id in response[CONF_DEVICES].keys():
add_devices([FireTVDevice(proto, host, port, device_id, name)])
_LOGGER.info("Device %s accessible and ready for control",
2016-09-05 15:40:57 +00:00
device_id)
2015-10-10 20:45:13 +00:00
else:
_LOGGER.warning("Device %s is not registered with firetv-server",
2016-09-05 15:40:57 +00:00
device_id)
2015-10-10 20:45:13 +00:00
except requests.exceptions.RequestException:
_LOGGER.error("Could not connect to firetv-server at %s", host)
2015-10-09 01:07:36 +00:00
class FireTV(object):
2016-03-08 09:34:33 +00:00
"""The firetv-server client.
2015-10-09 01:07:36 +00:00
2015-10-23 17:01:19 +00:00
Should a native Python 3 ADB module become available, python-firetv can
support Python 3, it can be added as a dependency, and this class can be
dispensed of.
2015-10-09 01:07:36 +00:00
2015-10-23 17:01:19 +00:00
For now, it acts as a client to the firetv-server HTTP server (which must
be running via Python 2).
2015-10-09 01:07:36 +00:00
"""
def __init__(self, proto, host, port, device_id):
2016-03-08 09:34:33 +00:00
"""Initialize the FireTV server."""
self.proto = proto
2015-10-09 01:07:36 +00:00
self.host = host
2016-09-05 15:40:57 +00:00
self.port = port
2015-10-09 01:07:36 +00:00
self.device_id = device_id
@property
def state(self):
2016-03-08 09:34:33 +00:00
"""Get the device state. An exception means UNKNOWN state."""
2015-10-09 01:07:36 +00:00
try:
response = requests.get(
2015-10-10 20:45:13 +00:00
DEVICE_STATE_URL.format(
self.proto, self.host, self.port, self.device_id
), timeout=10).json()
2015-10-10 20:45:13 +00:00
return response.get('state', STATE_UNKNOWN)
2015-10-09 01:07:36 +00:00
except requests.exceptions.RequestException:
2015-10-10 20:45:13 +00:00
_LOGGER.error(
"Could not retrieve device state for %s", self.device_id)
2015-10-09 01:07:36 +00:00
return STATE_UNKNOWN
def action(self, action_id):
2016-03-08 09:34:33 +00:00
"""Perform an action on the device."""
2015-10-09 01:07:36 +00:00
try:
2016-09-05 15:40:57 +00:00
requests.get(DEVICE_ACTION_URL.format(
self.proto, self.host, self.port, self.device_id, action_id
), timeout=10)
2015-10-09 01:07:36 +00:00
except requests.exceptions.RequestException:
2015-10-10 20:45:13 +00:00
_LOGGER.error(
"Action request for %s was not accepted for device %s",
2015-10-10 20:45:13 +00:00
action_id, self.device_id)
2015-10-09 01:07:36 +00:00
class FireTVDevice(MediaPlayerDevice):
2016-03-08 09:34:33 +00:00
"""Representation of an Amazon Fire TV device on the network."""
2015-10-09 01:07:36 +00:00
def __init__(self, proto, host, port, device, name):
2016-03-08 09:34:33 +00:00
"""Initialize the FireTV device."""
self._firetv = FireTV(proto, host, port, device)
2015-10-09 01:07:36 +00:00
self._name = name
2015-10-10 20:45:13 +00:00
self._state = STATE_UNKNOWN
2015-10-09 01:07:36 +00:00
@property
def name(self):
2016-03-08 09:34:33 +00:00
"""Return the device name."""
2015-10-09 01:07:36 +00:00
return self._name
@property
def should_poll(self):
2016-03-08 09:34:33 +00:00
"""Device should be polled."""
2015-10-09 01:07:36 +00:00
return True
@property
def supported_features(self):
"""Flag media player features that are supported."""
2015-10-09 01:07:36 +00:00
return SUPPORT_FIRETV
@property
def state(self):
2016-03-08 09:34:33 +00:00
"""Return the state of the player."""
2015-10-10 20:45:13 +00:00
return self._state
def update(self):
2016-03-08 09:34:33 +00:00
"""Get the latest date and update device state."""
2015-10-10 20:45:13 +00:00
self._state = {
2015-10-09 01:07:36 +00:00
'idle': STATE_IDLE,
'off': STATE_OFF,
'play': STATE_PLAYING,
'pause': STATE_PAUSED,
'standby': STATE_STANDBY,
'disconnected': STATE_UNKNOWN,
2015-10-10 20:45:13 +00:00
}.get(self._firetv.state, STATE_UNKNOWN)
2015-10-09 01:07:36 +00:00
def turn_on(self):
2016-03-08 09:34:33 +00:00
"""Turn on the device."""
2015-10-09 01:07:36 +00:00
self._firetv.action('turn_on')
def turn_off(self):
2016-03-08 09:34:33 +00:00
"""Turn off the device."""
2015-10-09 01:07:36 +00:00
self._firetv.action('turn_off')
def media_play(self):
2016-03-08 09:34:33 +00:00
"""Send play command."""
2015-10-09 01:07:36 +00:00
self._firetv.action('media_play')
def media_pause(self):
2016-03-08 09:34:33 +00:00
"""Send pause command."""
2015-10-09 01:07:36 +00:00
self._firetv.action('media_pause')
def media_play_pause(self):
2016-03-08 09:34:33 +00:00
"""Send play/pause command."""
2015-10-09 01:07:36 +00:00
self._firetv.action('media_play_pause')
def volume_up(self):
2016-03-08 09:34:33 +00:00
"""Send volume up command."""
2015-10-09 01:07:36 +00:00
self._firetv.action('volume_up')
def volume_down(self):
2016-03-08 09:34:33 +00:00
"""Send volume down command."""
2015-10-09 01:07:36 +00:00
self._firetv.action('volume_down')
def media_previous_track(self):
2016-03-08 09:34:33 +00:00
"""Send previous track command (results in rewind)."""
2015-10-09 01:07:36 +00:00
self._firetv.action('media_previous')
def media_next_track(self):
2016-03-08 09:34:33 +00:00
"""Send next track command (results in fast-forward)."""
2015-10-09 01:07:36 +00:00
self._firetv.action('media_next')