diff --git a/homeassistant/components/media_player/webostv.py b/homeassistant/components/media_player/webostv.py index 40792c338b2..a2f49cc3f21 100644 --- a/homeassistant/components/media_player/webostv.py +++ b/homeassistant/components/media_player/webostv.py @@ -1,5 +1,5 @@ """ -Support for interface with an LG WebOS TV. +Support for interface with an LG webOS Smart TV. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/media_player.webostv/ @@ -12,31 +12,35 @@ import voluptuous as vol import homeassistant.util as util from homeassistant.components.media_player import ( + SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, - SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE, SUPPORT_PLAY_MEDIA, MEDIA_TYPE_CHANNEL, MediaPlayerDevice, PLATFORM_SCHEMA) from homeassistant.const import ( - CONF_HOST, CONF_CUSTOMIZE, STATE_OFF, STATE_PLAYING, STATE_PAUSED, + CONF_HOST, CONF_MAC, CONF_CUSTOMIZE, STATE_OFF, + STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN, CONF_NAME) from homeassistant.loader import get_component import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['https://github.com/TheRealLink/pylgtv' '/archive/v0.1.2.zip' - '#pylgtv==0.1.2'] + '#pylgtv==0.1.2', + 'websockets==3.2', + 'wakeonlan==0.2.2'] -_CONFIGURING = {} +_CONFIGURING = {} # type: Dict[str, str] _LOGGER = logging.getLogger(__name__) CONF_SOURCES = 'sources' -DEFAULT_NAME = 'LG WebOS Smart TV' +DEFAULT_NAME = 'LG webOS Smart TV' -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 +SUPPORT_WEBOSTV = SUPPORT_TURN_OFF | \ + SUPPORT_NEXT_TRACK | SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | \ + SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_STEP | \ + SUPPORT_SELECT_SOURCE | SUPPORT_PLAY_MEDIA MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1) @@ -49,6 +53,7 @@ CUSTOMIZE_SCHEMA = vol.Schema({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_HOST): cv.string, + vol.Optional(CONF_MAC): cv.string, vol.Optional(CONF_CUSTOMIZE, default={}): CUSTOMIZE_SCHEMA, }) @@ -69,15 +74,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if host in _CONFIGURING: return + mac = config.get(CONF_MAC) name = config.get(CONF_NAME) customize = config.get(CONF_CUSTOMIZE) - setup_tv(host, name, customize, hass, add_devices) + setup_tv(host, mac, name, customize, hass, add_devices) -def setup_tv(host, name, customize, hass, add_devices): - """Setup a phue bridge based on host parameter.""" +def setup_tv(host, mac, name, customize, hass, add_devices): + """Setup a LG WebOS TV based on host parameter.""" from pylgtv import WebOsClient from pylgtv import PyLGTVPairException + from websockets.exceptions import ConnectionClosed client = WebOsClient(host) @@ -88,15 +95,16 @@ def setup_tv(host, name, customize, hass, add_devices): client.register() except PyLGTVPairException: _LOGGER.warning( - "Connected to LG WebOS TV %s but not paired", host) + "Connected to LG webOS TV %s but not paired", host) return - except OSError: + except (OSError, ConnectionClosed): _LOGGER.error("Unable to connect to host %s", host) return else: # Not registered, request configuration. - _LOGGER.warning("LG WebOS TV %s needs to be paired", host) - request_configuration(host, name, customize, hass, add_devices) + _LOGGER.warning("LG webOS TV %s needs to be paired", host) + request_configuration( + host, mac, name, customize, hass, add_devices) return # If we came here and configuring this host, mark as done. @@ -105,10 +113,11 @@ def setup_tv(host, name, customize, hass, add_devices): configurator = get_component('configurator') configurator.request_done(request_id) - add_devices([LgWebOSDevice(host, name, customize)]) + add_devices([LgWebOSDevice(host, mac, name, customize)], True) -def request_configuration(host, name, customize, hass, add_devices): +def request_configuration( + host, mac, name, customize, hass, add_devices): """Request configuration steps from the user.""" configurator = get_component('configurator') @@ -121,10 +130,10 @@ def request_configuration(host, name, customize, hass, add_devices): # pylint: disable=unused-argument def lgtv_configuration_callback(data): """The actions to do when our configuration callback is called.""" - setup_tv(host, name, customize, hass, add_devices) + setup_tv(host, mac, name, customize, hass, add_devices) _CONFIGURING[host] = configurator.request_config( - hass, 'LG WebOS TV', lgtv_configuration_callback, + hass, name, 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' @@ -134,10 +143,13 @@ def request_configuration(host, name, customize, hass, add_devices): class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" - def __init__(self, host, name, customize): + def __init__(self, host, mac, name, customize): """Initialize the webos device.""" from pylgtv import WebOsClient + from wakeonlan import wol self._client = WebOsClient(host) + self._wol = wol + self._mac = mac self._customize = customize self._name = name @@ -148,15 +160,14 @@ class LgWebOSDevice(MediaPlayerDevice): 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() + self._source_list = {} + self._app_list = {} @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" + from websockets.exceptions import ConnectionClosed try: self._state = STATE_PLAYING self._muted = self._client.get_muted() @@ -183,7 +194,7 @@ class LgWebOSDevice(MediaPlayerDevice): app = self._app_list[source['appId']] self._source_list[app['title']] = app - except OSError: + except (OSError, ConnectionClosed): self._state = STATE_OFF @property @@ -231,12 +242,23 @@ class LgWebOSDevice(MediaPlayerDevice): @property def supported_media_commands(self): """Flag of media commands that are supported.""" + if self._mac: + return SUPPORT_WEBOSTV | SUPPORT_TURN_ON return SUPPORT_WEBOSTV def turn_off(self): """Turn off media player.""" + from websockets.exceptions import ConnectionClosed self._state = STATE_OFF - self._client.power_off() + try: + self._client.power_off() + except (OSError, ConnectionClosed): + pass + + def turn_on(self): + """Turn on the media player.""" + if self._mac: + self._wol.send_magic_packet(self._mac) def volume_up(self): """Volume up the media player.""" diff --git a/requirements_all.txt b/requirements_all.txt index 6bc661d6ba0..6649fc058d9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -605,12 +605,16 @@ vsure==0.11.1 vtjp==0.1.11 # homeassistant.components.media_player.panasonic_viera +# homeassistant.components.media_player.webostv # homeassistant.components.switch.wake_on_lan wakeonlan==0.2.2 # homeassistant.components.media_player.gpmdp websocket-client==0.37.0 +# homeassistant.components.media_player.webostv +websockets==3.2 + # homeassistant.components.zigbee xbee-helper==0.0.7