def cmd(self, cmd): if "denon" in cmd: d = denonavr.DenonAVR(app_cfg['denon']['ip']) d.update() if cmd == "denon_input_digital": d.input_func = app_cfg['denon']['digital_in'] elif cmd == "denon_power_off": d.power_off() elif cmd == "denon_power_on": d.power_on() elif cmd == "denon_vol_down": d.volume_down() elif cmd == "denon_vol_mute": d.mute(True) #FIXME elif cmd == "denon_vol_up": d.volume_up() else: return '{"response":"invalid_cmd"}' return '{"response":"ok"}' elif "lg" in cmd: w = WebOsClient(app_cfg['lg']['ip']) w.register() if "lg_arr_" in cmd: w.request( "com.webos.service.networkinput/getPointerInputSocket") ws = websocket.WebSocket() ws.connect(w.last_response['payload']['socketPath']) if cmd == "lg_arr_down": ws.send('type:button\nname:DOWN\n\n') elif cmd == "lg_arr_up": ws.send('type:button\nname:UP\n\n') elif cmd == "lg_arr_left": ws.send('type:button\nname:LEFT\n\n') elif cmd == "lg_arr_right": ws.send('type:button\nname:RIGHT\n\n') elif cmd == "lg_arr_ok": ws.send('type:button\nname:ENTER\n\n') elif cmd == "lg_arr_back": ws.send('type:button\nname:BACK\n\n') elif cmd == "lg_cmd_pause": w.pause() elif cmd == "lg_input_netflix": w.launch_app(app_cfg['lg']['netflix']) elif cmd == "lg_input_ps4": w.set_input(app_cfg['lg']['ps4']) elif cmd == "lg_power_on": send_magic_packet(app_cfg['lg']['mac']) elif cmd == "lg_power_off": w.power_off() else: return '{"response":"invalid_cmd"}' return '{"response":"ok"}' else: return '{"response":"invalid_cmd"}'
class SnipsLGTV: def __init__(self, _ip, _mac, _onkyoip): self.ip = str(_ip) self.mac = _mac self.onkyoip = _onkyoip self.client = WebOsClient(self.ip, "/keys/lg.key") self.receiver = eISCP(self.onkyoip) def turn_on(self): send_magic_packet(self.mac) self.client.power_on() def turn_off(self): print("SNIPSLGTV OFF CALLED: %s" % self.ip) self.client.power_off() def open_app(self, app_name): print("Asked to start %s" % app_name) app_id = id_dict[app_name] print("Given app_id %s" % app_id) self.client.launch_app(app_id) def close_app(self): self.client.close_app() def set_volume(self, volume): if volume > 70: print("TOO LOUD!") else: print("Setting volume to %i" % volume) self.receiver.command("volume %d" % volume) print(self.client.last_response) def mute(self): self.client.set_mute("true") def unmute(self): self.client.set_mute("false")
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" def __init__(self, host, name, customize, config, timeout, hass, on_action): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host, config, timeout) self._on_script = Script(hass, on_action) if on_action else None self._customize = customize self._name = name # 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._state = STATE_UNKNOWN self._source_list = {} self._app_list = {} self._channel = None @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" from websockets.exceptions import ConnectionClosed try: current_input = self._client.get_input() if current_input is not None: self._current_source_id = current_input if self._state in (STATE_UNKNOWN, STATE_OFF): self._state = STATE_PLAYING else: self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None if self._state is not STATE_OFF: self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._channel = self._client.get_current_channel() self._source_list = {} self._app_list = {} conf_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app['id']] = app if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app elif (not conf_sources or app['id'] in conf_sources or any(word in app['title'] for word in conf_sources) or any(word in app['id'] for word in conf_sources)): self._source_list[app['title']] = app for source in self._client.get_inputs(): if source['id'] == self._current_source_id: self._current_source = source['label'] self._source_list[source['label']] = source elif (not conf_sources or source['label'] in conf_sources or any(source['label'].find(word) != -1 for word in conf_sources)): self._source_list[source['label']] = source except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None @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 sorted(self._source_list.keys()) @property def media_content_type(self): """Content type of current playing media.""" return MEDIA_TYPE_CHANNEL @property def media_title(self): """Title of current playing media.""" if (self._channel is not None) and ('channelName' in self._channel): return self._channel['channelName'] return None @property def media_image_url(self): """Image url of current playing media.""" if self._current_source_id in self._app_list: icon = self._app_list[self._current_source_id]['largeIcon'] if not icon.startswith('http'): icon = self._app_list[self._current_source_id]['icon'] return icon return None @property def supported_features(self): """Flag media player features that are supported.""" if self._on_script: 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 try: self._client.power_off() except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): pass def turn_on(self): """Turn on the media player.""" if self._on_script: self._on_script.run() 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._muted = mute 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 select_source(self, source): """Select input source.""" source_dict = self._source_list.get(source) if source_dict is None: _LOGGER.warning("Source %s not found for %s", source, self.name) return self._current_source_id = source_dict['id'] if source_dict.get('title'): self._current_source = source_dict['title'] self._client.launch_app(source_dict['id']) elif source_dict.get('label'): self._current_source = source_dict['label'] self._client.set_input(source_dict['id']) 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()
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" def __init__(self, host, name, customize, config, timeout, hass, on_action): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host, config, timeout) self._on_script = Script(hass, on_action) if on_action else None self._customize = customize self._name = name # 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._state = STATE_UNKNOWN self._source_list = {} self._app_list = {} self._channel = None @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" from websockets.exceptions import ConnectionClosed try: current_input = self._client.get_input() if current_input is not None: self._current_source_id = current_input if self._state in (STATE_UNKNOWN, STATE_OFF): self._state = STATE_PLAYING else: self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None if self._state is not STATE_OFF: self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._channel = self._client.get_current_channel() self._source_list = {} self._app_list = {} conf_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app['id']] = app if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app elif (not conf_sources or app['id'] in conf_sources or any(word in app['title'] for word in conf_sources) or any(word in app['id'] for word in conf_sources)): self._source_list[app['title']] = app for source in self._client.get_inputs(): if source['id'] == self._current_source_id: self._current_source = source['label'] self._source_list[source['label']] = source elif (not conf_sources or source['label'] in conf_sources or any(source['label'].find(word) != -1 for word in conf_sources)): self._source_list[source['label']] = source except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None @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 sorted(self._source_list.keys()) @property def media_content_type(self): """Content type of current playing media.""" return MEDIA_TYPE_CHANNEL @property def media_title(self): """Title of current playing media.""" if (self._channel is not None) and ('channelName' in self._channel): return self._channel['channelName'] return None @property def media_image_url(self): """Image url of current playing media.""" if self._current_source_id in self._app_list: icon = self._app_list[self._current_source_id]['largeIcon'] if not icon.startswith('http'): icon = self._app_list[self._current_source_id]['icon'] return icon return None @property def supported_features(self): """Flag media player features that are supported.""" if self._on_script: 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 try: self._client.power_off() except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): pass def turn_on(self): """Turn on the media player.""" if self._on_script: self._on_script.run() 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._muted = mute 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 select_source(self, source): """Select input source.""" source_dict = self._source_list.get(source) if source_dict is None: _LOGGER.warning("Source %s not found for %s", source, self.name) return self._current_source_id = source_dict['id'] if source_dict.get('title'): self._current_source = source_dict['title'] self._client.launch_app(source_dict['id']) elif source_dict.get('label'): self._current_source = source_dict['label'] self._client.set_input(source_dict['id']) def play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" _LOGGER.debug( "Call play media type <%s>, Id <%s>", media_type, media_id) if media_type == MEDIA_TYPE_CHANNEL: _LOGGER.debug("Searching channel...") partial_match_channel_id = None perfect_match_channel_id = None for channel in self._client.get_channels(): if media_id == channel['channelNumber']: perfect_match_channel_id = channel['channelId'] continue elif media_id.lower() == channel['channelName'].lower(): perfect_match_channel_id = channel['channelId'] continue elif media_id.lower() in channel['channelName'].lower(): partial_match_channel_id = channel['channelId'] if perfect_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with perfect match", perfect_match_channel_id) self._client.set_channel(perfect_match_channel_id) elif partial_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with partial match", partial_match_channel_id) self._client.set_channel(partial_match_channel_id) return 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.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_up() else: self._client.fast_forward() def media_previous_track(self): """Send the previous track command.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_down() else: self._client.rewind()
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" 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 # 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._state = STATE_UNKNOWN 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() self._volume = self._client.get_volume() self._current_source_id = self._client.get_input() self._source_list = {} self._app_list = {} custom_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app['id']] = app if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app elif (app['id'] in custom_sources or any(word in app['title'] for word in custom_sources) or any(word in app['id'] for word in custom_sources)): self._source_list[app['title']] = app for source in self._client.get_inputs(): if not source['connected']: continue app = self._app_list[source['appId']] self._source_list[app['title']] = app except (OSError, ConnectionClosed): 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 sorted(self._source_list.keys()) @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.""" if self._current_source_id in self._app_list: return self._app_list[self._current_source_id]['largeIcon'] return None @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 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.""" 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._muted = mute 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 select_source(self, source): """Select input source.""" self._current_source_id = self._source_list[source]['id'] self._current_source = self._source_list[source]['title'] self._client.launch_app(self._source_list[source]['id']) 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()
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" def __init__(self, host, name, customize, config, timeout, hass, on_action): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host, config, timeout) self._on_script = Script(hass, on_action) if on_action else None self._customize = customize self._name = name # 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._state = None self._source_list = {} self._app_list = {} self._channel = None self._last_icon = None @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" from websockets.exceptions import ConnectionClosed try: current_input = self._client.get_input() if current_input is not None: self._current_source_id = current_input if self._state in (None, STATE_OFF): self._state = STATE_PLAYING else: self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None if self._state is not STATE_OFF: self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._channel = self._client.get_current_channel() self._source_list = {} self._app_list = {} conf_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app["id"]] = app if app["id"] == self._current_source_id: self._current_source = app["title"] self._source_list[app["title"]] = app elif (not conf_sources or app["id"] in conf_sources or any(word in app["title"] for word in conf_sources) or any(word in app["id"] for word in conf_sources)): self._source_list[app["title"]] = app for source in self._client.get_inputs(): if source["id"] == self._current_source_id: self._current_source = source["label"] self._source_list[source["label"]] = source elif (not conf_sources or source["label"] in conf_sources or any(source["label"].find(word) != -1 for word in conf_sources)): self._source_list[source["label"]] = source except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): self._state = STATE_OFF self._current_source = None self._current_source_id = None self._channel = None @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 sorted(self._source_list.keys()) @property def media_content_type(self): """Content type of current playing media.""" return MEDIA_TYPE_CHANNEL @property def media_title(self): """Title of current playing media.""" if (self._channel is not None) and ("channelName" in self._channel): return self._channel["channelName"] return None @property def media_image_url(self): """Image url of current playing media.""" if self._current_source_id in self._app_list: icon = self._app_list[self._current_source_id]["largeIcon"] if not icon.startswith("http"): icon = self._app_list[self._current_source_id]["icon"] # 'icon' holds a URL with a transient key. Avoid unnecessary # updates by returning the same URL until the image changes. if self._last_icon and (icon.split("/")[-1] == self._last_icon.split("/")[-1]): return self._last_icon self._last_icon = icon return icon return None @property def supported_features(self): """Flag media player features that are supported.""" if self._on_script: 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 try: self._client.power_off() except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): pass def turn_on(self): """Turn on the media player.""" if self._on_script: self._on_script.run() 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._muted = mute 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 select_source(self, source): """Select input source.""" source_dict = self._source_list.get(source) if source_dict is None: _LOGGER.warning("Source %s not found for %s", source, self.name) return self._current_source_id = source_dict["id"] if source_dict.get("title"): self._current_source = source_dict["title"] self._client.launch_app(source_dict["id"]) elif source_dict.get("label"): self._current_source = source_dict["label"] self._client.set_input(source_dict["id"]) def play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" _LOGGER.debug("Call play media type <%s>, Id <%s>", media_type, media_id) if media_type == MEDIA_TYPE_CHANNEL: _LOGGER.debug("Searching channel...") partial_match_channel_id = None perfect_match_channel_id = None for channel in self._client.get_channels(): if media_id == channel["channelNumber"]: perfect_match_channel_id = channel["channelId"] continue elif media_id.lower() == channel["channelName"].lower(): perfect_match_channel_id = channel["channelId"] continue elif media_id.lower() in channel["channelName"].lower(): partial_match_channel_id = channel["channelId"] if perfect_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with perfect match", perfect_match_channel_id, ) self._client.set_channel(perfect_match_channel_id) elif partial_match_channel_id is not None: _LOGGER.info( "Switching to channel <%s> with partial match", partial_match_channel_id, ) self._client.set_channel(partial_match_channel_id) return 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.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_up() else: self._client.fast_forward() def media_previous_track(self): """Send the previous track command.""" current_input = self._client.get_input() if current_input == LIVETV_APP_ID: self._client.channel_down() else: self._client.rewind()
class LgCommand(object): def __init__(self, ip): self.client = WebOsClient(ip) self.commandLines = { 'off': self.off, 'on': self.wakeonlan, 'software-info': self.software_info, 'volume-up': self.volume_up, 'volume-down': self.volume_down, 'current-app': self.current_app, 'apps': self.apps, 'services': self.services, 'get-volume': self.get_volume, 'get-inputs': self.get_inputs, 'app': self.app, 'set-volume': self.set_volume, 'close-app': self.close_app, 'mute': self.mute, 'unmute': self.unmute, 'get-mute': self.get_mute, 'get-input': self.get_input, 'set-input': self.set_input, 'channel-up': self.channel_up, 'channel-down': self.channel_down, 'channels': self.channels, 'get-channel': self.get_channel, 'info': self.info, 'set-channel': self.set_channel, 'play': self.play, 'pause': self.pause, 'stop': self.stop, 'close': self.close, 'rewind': self.rewind, 'fast-forward': self.fast_forward, 'send-message': self.send_message, 'enter': self.enter, 'delete': self.delete, #'3d-on': threeDOn, #'3d-off': threeDOff, } def run(self, command, arg=None): return self.commandLines[command](arg) def send_message(self, arg): return self.client.send_message(arg) def delete(self, arg): return self.client.send_delete_key() def enter(self, arg): return self.client.send_enter_key() def play(self, arg): return self.client.play() def pause(self, arg): return self.client.pause() def stop(self, arg): return self.client.stop() def close(self, arg): return self.client.close() def rewind(self, arg): return self.client.rewind() def fast_forward(self, arg): return self.client.fast_forward() def info(self, arg): return self.client.get_channel_info() def set_channel(self, arg): return self.client.set_channel(arg) def get_channel(self, arg): return self.client.get_current_channel() def channels(self, arg): return self.client.get_channels() def channel_down(self, arg): return self.client.channel_down() def channel_up(self, arg): return self.client.channel_up() def get_input(self, arg): return self.client.get_input() def set_input(self, arg): return self.client.set_input(arg) def unmute(self, arg): return self.client.set_mute(False) def mute(self, arg): return self.client.set_mute(True) def get_mute(self, arg): return self.client.get_muted() def set_volume(self, arg): return self.client.set_volume(int(arg)) def close_app(self, arg): return self.client.close_app(arg) def app(self, arg): return self.client.launch_app(arg) def get_inputs(self, arg): return self.client.get_inputs() def get_volume(self, arg): return self.client.get_volume() def services(self, arg): return self.client.get_services() def current_app(self, arg): return self.client.get_current_app() def apps(self, arg): return self.client.get_apps() def off(self, arg): self.client.power_off() return "TV has been turned off." def software_info(self, arg): return self.check() def volume_down(self, arg): return self.client.volume_down() def volume_up(self, arg): return self.client.volume_up() def wakeonlan(self, mac): if mac is not None: addr_byte = mac.split(':') hw_addr = struct.pack('BBBBBB', int(addr_byte[0], 16), int(addr_byte[1], 16), int(addr_byte[2], 16), int(addr_byte[3], 16), int(addr_byte[4], 16), int(addr_byte[5], 16)) msg = b'\xff' * 6 + hw_addr * 16 socket_instance = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) socket_instance.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) socket_instance.sendto(msg, ('<broadcast>', 9)) socket_instance.close() return "TV has been turned on." else: return "mac address (arg) not set. use -h for help." def check(self): return self.client.get_software_info()
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" # pylint: disable=too-many-public-methods def __init__(self, host, name, customize): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host) self._customize = customize self._name = name # 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 = {} custom_sources = [] for source in self._customize.get(CONF_SOURCES, []): app_id = WEBOS_APPS_SHORT.get(source, None) if app_id: custom_sources.append(app_id) else: custom_sources.append(source) for app in self._client.get_apps(): self._app_list[app['id']] = app if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app if app['id'] in custom_sources: self._source_list[app['title']] = app for source in self._client.get_inputs(): if not source['connected']: continue app = self._app_list[source['appId']] self._source_list[app['title']] = app except OSError: 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 sorted(self._source_list.keys()) @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.""" if self._current_source_id in self._app_list: return self._app_list[self._current_source_id]['largeIcon'] return None @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._state = STATE_OFF 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._muted = mute 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 select_source(self, source): """Select input source.""" self._current_source_id = self._source_list[source]['id'] self._current_source = self._source_list[source]['title'] self._client.launch_app(self._source_list[source]['id']) 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()
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._source_label_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._source_label_list = [] self._app_list = {} for app in self._client.get_apps(): self._app_list[app['id']] = app for source in self._client.get_inputs(): self._source_list[source['label']] = source self._app_list[source['appId']] = source self._source_label_list.append(source['label']) if source['appId'] == self._current_source_id: self._current_source = source['label'] 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_label_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._muted = mute 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 select_source(self, source): """Select input source.""" self._current_source_id = self._source_list[source]['appId'] self._current_source = self._source_list[source]['label'] self._client.set_input(self._source_list[source]['id']) 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()
class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" def __init__(self, host, mac, name, customize, config): """Initialize the webos device.""" from pylgtv import WebOsClient from wakeonlan import wol self._client = WebOsClient(host, config) self._wol = wol self._mac = mac self._customize = customize self._name = name # 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._state = STATE_UNKNOWN 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: current_input = self._client.get_input() if current_input is not None: self._current_source_id = current_input if self._state in (STATE_UNKNOWN, STATE_OFF): self._state = STATE_PLAYING else: self._state = STATE_OFF self._current_source = None self._current_source_id = None if self._state is not STATE_OFF: self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._source_list = {} self._app_list = {} conf_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app['id']] = app if conf_sources: if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app elif (app['id'] in conf_sources or any(word in app['title'] for word in conf_sources) or any(word in app['id'] for word in conf_sources)): self._source_list[app['title']] = app else: self._current_source = app['title'] self._source_list[app['title']] = app for source in self._client.get_inputs(): if conf_sources: if source['id'] == self._current_source_id: self._source_list[source['label']] = source elif (source['label'] in conf_sources or any(source['label'].find(word) != -1 for word in conf_sources)): self._source_list[source['label']] = source else: self._source_list[source['label']] = source except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): self._state = STATE_OFF self._current_source = None self._current_source_id = None @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 sorted(self._source_list.keys()) @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.""" if self._current_source_id in self._app_list: icon = self._app_list[self._current_source_id]['largeIcon'] if not icon.startswith('http'): icon = self._app_list[self._current_source_id]['icon'] return icon return None @property def supported_features(self): """Flag media player features 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 try: self._client.power_off() except (OSError, ConnectionClosed, TypeError, asyncio.TimeoutError): 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.""" 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._muted = mute 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 select_source(self, source): """Select input source.""" if self._source_list.get(source).get('title'): self._current_source_id = self._source_list[source]['id'] self._current_source = self._source_list[source]['title'] self._client.launch_app(self._source_list[source]['id']) elif self._source_list.get(source).get('label'): self._current_source_id = self._source_list[source]['id'] self._current_source = self._source_list[source]['label'] self._client.set_input(self._source_list[source]['id']) 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()