Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Philips TVs with jointSPACE API #4157

Merged
merged 6 commits into from
Nov 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ omit =
homeassistant/components/media_player/onkyo.py
homeassistant/components/media_player/panasonic_viera.py
homeassistant/components/media_player/pandora.py
homeassistant/components/media_player/philips_js.py
homeassistant/components/media_player/pioneer.py
homeassistant/components/media_player/plex.py
homeassistant/components/media_player/roku.py
Expand Down
170 changes: 170 additions & 0 deletions homeassistant/components/media_player/philips_js.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
"""
Media Player component to integrate TVs exposing the Joint Space API.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.philips_js/
"""
import logging
from datetime import timedelta

import voluptuous as vol

from homeassistant.components.media_player import (
PLATFORM_SCHEMA, SUPPORT_SELECT_SOURCE, SUPPORT_TURN_OFF,
SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_MUTE, MediaPlayerDevice)
from homeassistant.const import (
STATE_ON, STATE_OFF, STATE_UNKNOWN, CONF_HOST, CONF_NAME)
from homeassistant.util import Throttle
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = ['ha-philipsjs==0.0.1']

_LOGGER = logging.getLogger(__name__)

MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)

SUPPORT_PHILIPS_JS = SUPPORT_TURN_OFF | SUPPORT_VOLUME_STEP | \
SUPPORT_VOLUME_MUTE | SUPPORT_SELECT_SOURCE

DEFAULT_DEVICE = 'default'
DEFAULT_HOST = '127.0.0.1'
DEFAULT_NAME = 'Philips TV'
BASE_URL = 'http://{0}:1925/1/{1}'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST, default=DEFAULT_HOST): cv.string,
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 Philips TV platform."""
import haphilipsjs

name = config.get(CONF_NAME)
host = config.get(CONF_HOST)

tvapi = haphilipsjs.PhilipsTV(host)

add_devices([PhilipsTV(tvapi, name)])


# pylint: disable=abstract-method
class PhilipsTV(MediaPlayerDevice):
"""Representation of a Philips TV exposing the JointSpace API."""

def __init__(self, tv, name):
"""Initialize the Philips TV."""
self._tv = tv
self._name = name
self._state = STATE_UNKNOWN
self._min_volume = None
self._max_volume = None
self._volume = None
self._muted = False
self._program_name = None
self._channel_name = None
self._source = None
self._source_list = []
self._connfail = 0
self._source_mapping = {}

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

@property
def should_poll(self):
"""Device should be polled."""
return True

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

@property
def state(self):
"""Get the device state. An exception means OFF state."""
return self._state

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

@property
def source_list(self):
"""List of available input sources."""
return self._source_list

def select_source(self, source):
"""Set the input source."""
if source in self._source_mapping:
self._tv.setSource(self._source_mapping.get(source))
self._source = source
if not self._tv.on:
self._state = STATE_OFF

@property
def volume_level(self):
"""Volume level of the media player (0..1)."""
return self._volume

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

def turn_off(self):
"""Turn off the device."""
self._tv.sendKey('Standby')
if not self._tv.on:
self._state = STATE_OFF

def volume_up(self):
"""Send volume up command."""
self._tv.sendKey('VolumeUp')
if not self._tv.on:
self._state = STATE_OFF

def volume_down(self):
"""Send volume down command."""
self._tv.sendKey('VolumeDown')
if not self._tv.on:
self._state = STATE_OFF

def mute_volume(self, mute):
"""Send mute command."""
self._tv.sendKey('Mute')
if not self._tv.on:
self._state = STATE_OFF

@property
def media_title(self):
"""Title of current playing media."""
return self._source

@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
"""Get the latest data and update device state."""
self._tv.update()
self._min_volume = self._tv.min_volume
self._max_volume = self._tv.max_volume
self._volume = self._tv.volume
self._muted = self._tv.muted
if self._tv.source_id:
src = self._tv.sources.get(self._tv.source_id, None)
if src:
self._source = src.get('name', None)
if self._tv.sources and not self._source_list:
for srcid in sorted(self._tv.sources):
srcname = self._tv.sources.get(srcid, dict()).get('name', None)
self._source_list.append(srcname)
self._source_mapping[srcname] = srcid
if self._tv.on:
self._state = STATE_ON
else:
self._state = STATE_OFF
3 changes: 3 additions & 0 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ ha-alpr==0.3
# homeassistant.components.ffmpeg
ha-ffmpeg==0.15

# homeassistant.components.media_player.philips_js
ha-philipsjs==0.0.1

# homeassistant.components.mqtt.server
hbmqtt==0.7.1

Expand Down