Skip to content

Commit

Permalink
Make cli interface more consistent (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
rytilahti committed Oct 9, 2021
1 parent c65705b commit e06b9a7
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 46 deletions.
1 change: 0 additions & 1 deletion .gitchangelog.rc

This file was deleted.

5 changes: 0 additions & 5 deletions .hound.yml

This file was deleted.

72 changes: 32 additions & 40 deletions kasa/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ async def cli(ctx, host, alias, target, debug, bulb, plug, lightstrip, strip):
else:
click.echo("Unable to detect type, use --strip or --bulb or --plug!")
return

await dev.update()
ctx.obj = dev

if ctx.invoked_subcommand is None:
Expand All @@ -106,6 +108,8 @@ async def scan(dev):
for dev in devs:
click.echo(f"\t {dev}")

return devs


@wifi.command()
@click.argument("ssid")
Expand All @@ -120,18 +124,7 @@ async def join(dev: SmartDevice, ssid, password, keytype):
f"Response: {res} - if the device is not able to join the network, it will revert back to its previous state."
)


@cli.command()
@click.option("--scrub/--no-scrub", default=True)
@click.pass_context
async def dump_discover(ctx, scrub):
"""Dump discovery information.
Useful for dumping into a file to be added to the test suite.
"""
click.echo(
"This is deprecated, use the script inside devtools to generate a devinfo file."
)
return res


@cli.command()
Expand All @@ -158,35 +151,30 @@ async def discover(ctx, timeout, discover_only, dump_raw):

async def find_host_from_alias(alias, target="255.255.255.255", timeout=1, attempts=3):
"""Discover a device identified by its alias."""
click.echo(
f"Trying to discover {alias} using {attempts} attempts of {timeout} seconds"
)
for attempt in range(1, attempts):
click.echo(f"Attempt {attempt} of {attempts}")
found_devs = await Discover.discover(target=target, timeout=timeout)
found_devs = found_devs.items()
for ip, dev in found_devs:
for ip, dev in found_devs.items():
if dev.alias.lower() == alias.lower():
host = dev.host
return host

return None


@cli.command()
@pass_dev
async def sysinfo(dev):
"""Print out full system information."""
await dev.update()
click.echo(click.style("== System info ==", bold=True))
click.echo(pf(dev.sys_info))
return dev.sys_info


@cli.command()
@pass_dev
@click.pass_context
async def state(ctx, dev: SmartDevice):
"""Print out device state and versions."""
await dev.update()
click.echo(click.style(f"== {dev.alias} - {dev.model} ==", bold=True))
click.echo(f"\tHost: {dev.host}")
click.echo(
Expand Down Expand Up @@ -234,7 +222,6 @@ async def state(ctx, dev: SmartDevice):
@click.option("--index", type=int)
async def alias(dev, new_alias, index):
"""Get or set the device (or plug) alias."""
await dev.update()
if index is not None:
if not dev.is_strip:
click.echo("Index can only used for power strips!")
Expand All @@ -244,8 +231,8 @@ async def alias(dev, new_alias, index):

if new_alias is not None:
click.echo(f"Setting alias to {new_alias}")
click.echo(await dev.set_alias(new_alias))
await dev.update()
res = await dev.set_alias(new_alias)
return res

click.echo(f"Alias: {dev.alias}")
if dev.is_strip:
Expand All @@ -264,9 +251,11 @@ async def raw_command(dev: SmartDevice, module, command, parameters):

if parameters is not None:
parameters = ast.literal_eval(parameters)

res = await dev._query_helper(module, command, parameters)
await dev.update() # TODO: is this needed?

click.echo(res)
return res


@cli.command()
Expand All @@ -280,7 +269,6 @@ async def emeter(dev: SmartDevice, year, month, erase):
Daily and monthly data provided in CSV format.
"""
click.echo(click.style("== Emeter ==", bold=True))
await dev.update()
if not dev.has_emeter:
click.echo("Device has no emeter")
return
Expand Down Expand Up @@ -324,15 +312,15 @@ async def emeter(dev: SmartDevice, year, month, erase):
@pass_dev
async def brightness(dev: SmartBulb, brightness: int, transition: int):
"""Get or set brightness."""
await dev.update()
if not dev.is_dimmable:
click.echo("This device does not support brightness.")
return

if brightness is None:
click.echo(f"Brightness: {dev.brightness}")
else:
click.echo(f"Setting brightness to {brightness}")
click.echo(await dev.set_brightness(brightness, transition=transition))
return await dev.set_brightness(brightness, transition=transition)


@cli.command()
Expand All @@ -343,10 +331,10 @@ async def brightness(dev: SmartBulb, brightness: int, transition: int):
@pass_dev
async def temperature(dev: SmartBulb, temperature: int, transition: int):
"""Get or set color temperature."""
await dev.update()
if not dev.is_variable_color_temp:
click.echo("Device does not support color temperature")
return

if temperature is None:
click.echo(f"Color temperature: {dev.color_temp}")
valid_temperature_range = dev.valid_temperature_range
Expand All @@ -359,7 +347,7 @@ async def temperature(dev: SmartBulb, temperature: int, transition: int):
)
else:
click.echo(f"Setting color temperature to {temperature}")
await dev.set_color_temp(temperature, transition=transition)
return await dev.set_color_temp(temperature, transition=transition)


@cli.command()
Expand All @@ -370,26 +358,28 @@ async def temperature(dev: SmartBulb, temperature: int, transition: int):
@click.pass_context
@pass_dev
async def hsv(dev, ctx, h, s, v, transition):
"""Get or set color in HSV. (Bulb only)."""
await dev.update()
"""Get or set color in HSV."""
if not dev.is_color:
click.echo("Device does not support colors")
return

if h is None or s is None or v is None:
click.echo(f"Current HSV: {dev.hsv}")
elif s is None or v is None:
raise click.BadArgumentUsage("Setting a color requires 3 values.", ctx)
else:
click.echo(f"Setting HSV: {h} {s} {v}")
click.echo(await dev.set_hsv(h, s, v, transition=transition))
return await dev.set_hsv(h, s, v, transition=transition)


@cli.command()
@click.argument("state", type=bool, required=False)
@pass_dev
async def led(dev, state):
"""Get or set (Plug's) led state."""
await dev.update()
if state is not None:
click.echo(f"Turning led to {state}")
click.echo(await dev.set_led(state))
return await dev.set_led(state)
else:
click.echo(f"LED state: {dev.led}")

Expand All @@ -398,7 +388,9 @@ async def led(dev, state):
@pass_dev
async def time(dev):
"""Get the device time."""
click.echo(await dev.get_time())
res = await dev.get_time()
click.echo(f"Current time: {res}")
return res


@cli.command()
Expand All @@ -408,19 +400,19 @@ async def time(dev):
@pass_dev
async def on(dev: SmartDevice, index: int, name: str, transition: int):
"""Turn the device on."""
await dev.update()
if index is not None or name is not None:
if not dev.is_strip:
click.echo("Index and name are only for power strips!")
return

dev = cast(SmartStrip, dev)
if index is not None:
dev = dev.get_plug_by_index(index)
elif name:
dev = dev.get_plug_by_name(name)

click.echo(f"Turning on {dev.alias}")
await dev.turn_on(transition=transition)
return await dev.turn_on(transition=transition)


@cli.command()
Expand All @@ -430,19 +422,19 @@ async def on(dev: SmartDevice, index: int, name: str, transition: int):
@pass_dev
async def off(dev: SmartDevice, index: int, name: str, transition: int):
"""Turn the device off."""
await dev.update()
if index is not None or name is not None:
if not dev.is_strip:
click.echo("Index and name are only for power strips!")
return

dev = cast(SmartStrip, dev)
if index is not None:
dev = dev.get_plug_by_index(index)
elif name:
dev = dev.get_plug_by_name(name)

click.echo(f"Turning off {dev.alias}")
await dev.turn_off(transition=transition)
return await dev.turn_off(transition=transition)


@cli.command()
Expand All @@ -451,7 +443,7 @@ async def off(dev: SmartDevice, index: int, name: str, transition: int):
async def reboot(plug, delay):
"""Reboot the device."""
click.echo("Rebooting the device..")
click.echo(await plug.reboot(delay))
return await plug.reboot(delay)


if __name__ == "__main__":
Expand Down

0 comments on commit e06b9a7

Please sign in to comment.