def try_connect(self): """Try to connect to the Legacy TV.""" config = { CONF_NAME: VALUE_CONF_NAME, CONF_DESCRIPTION: VALUE_CONF_NAME, CONF_ID: VALUE_CONF_ID, CONF_HOST: self.host, CONF_METHOD: self.method, CONF_PORT: None, # We need this high timeout because waiting for auth popup is just an open socket CONF_TIMEOUT: TIMEOUT_REQUEST, } try: LOGGER.debug("Try config: %s", config) with Remote(config.copy()): LOGGER.debug("Working config: %s", config) return RESULT_SUCCESS except AccessDenied: LOGGER.debug("Working but denied config: %s", config) return RESULT_AUTH_MISSING except UnhandledResponse: LOGGER.debug("Working but unsupported config: %s", config) return RESULT_NOT_SUPPORTED except (ConnectionClosed, OSError) as err: LOGGER.debug("Failing config: %s, error: %s", config, err) return RESULT_CANNOT_CONNECT
def _try_connect(self): """Try to connect and check auth.""" for cfg in SUPPORTED_METHODS: config = { "name": "HomeAssistant", "description": "HomeAssistant", "id": "ha.component.samsung", "host": self._host, "port": self._port, } config.update(cfg) try: LOGGER.debug("Try config: %s", config) with Remote(config.copy()): LOGGER.debug("Working config: %s", config) self._method = cfg["method"] return RESULT_SUCCESS except AccessDenied: LOGGER.debug("Working but denied config: %s", config) return RESULT_AUTH_MISSING except (UnhandledResponse, WebSocketException): LOGGER.debug("Working but unsupported config: %s", config) return RESULT_NOT_SUPPORTED except OSError as err: LOGGER.debug("Failing config: %s, error: %s", config, err) LOGGER.debug("No working config found") return RESULT_NOT_SUCCESSFUL
def _try_connect(self): """Try to connect and check auth.""" for method in METHODS: config = { "name": "HomeAssistant", "description": "HomeAssistant", "id": "ha.component.samsung", "host": self._host, "method": method, "port": self._port, # We need this high timeout because waiting for auth popup is just an open socket "timeout": 31, } try: LOGGER.debug("Try config: %s", config) with Remote(config.copy()): LOGGER.debug("Working config: %s", config) self._method = method return RESULT_SUCCESS except AccessDenied: LOGGER.debug("Working but denied config: %s", config) return RESULT_AUTH_MISSING except UnhandledResponse: LOGGER.debug("Working but unsupported config: %s", config) return RESULT_NOT_SUPPORTED except OSError as err: LOGGER.debug("Failing config: %s, error: %s", config, err) LOGGER.debug("No working config found") return RESULT_NOT_SUCCESSFUL
def try_connect(self, port): """Try to connect to the Legacy TV.""" if port is not None and port != self.port: return RESULT_NOT_SUCCESSFUL config = { "name": "HomeAssistant", "description": "HomeAssistant", "id": "ha.component.samsung", "host": self.host, "method": self.method, "port": self.port, # We need this high timeout because waiting for auth popup is just an open socket "timeout": 31, } try: LOGGER.debug("Try config: %s", config) with Remote(config.copy()): LOGGER.debug("Working config: %s", config) return RESULT_SUCCESS except AccessDenied: LOGGER.debug("Working but denied config: %s", config) return RESULT_AUTH_MISSING except UnhandledResponse: LOGGER.debug("Working but unsupported config: %s", config) return RESULT_NOT_SUPPORTED except OSError as err: LOGGER.debug("Failing config: %s, error: %s", config, err) return RESULT_NOT_SUCCESSFUL
def try_connect(self): """Try to connect to the TVs with pin.""" config = { CONF_NAME: VALUE_CONF_NAME, CONF_DESCRIPTION: VALUE_CONF_NAME, CONF_ID: VALUE_CONF_ID, CONF_HOST: self.host, CONF_METHOD: self.method, CONF_SESSION_ID: self.session_id, CONF_SESSION_KEY: self.session_key, CONF_PORT: self.port, # We need this high timeout because waiting for auth popup is just an open socket CONF_TIMEOUT: 31, } try: LOGGER.debug("Try config: %s", config) with Remote(config.copy()): LOGGER.debug("Working config: %s", config) return RESULT_SUCCESS except AccessDenied: LOGGER.debug("Working but denied config: %s", config) return RESULT_AUTH_MISSING except UnhandledResponse: LOGGER.debug("Working but unsupported config: %s", config) return RESULT_NOT_SUPPORTED except OSError as err: LOGGER.debug("Failing config: %s, error: %s", config, err) return RESULT_NOT_SUCCESSFUL
def _try_connect_samsungctl(self, port): if self._port is None or port == self._port: config = { "name": "HomeAssistant", "description": "HomeAssistant", "id": "ha.component.samsung", "host": self._host, "method": "legacy" if port == 55000 else "websocket", "port": port, # We need this high timeout because waiting for auth popup is just an open socket "timeout": 31, } try: LOGGER.debug("Try config: %s", config) with Remote(config.copy()): LOGGER.debug("Working config: %s", config) self._method = config["method"] return RESULT_SUCCESS except AccessDenied: LOGGER.debug("Working but denied config: %s", config) return RESULT_AUTH_MISSING except UnhandledResponse: LOGGER.debug("Working but unsupported config: %s", config) return RESULT_NOT_SUPPORTED except OSError as err: LOGGER.debug("Failing config: %s, error: %s", config, err) return RESULT_NOT_SUCCESSFUL
def _get_remote(self): """Create or return a remote control instance.""" if self._remote is None: # We need to create a new instance to reconnect. try: LOGGER.debug("Create SamsungRemote") self._remote = Remote(self.config.copy()) # This is only happening when the auth was switched to DENY # A removed auth will lead to socket timeout because waiting for auth popup is just an open socket except AccessDenied: self._notify_callback() raise return self._remote
def _get_remote(self, avoid_open: bool = False): """Create or return a remote control instance.""" if self._remote is None: # We need to create a new instance to reconnect. try: LOGGER.debug("Create SamsungTVLegacyBridge for %s (%s)", CONF_NAME, self.host) self._remote = Remote(self.config.copy()) # This is only happening when the auth was switched to DENY # A removed auth will lead to socket timeout because waiting for auth popup is just an open socket except AccessDenied: self._notify_callback() raise except (ConnectionClosed, OSError): pass return self._remote
def main(): epilog = "E.g. %(prog)s --host 192.168.0.10 --name myremote KEY_VOLDOWN" parser = argparse.ArgumentParser(prog=title, description=doc, epilog=epilog) parser.add_argument("--version", action="version", version="%(prog)s {0}".format(version)) parser.add_argument("-v", "--verbose", action="count", help="increase output verbosity") parser.add_argument("-q", "--quiet", action="store_true", help="suppress non-fatal output") parser.add_argument("-i", "--interactive", action="store_true", help="interactive control") parser.add_argument("--host", help="TV hostname or IP address") parser.add_argument("--port", type=int, help="TV port number (TCP)") parser.add_argument("--method", help="Connection method (legacy or websocket)") parser.add_argument("--name", help="remote control name") parser.add_argument("--description", metavar="DESC", help="remote control description") parser.add_argument("--id", help="remote control id") parser.add_argument("--timeout", type=float, help="socket timeout in seconds (0 = no timeout)") parser.add_argument( "--key-help", action="store_true", help="print available keys. (key support depends on tv model)") parser.add_argument("key", nargs="*", default=[], type=get_key, help="keys to be sent (e.g. KEY_VOLDOWN)") args = parser.parse_args() if args.quiet: log_level = logging.ERROR elif not args.verbose: log_level = logging.WARNING elif args.verbose == 1: log_level = logging.INFO else: log_level = logging.DEBUG logging.basicConfig(format="%(message)s", level=log_level) if args.key_help: keys_help(args.key) config = _read_config() config.update({k: v for k, v in vars(args).items() if v is not None}) if not config["host"]: logging.error("Error: --host must be set") return try: with Remote(config) as remote: for key in args.key: if key is None: continue key(remote) if args.interactive: logging.getLogger().setLevel(logging.ERROR) from . import interactive interactive.run(remote) elif len(args.key) == 0: logging.warning("Warning: No keys specified.") except exceptions.ConnectionClosed: logging.error("Error: Connection closed!") except exceptions.AccessDenied: logging.error("Error: Access denied!") except exceptions.UnknownMethod: logging.error("Error: Unknown method '{}'".format(config["method"])) except socket.timeout: logging.error("Error: Timed out!") except OSError as e: logging.error("Error: %s", e.strerror)
def main(): epilog = "E.g. %(prog)s --host 192.168.0.10 --name myremote KEY_VOLDOWN" parser = argparse.ArgumentParser( prog=title, description=doc, epilog=epilog ) parser.add_argument( "--version", action="version", version="%(prog)s {0}".format(version) ) parser.add_argument( "-v", "--verbose", action="count", help="increase output verbosity" ) parser.add_argument( "-q", "--quiet", action="store_true", help="suppress non-fatal output" ) parser.add_argument( "-i", "--interactive", action="store_true", help="interactive control" ) parser.add_argument( "--host", help="TV hostname or IP address" ) parser.add_argument( "--port", type=int, help="TV port number (TCP)" ) parser.add_argument( "--method", help="Connection method (legacy or websocket)" ) parser.add_argument( "--name", help="remote control name" ) parser.add_argument( "--description", metavar="DESC", help="remote control description" ) parser.add_argument( "--id", help="remote control id" ) parser.add_argument( "--timeout", type=float, help="socket timeout in seconds (0 = no timeout)" ) parser.add_argument( "--start-app", help="start an application --start-app \"Netflix\"" ) parser.add_argument( "--app-metadata", help=( "pass options string of information the application " "can use when it starts up. And example would be the browser. " "To have it open directly to a specific URL you would enter: " "\"http\/\/www.some-web-address.com\". wrapping the meta data in " "quotes will reduce the possibility of a command line parser " "error." ) ) parser.add_argument( "--key-help", action="store_true", help="print available keys. (key support depends on tv model)" ) parser.add_argument( "key", nargs="*", default=[], type=get_key, help="keys to be sent (e.g. KEY_VOLDOWN)" ) args = parser.parse_args() if args.quiet: log_level = logging.ERROR elif not args.verbose: log_level = logging.WARNING elif args.verbose == 1: log_level = logging.INFO else: log_level = logging.DEBUG if args.key_help: keys_help(args.key) config = _read_config() config.update({k: v for k, v in vars(args).items() if v is not None}) if not config["host"]: logging.error("Error: --host must be set") return try: with Remote(config, log_level) as remote: if args.interactive: logging.getLogger().setLevel(logging.ERROR) from . import interactive interactive.run(remote) elif config["method"] == 'websocket' and args.start_app: app = remote.get_application(args.start_app) if args.app_metadata: app.run(args.app_metadata) else: app.run() elif len(args.key) == 0: logging.warning("Warning: No keys specified.") else: for key in args.key: if key is None: continue key(remote) except exceptions.ConnectionClosed: logging.error("Error: Connection closed!") except exceptions.AccessDenied: logging.error("Error: Access denied!") except exceptions.UnknownMethod: logging.error("Error: Unknown method '{}'".format(config["method"])) except socket.timeout: logging.error("Error: Timed out!") except OSError as e: logging.error("Error: %s", e.strerror)
def main(): epilog = "E.g. %(prog)s --host 192.168.0.10 --name myremote KEY_VOLDOWN" parser = argparse.ArgumentParser(prog=title, description=doc, epilog=epilog) parser.add_argument("--version", action="version", version="%(prog)s {0}".format(version)) parser.add_argument("-v", "--verbose", action="count", help="increase output verbosity") parser.add_argument("-q", "--quiet", action="store_true", help="suppress non-fatal output") parser.add_argument("-i", "--interactive", action="store_true", help="interactive control") parser.add_argument("--host", help="TV hostname or IP address") parser.add_argument("--token", default=None, help="token for TV's >= 2014") parser.add_argument("--port", type=int, help="TV port number (TCP)") parser.add_argument("--method", help="Connection method (legacy or websocket)") parser.add_argument("--name", help="remote control name") parser.add_argument("--description", metavar="DESC", help="remote control description") parser.add_argument("--id", help="remote control id") parser.add_argument( "--volume", type=int, help=("sets the TV volume to the entered value, a value of -1 will " "display the volume level")) parser.add_argument( "--brightness", type=int, help=("sets the TV brightness level to the entered value, " "a value of -1 will display the brightness level")) parser.add_argument( "--contrast", type=int, help=("sets the TV contrast level to the entered value, " "a value of -1 will display the contrast level")) parser.add_argument( "--sharpness", type=int, help=("sets the TV sharpness level to the entered value, " "a value of -1 will display the sharpness level")) parser.add_argument("--mute", type=str, choices=['off', 'on', 'state'], help=("sets the mute on or off (not a toggle), " "state displays if the mute if on or off")) parser.add_argument( "--source", type=str, help=( "changes the input source to the one specified. " "You can either enter the TV source name " "eg: HDMI1 HDMI2, USB, PC...." "or you can enter the programmed label for the source. " "This is going to be what is displayed on the OSD when you change " "the source from the remote. If you enter 'state' for the source " "name it will print out the currently " "active source label and name.")) parser.add_argument( "--source-label", type=str, help=( "changes the label for a source. " "If you do not use --source to specify the source to change the " "label on. It will automatically default to the currently " "active source. If you set the label to 'state' it will print out " "the current label for a source if specified using --source or " "the currently active source")) parser.add_argument("--timeout", type=float, help="socket timeout in seconds (0 = no timeout)") parser.add_argument("--config-file", type=str, default=None, help="configuration file to load and/or save to") parser.add_argument("--start-app", help="start an application --start-app \"Netflix\"") parser.add_argument( "--app-metadata", help=( "pass options string of information the application " "can use when it starts up. And example would be the browser. " "To have it open directly to a specific URL you would enter: " "\"http\/\/www.some-web-address.com\". wrapping the meta data in " "quotes will reduce the possibility of a command line parser " "error.")) parser.add_argument( "--key-help", action="store_true", help="print available keys. (key support depends on tv model)") parser.add_argument("key", nargs="*", default=[], type=get_key, help="keys to be sent (e.g. KEY_VOLDOWN)") args = parser.parse_args() if args.quiet: log_level = logging.ERROR elif not args.verbose: log_level = logging.WARNING elif args.verbose == 1: log_level = logging.INFO else: log_level = logging.DEBUG if args.key_help: keys_help(args.key) if args.config_file is None: config = _read_config() config.update({k: v for k, v in vars(args).items() if v is not None}) config = Config(**config) else: if os.path.isfile(args.config_file): config = Config.load(args.config_file) else: config = _read_config() config.update( {k: v for k, v in vars(args).items() if v is not None}) config = Config(**config) config.path = args.config_file if not config.host: logging.error("Error: --host must be set") return config.log_level = log_level if config.upnp_locations is None: config.upnp_locations = [] try: with Remote(config) as remote: if args.interactive: logging.getLogger().setLevel(logging.ERROR) from . import interactive interactive.run(remote) elif config.method == 'websocket' and args.start_app: app = remote.get_application(args.start_app) if args.app_metadata: app.run(args.app_metadata) else: app.run() else: for key in args.key: if key is None: continue key(remote) if args.volume is not None: if args.volume == -1: print('Volume:', remote.volume, '%') else: remote.volume = args.volume elif args.mute is not None: if args.mute == 'state': print('Mute:', 'ON' if remote.mute else 'OFF') else: remote.mute = args.mute == 'on' if args.brightness is not None: if args.brightness == -1: print('Brightness:', remote.brightness, '%') else: remote.brightness = args.brightness if args.contrast is not None: if args.contrast == -1: print('Contrast:', remote.contrast, '%') else: remote.contrast = args.contrast if args.sharpness is not None: if args.sharpness == -1: print('Sharpness:', remote.sharpness, '%') else: remote.sharpness = args.sharpness if args.source_label is not None: if args.source is None: if args.source_label == 'state': print('Source Label:', remote.source.label) else: remote.source.label = args.remote_label else: for source in remote.sources: if args.source in (source.label, source.name): if args.source_label == 'state': print('Source Label:', source.label) else: source.label = args.source_label break elif args.source is not None: if args.source == 'state': source = remote.source print('Source: Label =', source.label, 'Name =', source.name) else: remote.source = args.source except exceptions.ConnectionClosed: logging.error("Error: Connection closed!") except exceptions.AccessDenied: logging.error("Error: Access denied!") except exceptions.ConfigUnknownMethod: logging.error("Error: Unknown method '{}'".format(config.method)) except socket.timeout: logging.error("Error: Timed out!") except OSError as e: logging.error("Error: %s", e.strerror) if args.config_file: config.save()
def main(): epilog = "E.g. %(prog)s --host 192.168.0.10 --name myremote KEY_VOLDOWN" parser = argparse.ArgumentParser( prog=title, description=doc, epilog=epilog ) parser.add_argument( "--version", action="version", version="%(prog)s {0}".format(version) ) parser.add_argument( "-v", "--verbose", action="count", help="increase output verbosity" ) parser.add_argument( "-i", "--interactive", action="store_true", help="interactive control" ) parser.add_argument( "--host", help="TV hostname or IP address" ) parser.add_argument( "--name", help="remote control name" ) parser.add_argument( "--description", metavar="DESC", help="remote control description" ) parser.add_argument( "--volume", type=int, default=None, help=( "sets the TV volume to the entered value, a value of -1 will " "display the volume level" ) ) parser.add_argument( "--brightness", type=int, default=None, help=( "sets the TV brightness level to the entered value, " "a value of -1 will display the brightness level" ) ) parser.add_argument( "--contrast", type=int, default=None, help=( "sets the TV contrast level to the entered value, " "a value of -1 will display the contrast level" ) ) parser.add_argument( "--sharpness", type=int, default=None, help=( "sets the TV sharpness level to the entered value, " "a value of -1 will display the sharpness level" ) ) parser.add_argument( "--mute", type=str, default=None, choices=['off', 'on', 'state'], help=( "sets the mute on or off (not a toggle), " "state displays if the mute is on or off" ) ) parser.add_argument( "--artmode", type=str, default=None, choices=['off', 'on', 'state'], help=( "sets the art mode for Frame TV's, " "state displays if the art mode is on or off" ) ) parser.add_argument( "--source", type=str, default=None, help=( "changes the input source to the one specified. " "You can either enter the TV source name " "eg: HDMI1 HDMI2, USB, PC...." "or you can enter the programmed label for the source. " "This is going to be what is displayed on the OSD when you change " "the source from the remote. If you enter 'state' for the source " "name it will print out the currently " "active source label and name." ) ) parser.add_argument( "--config-file", type=str, default=None, help="configuration file to load and/or save to" ) parser.add_argument( "--start-app", help="start an application --start-app \"Netflix\"" ) parser.add_argument( "--app-metadata", help=( "pass options string of information the application " "can use when it starts up. And example would be the browser. " "To have it open directly to a specific URL you would enter: " "\"http\/\/www.some-web-address.com\". wrapping the meta data in " "quotes will reduce the possibility of a command line parser " "error." ) ) parser.add_argument( "--key-help", action="store_true", help="print available keys. (key support depends on tv model)" ) parser.add_argument( "key", nargs="*", default=[], type=get_key, help="keys to be sent (e.g. KEY_VOLDOWN)" ) args = parser.parse_args() log_levels = [ logging.NOTSET, logging.INFO, logging.WARNING, logging.ERROR, logging.DEBUG ] logger.setLevel(log_levels[args.verbose]) if args.key_help: keys_help(args.key) if args.config_file is None: config = Config else: config = Config.load(args.config_file) config = config( host=args.host ) if not config.uuid: configs = discover(args.host) if len(configs) > 1: while True: for i, cfg in enumerate(configs): print(i + 1, ':', cfg.model) try: # noinspection PyCompatibility answer = raw_input( 'Enter the number of the TV you want to pair with:' ) except NameError: answer = input( 'Enter the number of the TV you want to pair with:' ) try: answer = int(answer) - 1 config = configs[answer] break except (TypeError, ValueError, IndexError): pass elif configs: config = configs[0] else: print('Unable to discover any TV\'s') sys.exit(1) config.log_level = log_levels[args.verbose] if not config.uuid: print('No UUID for TV located') sys.exit(1) if config.upnp_locations is None: config.upnp_locations = [] try: with Remote(config) as remote: if args.interactive: logging.getLogger().setLevel(logging.ERROR) from . import interactive inter = interactive.Interactive(remote) inter.run() sys.exit(1) if ( args.key and args.key[0] in ('KEY_POWER', 'KEY_POWERON') and config.paired and not remote.power ): args.key.pop(0) remote.power = True import time while remote.is_powering_on: time.sleep(0.25) if not remote.power: print('Unable to power on the TV') sys.exit(1) if config.method == 'websocket' and args.start_app: app = remote.get_application(args.start_app) if args.app_metadata: app.run(args.app_metadata) else: app.run() else: for key in args.key: if key is None: continue key(remote) if args.volume is not None: if args.volume == -1: print('Volume:', remote.volume, '%') else: remote.volume = args.volume elif args.mute is not None: if args.mute == 'state': print('Mute:', 'ON' if remote.mute else 'OFF') else: remote.mute = args.mute == 'on' elif args.artmode is not None: if args.artmode == 'state': print('Art Mode:', 'ON' if remote.artmode else 'OFF') else: remote.artmode = args.artmode == 'on' if args.brightness is not None: if args.brightness == -1: print('Brightness:', remote.brightness, '%') else: remote.brightness = args.brightness if args.contrast is not None: if args.contrast == -1: print('Contrast:', remote.contrast, '%') else: remote.contrast = args.contrast if args.sharpness is not None: if args.sharpness == -1: print('Sharpness:', remote.sharpness, '%') else: remote.sharpness = args.sharpness if args.source is not None: if args.source == 'state': source = remote.source print( 'Source: Label =', source.label, 'Name =', source.name ) else: remote.source = args.source except exceptions.ConnectionClosed: logging.error("Error: Connection closed!") except exceptions.AccessDenied: logging.error("Error: Access denied!") except exceptions.ConfigUnknownMethod: logging.error("Error: Unknown method '{}'".format(config.method)) except socket.timeout: logging.error("Error: Timed out!") except OSError as e: logging.error("Error: %s", e.strerror) if args.config_file: config.save()
def main(): auto_discover.start() epilog = "E.g. %(prog)s --host 192.168.0.10 --name myremote KEY_VOLDOWN" parser = argparse.ArgumentParser(prog=title, description=doc, epilog=epilog) parser.add_argument("--version", action="version", version="%(prog)s {0}".format(version)) parser.add_argument("-v", "--verbose", action="count", help="increase output verbosity") parser.add_argument("-q", "--quiet", action="store_true", help="suppress non-fatal output") parser.add_argument("-i", "--interactive", action="store_true", help="interactive control") parser.add_argument("--host", help="TV hostname or IP address") parser.add_argument("--token", default=None, help="token for TV's >= 2014") parser.add_argument("--port", type=int, help="TV port number (TCP)") parser.add_argument("--method", help="Connection method (legacy or websocket)") parser.add_argument("--name", help="remote control name") parser.add_argument("--description", metavar="DESC", help="remote control description") parser.add_argument("--id", help="remote control id") parser.add_argument( "--volume", type=int, default=None, help=("sets the TV volume to the entered value, a value of -1 will " "display the volume level")) parser.add_argument( "--brightness", type=int, default=None, help=("sets the TV brightness level to the entered value, " "a value of -1 will display the brightness level")) parser.add_argument( "--contrast", type=int, default=None, help=("sets the TV contrast level to the entered value, " "a value of -1 will display the contrast level")) parser.add_argument( "--sharpness", type=int, default=None, help=("sets the TV sharpness level to the entered value, " "a value of -1 will display the sharpness level")) parser.add_argument("--mute", type=str, default=None, choices=['off', 'on', 'state'], help=("sets the mute on or off (not a toggle), " "state displays if the mute is on or off")) parser.add_argument("--artmode", type=str, default=None, choices=['off', 'on', 'state'], help=("sets the art mode for Frame TV's, " "state displays if the art mode is on or off")) parser.add_argument( "--source", type=str, default=None, help=( "changes the input source to the one specified. " "You can either enter the TV source name " "eg: HDMI1 HDMI2, USB, PC...." "or you can enter the programmed label for the source. " "This is going to be what is displayed on the OSD when you change " "the source from the remote. If you enter 'state' for the source " "name it will print out the currently " "active source label and name.")) parser.add_argument( "--source-label", type=str, default=None, help=( "changes the label for a source. " "If you do not use --source to specify the source to change the " "label on. It will automatically default to the currently " "active source. If you set the label to 'state' it will print out " "the current label for a source if specified using --source or " "the currently active source")) parser.add_argument("--timeout", type=float, help="socket timeout in seconds (0 = no timeout)") parser.add_argument("--config-file", type=str, default=None, help="configuration file to load and/or save to") parser.add_argument("--start-app", help="start an application --start-app \"Netflix\"") parser.add_argument( "--app-metadata", help=( "pass options string of information the application " "can use when it starts up. And example would be the browser. " "To have it open directly to a specific URL you would enter: " "\"http\/\/www.some-web-address.com\". wrapping the meta data in " "quotes will reduce the possibility of a command line parser " "error.")) parser.add_argument( "--key-help", action="store_true", help="print available keys. (key support depends on tv model)") parser.add_argument("key", nargs="*", default=[], type=get_key, help="keys to be sent (e.g. KEY_VOLDOWN)") args = parser.parse_args() if args.quiet: log_level = logging.ERROR elif not args.verbose: log_level = logging.WARNING elif args.verbose == 1: log_level = logging.INFO else: log_level = logging.DEBUG if args.key_help: keys_help(args.key) try: if args.config_file is None: config = _read_config() config.update( {k: v for k, v in vars(args).items() if v is not None}) config = Config(**config) else: config = {k: v for k, v in vars(args).items() if v is not None} config = Config.load(args.config_file)(**config) except exceptions.ConfigError: import traceback traceback.print_exc() return config.log_level = log_level if config.upnp_locations is None: config.upnp_locations = [] if not config.host or not config.uuid: configs = discover(config.host) if len(configs) > 1: while True: for i, cfg in enumerate(configs): print(i + 1, ':', cfg.model) try: # noinspection PyCompatibility answer = raw_input( 'Enter the number of the TV you want to pair with:') except NameError: answer = input( 'Enter the number of the TV you want to pair with:') try: answer = int(answer) - 1 cfg = configs[answer] break except (TypeError, ValueError, IndexError): pass elif configs: cfg = configs[0] else: print('Unable to discover any TV\'s') exit_func(0) # this never actually happens it is only here to make my IDE happy raise RuntimeError else: cfg = config try: with Remote(cfg) as remote: if args.interactive: logging.getLogger().setLevel(logging.ERROR) from . import interactive inter = interactive.Interactive(remote) inter.run() exit_func(0) if (args.key and args.key[0] in ('KEY_POWER', 'KEY_POWERON') and cfg.paired and not remote.power): args.key.pop(0) import threading event = threading.Event() def callback(_, state): if state: event.set() auto_discover.register_callback(callback, cfg.uuid) remote.power = True event.wait(10.0) auto_discover.unregister_callback(callback, cfg.uuid) if not event.isSet(): print('Unable to send command TV is not powered on.') exit_func(1) if cfg.method == 'websocket' and args.start_app: app = remote.get_application(args.start_app) if args.app_metadata: app.run(args.app_metadata) else: app.run() else: for key in args.key: if key is None: continue key(remote) if args.volume is not None: if args.volume == -1: print('Volume:', remote.volume, '%') else: remote.volume = args.volume elif args.mute is not None: if args.mute == 'state': print('Mute:', 'ON' if remote.mute else 'OFF') else: remote.mute = args.mute == 'on' elif args.artmode is not None: if args.artmode == 'state': print('Art Mode:', 'ON' if remote.artmode else 'OFF') else: remote.artmode = args.artmode == 'on' if args.brightness is not None: if args.brightness == -1: print('Brightness:', remote.brightness, '%') else: remote.brightness = args.brightness if args.contrast is not None: if args.contrast == -1: print('Contrast:', remote.contrast, '%') else: remote.contrast = args.contrast if args.sharpness is not None: if args.sharpness == -1: print('Sharpness:', remote.sharpness, '%') else: remote.sharpness = args.sharpness if args.source_label is not None: if args.source is None: if args.source_label == 'state': print('Source Label:', remote.source.label) else: remote.source.label = args.remote_label else: for source in remote.sources: if args.source in (source.label, source.name): if args.source_label == 'state': print('Source Label:', source.label) else: source.label = args.source_label break elif args.source is not None: if args.source == 'state': source = remote.source print('Source: Label =', source.label, 'Name =', source.name) else: remote.source = args.source except exceptions.ConnectionClosed: logging.error("Error: Connection closed!") except exceptions.AccessDenied: logging.error("Error: Access denied!") except exceptions.ConfigUnknownMethod: logging.error("Error: Unknown method '{}'".format(cfg.method)) except socket.timeout: logging.error("Error: Timed out!") except OSError as e: logging.error("Error: %s", e.strerror) if args.config_file: cfg.save() exit_func(0)