Skip to content

Commit

Permalink
Support for the Orange Livebox Play TV appliance (home-assistant#5533)
Browse files Browse the repository at this point in the history
* Support for the Orage Livebox Play TV appliance

* Add liveboxplaytv to coveragerc

* Minor refactoring

* Update requirements

* Adjust comments

* Fix alignment

* Fix some coding-style issues highlighted by Travis CI

* The livebox play TV does not support playing media

* Lint: shorten line

* Remove unused callback function

* Remove redundant backslash

* Implement changes requested by balloob

* Don't error out if channel name or media url could not be retrieved

* Support current program (media title property)

* Remove unnecessary check

* Clean up: Remove another unnecessary check, _CONFIGURING variable and _playing attribute

* Update liveboxplaytv dependency to version 1.4.4

* Fix liveboxplaytv requirement

* Improve media state (support for playing and pause state)

* Update liveboxplaytv.py
  • Loading branch information
pschmitt authored and balloob committed Feb 3, 2017
1 parent f9ede73 commit 7506569
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 0 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ omit =
homeassistant/components/media_player/itunes.py
homeassistant/components/media_player/kodi.py
homeassistant/components/media_player/lg_netcast.py
homeassistant/components/media_player/liveboxplaytv.py
homeassistant/components/media_player/mpchc.py
homeassistant/components/media_player/mpd.py
homeassistant/components/media_player/nad.py
Expand Down
207 changes: 207 additions & 0 deletions homeassistant/components/media_player/liveboxplaytv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
"""
Support for interface with an Orange Livebox Play TV appliance.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.liveboxplaytv/
"""
import logging
from datetime import timedelta

import requests
import voluptuous as vol

import homeassistant.util as util
from homeassistant.components.media_player import (
SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_PLAY,
SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK,
SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_MUTE, SUPPORT_SELECT_SOURCE,
MEDIA_TYPE_CHANNEL, MediaPlayerDevice, PLATFORM_SCHEMA)
from homeassistant.const import (
CONF_HOST, CONF_PORT, STATE_ON, STATE_OFF, STATE_PLAYING,
STATE_PAUSED, STATE_UNKNOWN, CONF_NAME)
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = ['liveboxplaytv==1.4.7']

_LOGGER = logging.getLogger(__name__)

DEFAULT_NAME = 'Livebox Play TV'
DEFAULT_PORT = 8080

SUPPORT_LIVEBOXPLAYTV = SUPPORT_TURN_OFF | SUPPORT_TURN_ON | \
SUPPORT_NEXT_TRACK | SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | \
SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE | SUPPORT_SELECT_SOURCE | \
SUPPORT_PLAY

MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string
})


# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Orange Livebox Play TV platform."""
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
name = config.get(CONF_NAME)

add_devices([LiveboxPlayTvDevice(host, port, name)], True)


class LiveboxPlayTvDevice(MediaPlayerDevice):
"""Representation of an Orange Livebox Play TV."""

def __init__(self, host, port, name):
"""Initialize the Livebox Play TV device."""
from liveboxplaytv import LiveboxPlayTv
self._client = LiveboxPlayTv(host, port)
# Assume that the appliance is not muted
self._muted = False
# Assume that the TV is in Play mode
self._name = name
self._current_source = None
self._state = STATE_UNKNOWN
self._channel_list = {}
self._current_channel = None
self._current_program = None
self._media_image_url = None

@util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
def update(self):
"""Retrieve the latest data."""
try:
self._state = self.refresh_state()
# Update current channel
channel = self._client.get_current_channel()
if channel is not None:
self._current_program = self._client.program
self._current_channel = channel.get('name', None)
self._media_image_url = \
self._client.get_current_channel_image(img_size=300)
self.refresh_channel_list()
except requests.ConnectionError:
self._state = STATE_OFF

@property
def name(self):
"""Return the name of the device."""
return self._name

@property
def state(self):
"""Return the state of the device."""
return self._state

@property
def is_volume_muted(self):
"""Boolean if volume is currently muted."""
return self._muted

@property
def source(self):
"""Return the current input source."""
return self._current_channel

@property
def source_list(self):
"""List of available input sources."""
# Sort channels by tvIndex
return [self._channel_list[c] for c in
sorted(self._channel_list.keys())]

@property
def media_content_type(self):
"""Content type of current playing media."""
# return self._client.media_type
return MEDIA_TYPE_CHANNEL

@property
def media_image_url(self):
"""Image url of current playing media."""
return self._media_image_url

@property
def media_title(self):
"""Title of current playing media."""
if self._current_channel:
return '{}: {}'.format(self._current_channel,
self._current_program)

@property
def supported_media_commands(self):
"""Flag of media commands that are supported."""
return SUPPORT_LIVEBOXPLAYTV

def refresh_channel_list(self):
"""Refresh the list of available channels."""
new_channel_list = {}
# update channels
for channel in self._client.get_channels():
new_channel_list[int(channel['index'])] = channel['name']
self._channel_list = new_channel_list

def refresh_state(self):
"""Refresh the current media state."""
state = self._client.media_state
if state == 'PLAY':
return STATE_PLAYING
elif state == 'PAUSE':
return STATE_PAUSED
else:
return STATE_ON if self._client.is_on else STATE_OFF
return STATE_UNKNOWN

def turn_off(self):
"""Turn off media player."""
self._state = STATE_OFF
self._client.turn_off()

def turn_on(self):
"""Turn on the media player."""
self._state = STATE_ON
self._client.turn_on()

def volume_up(self):
"""Volume up the media player."""
self._client.volume_up()

def volume_down(self):
"""Volume down media player."""
self._client.volume_down()

def mute_volume(self, mute):
"""Send mute command."""
self._muted = mute
self._client.mute()

def media_play_pause(self):
"""Simulate play pause media player."""
self._client.play_pause()

def select_source(self, source):
"""Select input source."""
self._current_source = source
self._client.set_channel(source)

def media_play(self):
"""Send play command."""
self._state = STATE_PLAYING
self._client.play()

def media_pause(self):
"""Send media pause command to media player."""
self._state = STATE_PAUSED
self._client.pause()

def media_next_track(self):
"""Send next track command."""
self._client.channel_up()

def media_previous_track(self):
"""Send the previous track command."""
self._client.channel_down()
3 changes: 3 additions & 0 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ liffylights==0.9.4
# homeassistant.components.light.limitlessled
limitlessled==1.0.2

# homeassistant.components.media_player.liveboxplaytv
liveboxplaytv==1.4.7

# homeassistant.components.notify.matrix
matrix-client==0.0.5

Expand Down

0 comments on commit 7506569

Please sign in to comment.