Skip to content

Commit 22d2ccb

Browse files
authored
Network scanning interface (#55)
* Implement network scanning * Bump minimum package versions
1 parent 2f7eec1 commit 22d2ccb

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ dependencies = [
1717
"click",
1818
"coloredlogs",
1919
"scapy",
20-
"zigpy>=0.55.0",
20+
"zigpy>=0.75.0",
2121
"bellows>=0.43.0",
2222
"zigpy-deconz>=0.21.0",
2323
"zigpy-xbee>=0.18.0",

zigpy_cli/radio.py

+63
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,66 @@ async def channel_hopper():
316316
+ b"\n"
317317
)
318318
output.flush()
319+
320+
321+
@radio.command()
322+
@click.pass_obj
323+
@click.option("-r", "--randomize", is_flag=True, type=bool, default=False)
324+
@click.option("-u", "--unfiltered", is_flag=True, type=bool, default=False)
325+
@click.option("-n", "--num-scans", type=int, default=-1)
326+
@click.option("-d", "--duration-exponent", type=int, default=4)
327+
@click.option(
328+
"-c",
329+
"--channels",
330+
type=CHANNELS_LIST,
331+
default=zigpy.types.Channels.ALL_CHANNELS,
332+
)
333+
@click_coroutine
334+
async def network_scan(
335+
app, randomize, unfiltered, num_scans, duration_exponent, channels
336+
):
337+
if app._network_scan is ControllerApplication._network_scan:
338+
raise click.ClickException("Network scan is not supported by this radio")
339+
340+
await app.startup()
341+
LOGGER.info("Running scan...")
342+
343+
seen_beacons = set()
344+
345+
if randomize:
346+
347+
def channels_iter_func():
348+
while True:
349+
yield random.choice(tuple(channels))
350+
351+
channels_iter = channels_iter_func()
352+
else:
353+
channels_iter = itertools.cycle(channels)
354+
355+
for scan in itertools.count():
356+
channel = next(channels_iter)
357+
358+
if num_scans != -1 and scan > num_scans:
359+
break
360+
361+
print(f"Scanning channel {channel}\r", end="", flush=True)
362+
363+
async for network in app.network_scan(
364+
channels=zigpy.types.Channels.from_channel_list([channel]),
365+
duration_exp=duration_exponent,
366+
):
367+
key = network.replace(lqi=None, rssi=None)
368+
369+
if key in seen_beacons:
370+
continue
371+
372+
seen_beacons.add(key)
373+
374+
print(
375+
f"channel: {network.channel}, "
376+
f"network: {network.pan_id} ({network.extended_pan_id}), "
377+
f"permitting joins: {int(network.permit_joining)}, "
378+
f"nwk update id: {network.nwk_update_id}, "
379+
f"lqi: {network.lqi:>4}, "
380+
f"rssi: {network.rssi:>3}"
381+
)

0 commit comments

Comments
 (0)