#!/usr/bin/env node 'use strict' const {exec} = require('child_process'); function execAsync(command, opts) { return new Promise((resolve, reject) => { exec(command, opts, (error, stdout, stderr) => { if (error) { reject(error); } else { resolve({stdout, stderr}); } }); }); } function sleep(n) { return new Promise((resolve) => setTimeout(resolve, n)); } async function findInterface() { const {stdout} = await execAsync('iw dev'); const lines = stdout.split('\n') .map((line) => line.trim()) .filter((line) => line.startsWith('Interface ')) .map((line) => line.split(' ')[1]); return lines[0]; } async function scanInterface(iface) { const {stdout} = await execAsync(`sudo iw dev ${iface} scan`); const results = []; let partial = null; for (let line of stdout.split('\n')) { if (line.startsWith('BSS ')) { finishPartial(); partial = {}; partial.bssid = line.match(/[a-z0-9:]+/)[0]; } line = line.trim() if (line.startsWith('SSID: ')) { partial.ssid = line.split(':')[1].trim(); } if (line.startsWith('signal: ')) { partial.signal = line.split(':')[1].trim(); } if (line.startsWith('DS Parameter set: channel')) { partial.channel = line.split(':')[1].trim(); } if (line.startsWith('freq: ')) { partial.freq = 'freq ' + line.split(':')[1].trim(); } } function finishPartial() { if (!partial) { return; } partial.ssid = partial.ssid || ''; partial.channel = partial.channel || partial.freq || ''; const sortKey = [ parseFloat(partial.signal), parseInt(partial.channel.split(' ')[1]) ]; results.push([sortKey, partial]); } return results .sort() .map(([, {bssid, ssid, signal, channel}]) => { ssid = ssid.padStart(40, ' '); channel = channel.padEnd(10, ' '); return `${signal} ${channel} ${ssid} ${bssid}`; }) .join('\n') + '\n'; } async function main() { const iface = await findInterface(); for (;;) { const scanResult = await scanInterface(iface).catch((err) => err.toString()); process.stdout.write('\x1b[2J\x1b[0f'); process.stdout.write(scanResult); await sleep(3000); } } main().catch((err) => { console.log('Unhandled error!', err); process.exit(1); });