From b39bb7e021cfc336cd63dcaa0cf20cd6d060bf57 Mon Sep 17 00:00:00 2001 From: Jeppe Fihl-Pearson Date: Sun, 10 Dec 2023 21:04:04 +0000 Subject: [PATCH] Add `sendButton` command to send remote button presses This makes it possible to send a sequence of button presses (among the current options) to the TV which can help automate actions that can't otherwise be achieved with the normal API. --- LGTV/__init__.py | 14 ++++++++++--- LGTV/cursor.py | 53 +++++++++++++++++++++++++++++++++++++++++++----- README.md | 1 + 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/LGTV/__init__.py b/LGTV/__init__.py index 89dfff4..46c634f 100644 --- a/LGTV/__init__.py +++ b/LGTV/__init__.py @@ -12,6 +12,7 @@ from .scan import LGTVScan from .remote import LGTVRemote from .auth import LGTVAuth +from .cursor import LGTVCursor search_config = [ @@ -158,9 +159,10 @@ def main(): else: try: kwargs = parseargs(args.command, args.args) - except Exception as e: - parser.print_help() - sys.exit(1) + except Exception: + if args.command not in {"sendButton"}: + parser.print_help() + sys.exit(1) if args.name: name = args.name @@ -170,6 +172,12 @@ def main(): print("A TV name is required. Set one with -n/--name or the setDefault command.") sys.exit(1) + if args.command == "sendButton": + cursor = LGTVCursor(name, **config[name], ssl=args.ssl) + cursor.connect() + cursor.execute(args.args) + return + try: ws = LGTVRemote(name, **config[name], ssl=args.ssl) diff --git a/LGTV/cursor.py b/LGTV/cursor.py index 69c3629..2f83b24 100644 --- a/LGTV/cursor.py +++ b/LGTV/cursor.py @@ -1,5 +1,8 @@ # Stub for cursor support. +import inspect +from time import sleep + from .remote import LGTVRemote from ws4py.client.threadedclient import WebSocketClient @@ -7,13 +10,48 @@ class LGTVCursor(WebSocketClient): def __finalize(self, response): + self.remote.close() address = response['payload']['socketPath'] super(LGTVCursor, self).__init__(address, exclude_headers=["Origin"]) - def __init__(self, name, ip=None, mac=None, key=None, hostname=None): - self.remote = LGTVRemote(name, ip, mac, key, hostname) + def __init__(self, name, ip=None, mac=None, key=None, hostname=None, ssl=False): + self.remote = LGTVRemote(name, ip, mac, key, hostname, ssl) self.remote.connect() - self.remote.getCursorSocket(self.__finalize) + self.remote.execute("getCursorSocket", {"callback": self.__finalize}) + self.remote.run_forever() + + def _list_possible_buttons(self): + buttons = [] + self_class = self.__class__.__name__ + + for name, method in inspect.getmembers(self, predicate=inspect.ismethod): + if name.startswith("_"): + continue + + if name in {"execute"}: + continue + + if not method.__qualname__.startswith(f"{self_class}."): + continue + + buttons.append(name) + + return buttons + + def execute(self, buttons): + if not buttons: + print("Add button presses to perform. Possible options:", ", ".join(self._list_possible_buttons())) + return + + for i, button in enumerate(buttons): + if not hasattr(self, button): + print(f"{button} is not a possible button press, skipped") + continue + + if i != 0: + sleep(0.1) + + getattr(self, button)() def up(self): self.send("type:button\nname:UP\n\n") @@ -34,5 +72,10 @@ def back(self): self.send("type:button\nname:BACK\n\n") def enter(self): - self.remote.sendEnterKey() - + self.send("type:button\nname:ENTER\n\n") + + def home(self): + self.send("type:button\nname:HOME\n\n") + + def exit(self): + self.send("type:button\nname:EXIT\n\n") diff --git a/README.md b/README.md index e5cd21e..28a9e26 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ All devices with firmware major version 4, product name "webOSTV 2.0" lgtv --name MyTV --ssl openYoutubeURL lgtv --name MyTV --ssl openYoutubeLegacyId lgtv --name MyTV --ssl openYoutubeLegacyURL + lgtv --name MyTV --ssl sendButton