Add support for DNS host names (#104)

This commit is contained in:
K Henriksson 2018-01-17 13:03:19 -08:00 committed by Teemu R
parent a426488449
commit d40fff4f9e
7 changed files with 37 additions and 31 deletions

View File

@ -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 <address>` as an option.
The device to which the commands are sent is chosen by `PYHS100_HOST` environment variable or passing `--host <address>` 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`,

View File

@ -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))

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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)

View File

@ -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