From 46274d4393895fb8ca2fe048ba77adaa74bd1f55 Mon Sep 17 00:00:00 2001 From: Dennis Karpienski Date: Tue, 19 Apr 2016 17:53:58 +0200 Subject: [PATCH] add media_player webos tv platform (#1853) * added webos tv platform * moved coverage entries --- .coveragerc | 5 +- .../www_static/images/config_webos.png | Bin 0 -> 22848 bytes .../components/media_player/webostv.py | 249 ++++++++++++++++++ homeassistant/components/notify/webostv.py | 62 +++++ requirements_all.txt | 3 + 5 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/frontend/www_static/images/config_webos.png create mode 100644 homeassistant/components/media_player/webostv.py create mode 100644 homeassistant/components/notify/webostv.py diff --git a/.coveragerc b/.coveragerc index 5e3dc0978ee..1c7b05c7d24 100644 --- a/.coveragerc +++ b/.coveragerc @@ -68,6 +68,10 @@ omit = homeassistant/components/upnp.py homeassistant/components/zeroconf.py + homeassistant/components/*/thinkingcleaner.py + + homeassistant/components/*/webostv.py + homeassistant/components/binary_sensor/arest.py homeassistant/components/binary_sensor/rest.py homeassistant/components/browser.py @@ -179,7 +183,6 @@ omit = homeassistant/components/thermostat/homematic.py homeassistant/components/thermostat/proliphix.py homeassistant/components/thermostat/radiotherm.py - homeassistant/components/*/thinkingcleaner.py [report] diff --git a/homeassistant/components/frontend/www_static/images/config_webos.png b/homeassistant/components/frontend/www_static/images/config_webos.png new file mode 100644 index 0000000000000000000000000000000000000000..757aec76270b50d9f7415b840d916fbc2071a76b GIT binary patch literal 22848 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 W`Aizpf&L5(3=E#GelF{r5}E*MpCFR} literal 0 HcmV?d00001 diff --git a/homeassistant/components/media_player/webostv.py b/homeassistant/components/media_player/webostv.py new file mode 100644 index 00000000000..2e22e7daf31 --- /dev/null +++ b/homeassistant/components/media_player/webostv.py @@ -0,0 +1,249 @@ +""" +Support for interface with an LG WebOS TV. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/media_player.webostv/ +""" +import logging +from datetime import timedelta +from urllib.parse import urlparse + +import homeassistant.util as util +from homeassistant.components.media_player import ( + SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, + SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + SUPPORT_SELECT_SOURCE, SUPPORT_PLAY_MEDIA, MEDIA_TYPE_CHANNEL, + MediaPlayerDevice) +from homeassistant.const import ( + CONF_HOST, STATE_OFF, STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN) +from homeassistant.loader import get_component + +_CONFIGURING = {} +_LOGGER = logging.getLogger(__name__) + +REQUIREMENTS = ['https://github.com/TheRealLink/pylgtv' + '/archive/v0.1.1.zip' + '#pylgtv==0.1.1'] + +SUPPORT_WEBOSTV = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \ + SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | \ + SUPPORT_NEXT_TRACK | SUPPORT_TURN_OFF | \ + SUPPORT_SELECT_SOURCE | SUPPORT_PLAY_MEDIA + +MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) +MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the LG WebOS TV platform.""" + if discovery_info is not None: + host = urlparse(discovery_info[1]).hostname + else: + host = config.get(CONF_HOST, None) + + if host is None: + _LOGGER.error('No host found in configuration') + return False + + # Only act if we are not already configuring this host + if host in _CONFIGURING: + return + + setup_tv(host, hass, add_devices) + + +def setup_tv(host, hass, add_devices): + """Setup a phue bridge based on host parameter.""" + from pylgtv import WebOsClient + from pylgtv import PyLGTVPairException + + client = WebOsClient(host) + + if not client.is_registered(): + if host in _CONFIGURING: + # Try to pair. + try: + client.register() + except PyLGTVPairException: + _LOGGER.warning( + 'Connected to LG WebOS TV at %s but not paired.', host) + return + except ConnectionRefusedError: + _LOGGER.error('Unable to connect to host %s.', host) + return + else: + # Not registered, request configuration. + _LOGGER.warning('LG WebOS TV at %s needs to be paired.', host) + request_configuration(host, hass, add_devices) + return + + # If we came here and configuring this host, mark as done. + if client.is_registered() and host in _CONFIGURING: + request_id = _CONFIGURING.pop(host) + configurator = get_component('configurator') + configurator.request_done(request_id) + + add_devices([LgWebOSDevice(host)]) + + +def request_configuration(host, hass, add_devices): + """Request configuration steps from the user.""" + configurator = get_component('configurator') + + # We got an error if this method is called while we are configuring + if host in _CONFIGURING: + configurator.notify_errors( + _CONFIGURING[host], 'Failed to pair, please try again.') + return + + # pylint: disable=unused-argument + def lgtv_configuration_callback(data): + """The actions to do when our configuration callback is called.""" + setup_tv(host, hass, add_devices) + + _CONFIGURING[host] = configurator.request_config( + hass, 'LG WebOS TV', lgtv_configuration_callback, + description='Click start and accept the pairing request on your tv.', + description_image='/static/images/config_webos.png', + submit_caption='Start pairing request' + ) + + +# pylint: disable=abstract-method +# pylint: disable=too-many-instance-attributes +class LgWebOSDevice(MediaPlayerDevice): + """Representation of a LG WebOS TV.""" + + # pylint: disable=too-many-public-methods + def __init__(self, host): + """Initialize the webos device.""" + from pylgtv import WebOsClient + self._client = WebOsClient(host) + + self._name = 'LG WebOS TV Remote' + # Assume that the TV is not muted + self._muted = False + # Assume that the TV is in Play mode + self._playing = True + self._volume = 0 + self._current_source = None + self._current_source_id = None + self._source_list = None + self._state = STATE_UNKNOWN + self._app_list = None + + self.update() + + @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) + def update(self): + """Retrieve the latest data.""" + try: + self._state = STATE_PLAYING + self._muted = self._client.get_muted() + self._volume = self._client.get_volume() + self._current_source_id = self._client.get_input() + + self._source_list = [] + self._app_list = {} + for app in self._client.get_apps(): + self._app_list[app['id']] = app + self._source_list.append(app['title']) + if app['id'] == self._current_source_id: + self._current_source = app['title'] + + except ConnectionRefusedError: + 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 volume_level(self): + """Volume level of the media player (0..1).""" + return self._volume / 100.0 + + @property + def source(self): + """Return the current input source.""" + return self._current_source + + @property + def source_list(self): + """List of available input sources.""" + return self._source_list + + @property + def media_content_type(self): + """Content type of current playing media.""" + return MEDIA_TYPE_CHANNEL + + @property + def media_image_url(self): + """Image url of current playing media.""" + return self._app_list[self._current_source_id]['icon'] + + @property + def supported_media_commands(self): + """Flag of media commands that are supported.""" + return SUPPORT_WEBOSTV + + def turn_off(self): + """Turn off media player.""" + self._client.power_off() + + 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 set_volume_level(self, volume): + """Set volume level, range 0..1.""" + tv_volume = volume * 100 + self._client.set_volume(tv_volume) + + def mute_volume(self, mute): + """Send mute command.""" + self._client.set_mute(mute) + + def media_play_pause(self): + """Simulate play pause media player.""" + if self._playing: + self.media_pause() + else: + self.media_play() + + def media_play(self): + """Send play command.""" + self._playing = True + self._state = STATE_PLAYING + self._client.play() + + def media_pause(self): + """Send media pause command to media player.""" + self._playing = False + self._state = STATE_PAUSED + self._client.pause() + + def media_next_track(self): + """Send next track command.""" + self._client.fast_forward() + + def media_previous_track(self): + """Send the previous track command.""" + self._client.rewind() diff --git a/homeassistant/components/notify/webostv.py b/homeassistant/components/notify/webostv.py new file mode 100644 index 00000000000..fb6cf02c9c5 --- /dev/null +++ b/homeassistant/components/notify/webostv.py @@ -0,0 +1,62 @@ +""" +LG WebOS TV notification service. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.webostv/ +""" +import logging + +from homeassistant.components.notify import (BaseNotificationService, DOMAIN) +from homeassistant.const import (CONF_HOST, CONF_NAME) +from homeassistant.helpers import validate_config + +_LOGGER = logging.getLogger(__name__) + + +def get_service(hass, config): + """Return the notify service.""" + if not validate_config({DOMAIN: config}, {DOMAIN: [CONF_HOST, CONF_NAME]}, + _LOGGER): + return None + + host = config.get(CONF_HOST, None) + + if not host: + _LOGGER.error('No host provided.') + return None + + from pylgtv import WebOsClient + from pylgtv import PyLGTVPairException + + client = WebOsClient(host) + + try: + client.register() + except PyLGTVPairException: + _LOGGER.error('Pairing failed.') + return None + except ConnectionRefusedError: + _LOGGER.error('Host unreachable.') + return None + + return LgWebOSNotificationService(client) + + +# pylint: disable=too-few-public-methods +class LgWebOSNotificationService(BaseNotificationService): + """Implement the notification service for LG WebOS TV.""" + + def __init__(self, client): + """Initialize the service.""" + self._client = client + + def send_message(self, message="", **kwargs): + """Send a message to the tv.""" + from pylgtv import PyLGTVPairException + + try: + self._client.send_message(message) + except PyLGTVPairException: + _LOGGER.error('Pairing failed.') + except ConnectionRefusedError: + _LOGGER.error('Host unreachable.') diff --git a/requirements_all.txt b/requirements_all.txt index c3bbb5712b5..7dae3df1b85 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -79,6 +79,9 @@ https://github.com/HydrelioxGitHub/netatmo-api-python/archive/43ff238a0122b0939a # homeassistant.components.switch.dlink https://github.com/LinuxChristian/pyW215/archive/v0.1.1.zip#pyW215==0.1.1 +# homeassistant.components.media_player.webostv +https://github.com/TheRealLink/pylgtv/archive/v0.1.1.zip#pylgtv==0.1.1 + # homeassistant.components.sensor.thinkingcleaner # homeassistant.components.switch.thinkingcleaner https://github.com/TheRealLink/pythinkingcleaner/archive/v0.0.2.zip#pythinkingcleaner==0.0.2