diff --git a/README.md b/README.md index 5efbc4d7..8d714119 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Python Library to control TPLink smart plugs/switches and smart bulbs. # Usage The package is shipped with a console tool named pyhs100, please refer to ```pyhs100 --help``` for detailed usage. -The device to which the commands are sent is chosen by `PYHS100_IP` environment variable or passing `--ip
` as an option. +The device to which the commands are sent is chosen by `PYHS100_HOST` environment variable or passing `--host ` as an option. To see what is being sent to and received from the device, specify option `--debug`. To avoid discovering the devices when executing commands its type can be passed by specifying either `--plug` or `--bulb`, diff --git a/pyHS100/cli.py b/pyHS100/cli.py index 65463f87..b4fb96d4 100644 --- a/pyHS100/cli.py +++ b/pyHS100/cli.py @@ -18,12 +18,17 @@ pass_dev = click.make_pass_decorator(SmartDevice) @click.group(invoke_without_command=True) -@click.option('--ip', envvar="PYHS100_IP", required=False) +@click.option('--ip', envvar="PYHS100_IP", required=False, + help='The IP address of the device to connect to. This option ' + 'is deprecated and will be removed in the future; use --host ' + 'instead.') +@click.option('--host', envvar="PYHS100_HOST", required=False, + help='The host name or IP address of the device to connect to.') @click.option('--debug/--normal', default=False) @click.option('--bulb', default=False, is_flag=True) @click.option('--plug', default=False, is_flag=True) @click.pass_context -def cli(ctx, ip, debug, bulb, plug): +def cli(ctx, ip, host, debug, bulb, plug): """A cli tool for controlling TP-Link smart home plugs.""" if debug: logging.basicConfig(level=logging.DEBUG) @@ -33,19 +38,22 @@ def cli(ctx, ip, debug, bulb, plug): if ctx.invoked_subcommand == "discover": return - if ip is None: - click.echo("No IP given, trying discovery..") + if ip is not None and host is None: + host = ip + + if host is None: + click.echo("No host name given, trying discovery..") ctx.invoke(discover) return - elif ip is not None: + else: if not bulb and not plug: click.echo("No --bulb nor --plug given, discovering..") - dev = Discover.discover_single(ip) + dev = Discover.discover_single(host) elif bulb: - dev = SmartBulb(ip) + dev = SmartBulb(host) elif plug: - dev = SmartPlug(ip) + dev = SmartPlug(host) else: click.echo("Unable to detect type, use --bulb or --plug!") return @@ -90,7 +98,7 @@ def state(ctx, dev): click.echo(click.style("Device state: %s" % "ON" if dev.is_on else "OFF", fg="green" if dev.is_on else "red")) - click.echo("IP address: %s" % dev.ip_address) + click.echo("Host/IP: %s" % dev.host) for k, v in dev.state_information.items(): click.echo("%s: %s" % (k, v)) click.echo(click.style("== Generic information ==", bold=True)) diff --git a/pyHS100/discover.py b/pyHS100/discover.py index e7cb1369..f04c5845 100644 --- a/pyHS100/discover.py +++ b/pyHS100/discover.py @@ -61,14 +61,14 @@ class Discover: return devices @staticmethod - def discover_single(ip_address: str, + def discover_single(host: str, protocol: TPLinkSmartHomeProtocol = None ) -> SmartDevice: """ - Similar to discover(), except only return device object for single - passed device given by IP address. + Similar to discover(), except only return device object for a single + host. - :param ip_address: IP address of device to query + :param host: Hostname of device to query :param protocol: Protocol implementation to use :rtype: SmartDevice :return: Object for querying/controlling found device. @@ -76,11 +76,11 @@ class Discover: if protocol is None: protocol = TPLinkSmartHomeProtocol() - info = protocol.query(ip_address, Discover.DISCOVERY_QUERY) + info = protocol.query(host, Discover.DISCOVERY_QUERY) device_class = Discover._get_device_class(info) if device_class is not None: - return device_class(ip_address) + return device_class(host) else: return None diff --git a/pyHS100/protocol.py b/pyHS100/protocol.py index 2fcff7a7..a950418f 100644 --- a/pyHS100/protocol.py +++ b/pyHS100/protocol.py @@ -32,7 +32,7 @@ class TPLinkSmartHomeProtocol: Request information from a TP-Link SmartHome Device and return the response. - :param str host: ip address of the device + :param str host: host name or ip address of the device :param int port: port on the device (default: 9999) :param request: command to send to the device (can be either dict or json string) @@ -41,10 +41,9 @@ class TPLinkSmartHomeProtocol: if isinstance(request, dict): request = json.dumps(request) - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(TPLinkSmartHomeProtocol.DEFAULT_TIMEOUT) + timeout = TPLinkSmartHomeProtocol.DEFAULT_TIMEOUT try: - sock.connect((host, port)) + sock = socket.create_connection((host, port), timeout) _LOGGER.debug("> (%i) %s", len(request), request) sock.send(TPLinkSmartHomeProtocol.encrypt(request)) diff --git a/pyHS100/smartbulb.py b/pyHS100/smartbulb.py index 43c16728..7aa4d9ea 100644 --- a/pyHS100/smartbulb.py +++ b/pyHS100/smartbulb.py @@ -42,9 +42,9 @@ class SmartBulb(SmartDevice): BULB_STATE_OFF = 'OFF' def __init__(self, - ip_address: str, + host: str, protocol: 'TPLinkSmartHomeProtocol' = None) -> None: - SmartDevice.__init__(self, ip_address, protocol) + SmartDevice.__init__(self, host, protocol) self.emeter_type = "smartlife.iot.common.emeter" self.emeter_units = True diff --git a/pyHS100/smartdevice.py b/pyHS100/smartdevice.py index e68b7a94..ffe8d5e9 100644 --- a/pyHS100/smartdevice.py +++ b/pyHS100/smartdevice.py @@ -40,15 +40,14 @@ class SmartDevice(object): ALL_FEATURES = (FEATURE_ENERGY_METER, FEATURE_TIMER) def __init__(self, - ip_address: str, + host: str, protocol: Optional[TPLinkSmartHomeProtocol] = None) -> None: """ - Create a new SmartDevice instance, identified through its IP address. + Create a new SmartDevice instance. - :param str ip_address: ip address on which the device listens + :param str host: host name or ip address on which the device listens """ - socket.inet_pton(socket.AF_INET, ip_address) - self.ip_address = ip_address + self.host = host if not protocol: protocol = TPLinkSmartHomeProtocol() self.protocol = protocol @@ -73,7 +72,7 @@ class SmartDevice(object): arg = {} try: response = self.protocol.query( - host=self.ip_address, + host=self.host, request={target: {cmd: arg}} ) except Exception as ex: @@ -523,7 +522,7 @@ class SmartDevice(object): def __repr__(self): return "<%s at %s (%s), is_on: %s - dev specific: %s>" % ( self.__class__.__name__, - self.ip_address, + self.host, self.alias, self.is_on, self.state_information) diff --git a/pyHS100/smartplug.py b/pyHS100/smartplug.py index 7161dbbd..a8e062f3 100644 --- a/pyHS100/smartplug.py +++ b/pyHS100/smartplug.py @@ -32,9 +32,9 @@ class SmartPlug(SmartDevice): SWITCH_STATE_UNKNOWN = 'UNKNOWN' def __init__(self, - ip_address: str, + host: str, protocol: 'TPLinkSmartHomeProtocol' = None) -> None: - SmartDevice.__init__(self, ip_address, protocol) + SmartDevice.__init__(self, host, protocol) self.emeter_type = "emeter" self.emeter_units = False