Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 44 additions & 9 deletions kasa/cli/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,48 @@
_conditional_echo("Decrypted", pf(dr.decrypted_data) if dr.decrypted_data else None)


async def find_host_from_alias(alias, target="255.255.255.255", timeout=1, attempts=3):
async def find_dev_from_alias(
alias: str,
credentials: Credentials | None,
target: str = "255.255.255.255",
timeout: int = 5,
attempts: int = 3,
) -> Device | None:
"""Discover a device identified by its alias."""
for _attempt in range(1, attempts):
found_devs = await Discover.discover(target=target, timeout=timeout)
for _ip, dev in found_devs.items():
if dev.alias.lower() == alias.lower():
host = dev.host
return host

return None
found_event = asyncio.Event()
found_device = []
seen_hosts = set()

Check warning on line 252 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L250-L252

Added lines #L250 - L252 were not covered by tests

async def on_discovered(dev: Device):

Check warning on line 254 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L254

Added line #L254 was not covered by tests
if dev.host in seen_hosts:
return
seen_hosts.add(dev.host)
try:
await dev.update()
except Exception as ex:
echo(f"Error querying device {dev.host}: {ex}")
return

Check warning on line 262 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L256-L262

Added lines #L256 - L262 were not covered by tests
finally:
await dev.protocol.close()

Check warning on line 264 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L264

Added line #L264 was not covered by tests
if not dev.alias:
echo(f"Skipping device {dev.host} with no alias")
return

Check warning on line 267 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L266-L267

Added lines #L266 - L267 were not covered by tests
if dev.alias.lower() == alias.lower():
found_device.append(dev)
found_event.set()

Check warning on line 270 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L269-L270

Added lines #L269 - L270 were not covered by tests

async def do_discover():

Check warning on line 272 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L272

Added line #L272 was not covered by tests
for _ in range(1, attempts):
await Discover.discover(

Check warning on line 274 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L274

Added line #L274 was not covered by tests
target=target,
timeout=timeout,
credentials=credentials,
on_discovered=on_discovered,
)
if found_event.is_set():
break
found_event.set()

Check warning on line 282 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L281-L282

Added lines #L281 - L282 were not covered by tests

asyncio.create_task(do_discover())
await found_event.wait()
return found_device[0] if found_device else None

Check warning on line 286 in kasa/cli/discover.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/discover.py#L284-L286

Added lines #L284 - L286 were not covered by tests
28 changes: 15 additions & 13 deletions kasa/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,18 +275,6 @@
if alias is not None and host is not None:
raise click.BadOptionUsage("alias", "Use either --alias or --host, not both.")

if alias is not None and host is None:
echo(f"Alias is given, using discovery to find host {alias}")

from .discover import find_host_from_alias

host = await find_host_from_alias(alias=alias, target=target)
if host:
echo(f"Found hostname is {host}")
else:
echo(f"No device with name {alias} found")
return

if bool(password) != bool(username):
raise click.BadOptionUsage(
"username", "Using authentication requires both --username and --password"
Expand All @@ -299,7 +287,7 @@
else:
credentials = None

if host is None:
if host is None and alias is None:
if ctx.invoked_subcommand and ctx.invoked_subcommand != "discover":
error("Only discover is available without --host or --alias")

Expand All @@ -309,6 +297,7 @@
return await ctx.invoke(discover)

device_updated = False

if type is not None and type not in {"smart", "camera"}:
from kasa.deviceconfig import DeviceConfig

Expand Down Expand Up @@ -347,6 +336,19 @@
)
dev = await Device.connect(config=config)
device_updated = True
elif alias:
echo(f"Alias is given, using discovery to find host {alias}")

Check warning on line 340 in kasa/cli/main.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/main.py#L340

Added line #L340 was not covered by tests

from .discover import find_dev_from_alias

Check warning on line 342 in kasa/cli/main.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/main.py#L342

Added line #L342 was not covered by tests

dev = await find_dev_from_alias(

Check warning on line 344 in kasa/cli/main.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/main.py#L344

Added line #L344 was not covered by tests
alias=alias, target=target, credentials=credentials
)
if not dev:
echo(f"No device with name {alias} found")
return
echo(f"Found hostname by alias: {dev.host}")
device_updated = True

Check warning on line 351 in kasa/cli/main.py

View check run for this annotation

Codecov / codecov/patch

kasa/cli/main.py#L348-L351

Added lines #L348 - L351 were not covered by tests
else:
from .discover import discover

Expand Down
Loading