Compare commits

..

No commits in common. "master" and "v0.0.4" have entirely different histories.

18 changed files with 303 additions and 3543 deletions

1
.gitignore vendored
View File

@ -1,3 +1,2 @@
.idea .idea
node_modules node_modules
/yarn.lock

View File

@ -1,8 +0,0 @@
language: node_js
branches:
only:
- master
- develop
node_js:
- "10"
- "11"

View File

@ -1,47 +1,4 @@
# Fork of node-wifi-scanner #node-wifi-scanner
This fork is used to add the ability to scan as sudo under linux.
Why the fork?
- Add ability to execute command with prefix 'sudo' to get iwlist working on linux!
- Uses promise instead of callback in module exports to make it easier and prevent callback hells.
- Add `encrypted:boolean` to the output, to determine if the network is encrypted (Currently only works under iwlist/linux, otherwise just returns false)
To use sudo, just pass `true` to the scan method and it will use sudo.
For ex.
```js
const wifiScan = require("node-wifi-scanner");
let result = await wifiScan.scan(true);
```
Beforehand you should add the iwlist scan command to the sudoers file.
`%mygroup ALL = (root) NOPASSWD: iwlist wlanX scan` [src](https://stackoverflow.com/questions/53710368/how-do-i-add-typescript-types-to-a-javascript-module-without-switching-to-typesc)
### Installation
`yarn add git+https://github.com/Tobstr02/node-wifi-scanner.git`
or `npm install git+https://github.com/Tobstr02/node-wifi-scanner.git`
### Type definitions
I also tried to add type definitions (see /types/index.d.ts), but as far as i know i did it wrong haha.
Since this is my first ever module (-fork) i don't really know how to do it. - Let me know in the issues tab or create a pull request :)
But i added jsdoc to the functions to add the ability to make the coding process a bit cleaner.
<br>
<i>Fork from: [Node-Wifi-Scanner Github](https://github.com/ancasicolica/node-wifi-scanner/)</i>
<br><br>
----
# Node-Wifi-Scanner
[![Build Status](https://travis-ci.org/ancasicolica/node-wifi-scanner.svg?branch=master)](https://travis-ci.org/ancasicolica/node-wifi-scanner)
[![npm](https://img.shields.io/npm/v/node-wifi-scanner.svg)]()
[![npm](https://img.shields.io/npm/dt/node-wifi-scanner.svg)](https://www.npmjs.com/package/node-wifi-scanner)
This module for node.js scans available wifi networks. The main purpose was to enhance my node.js based This module for node.js scans available wifi networks. The main purpose was to enhance my node.js based
[ZigBee Site Survey Tool](http://ancasicolica.github.io/ZigBeeSiteSurvey/) with WiFi coexistence charts. This tool [ZigBee Site Survey Tool](http://ancasicolica.github.io/ZigBeeSiteSurvey/) with WiFi coexistence charts. This tool
@ -52,27 +9,38 @@ The module was inspired from Maurice Sways "[node-wifiscanner](https://github.co
had to handle much more complex network environments and also wanted to be independent of the operating had to handle much more complex network environments and also wanted to be independent of the operating
system language. The adaptions needed would have been too comprehensive for a pull request so I decided to write an own module. system language. The adaptions needed would have been too comprehensive for a pull request so I decided to write an own module.
**The module is currently in BETA testing, changes in functionality and interface are possible. Please report bugs on the projects GitHub page, Thanks!**
## Operating Systems ## Operating Systems
It was tested with the following operating systems: It was tested with the following operating systems:
* Mac OS-X [Not tested by fork author] * Mac OS-X
* Windows 10 [Not tested by fork author] * Windows 10
* Ubuntu 14.04 [Tested by fork author] * Ubuntu 14.04
* Raspbian "Jessie" [Tested by fork author] * Raspbian "Jessie"
## Installation ## Installation
yarn add git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner npm i node-wifi-scanner
## Usage ## Usage
const scanner = require('node-wifi-scanner');
scanner.scan((err, networks) => {
if (err) {
console.error(err);
return;
}
console.log(networks);
});
The tool returns an array with objects, each object representing a network with the following properties: The tool returns an array with objects, each object representing a network with the following properties:
* channel: WiFi channel * channel: WiFi channel
* ssid: SSID of the network (if available) * ssid: SSID of the network (if available)
* mac: MAC Address of the network access point (if available, otherwise empty string) * mac: MAC Address of the network access point
* rssi: signal strength * rssi: signal strength
* encrypted: boolean - Is network encrypted?
In contrary to other wifi scanners no information about security is returned. This is due to the very different implementation In contrary to other wifi scanners no information about security is returned. This is due to the very different implementation
of the command line tools which do not allow a flawless detection. of the command line tools which do not allow a flawless detection.
@ -83,34 +51,18 @@ The module uses command line tools for gathering the network information:
* airport on Mac OS-X: `airport -s` * airport on Mac OS-X: `airport -s`
* netsh on Windows: `netsh wlan show networks mode=Bssid` * netsh on Windows: `netsh wlan show networks mode=Bssid`
* iwlist on Linux: `iwlist scan` * iwlist (1st choice) on Linux: `iwlist scan`
* nmcli (fallback only) on Linux: `nmcli -m tabular -f SSID,BSSID,SIGNAL,FREQ device wifi`
Unfortunately, Mac OS-X and Windows use the system language for the output which requires a quite Unfortunately, Mac OS-X and Windows use the system language for the output which requires a quite
generic way of parsing the data. If you experience any troubles, please create a GitHub issue and supply generic way of parsing the data. If you experience any troubles, please create a GitHub issue and supply
the output of the tool. the output of the tool.
## Limits of the tool
There is no such thing as perfect software and this is all the more true when the tools used require different
access rights depending on
the operating system. Please note the following restrictions
before using this tool in a productive system.
**Linux**: iwlist does only return all found networks if run as sudo! Otherwise you'll
get only the network you're connected to. <i>That's where my fork comes in!!</i>
**Windows**: there are some network cards which do not
return the MAC address and other parameters of the found networks. In this case
the "found" networks are ignored as there is no valuable data. If you have this effect
on your system, please provide as many information about your system (PC manufacturer, network
card, OS,...) as available. Thanks
## Licence ## Licence
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2016-2024 Christian Kuster, Tobias Hopp Copyright (c) 2016 Christian Kuster
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -129,4 +81,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

View File

@ -5,7 +5,7 @@
* Created by kc on 04.04.16. * Created by kc on 04.04.16.
*/ */
const scanner = require('../index'); var scanner = require('../index');
scanner.scan((err, output) => { scanner.scan((err, output) => {
if (err) { if (err) {

138
index.js
View File

@ -1,143 +1,73 @@
/**
* @typedef {Object} WifiNetwork
* @property {string} ssid - SSID of the wifi
* @property {string} mac - MAC-Address of the wifi
* @property {number} channel - Channel of the wifi
* @property {number} rssi - Signalstrength of Wifi-Network (RSSI)
* @property {boolean} encrypted - Encrypted
*/
/** /**
* node-wifi-scanner * node-wifi-scanner
* Created by kc on 04.04.16. - Forked and updated by Tobias Hopp 27.03.2024 * Created by kc on 04.04.16.
*/ */
const {exec, spawn} = require('child_process'); const fs = require('fs');
const exec = require('child_process').exec;
const async = require('async');
const _ = require('lodash');
// The tools // The tools
const airport = require('./lib/airport'); const airport = require('./lib/airport');
const iwlist = require('./lib/iwlist'); const iwlist = require('./lib/iwlist');
const nmcli = require('./lib/nmcli');
const netsh = require('./lib/netsh'); const netsh = require('./lib/netsh');
let scanner; var scanner;
// Initializing the tools // Initializing the tools
function initTools(callback) { function initTools(callback) {
fs.stat(airport.tool, function (err, stats) {
if (stats) {
return callback(null, airport);
}
// When a command is not found, an error is issued and async would finish. Therefore we pack fs.stat(iwlist.tool, function (err, stats) {
// the error into the result and check it later on. if (stats) {
async.parallel([ return callback(null, iwlist);
function (cb) {
exec(airport.detector, function (err) {
cb(null, {err: err, scanner: airport}
)
} }
);
},
function (cb) {
exec(iwlist.detector, function (err) {
cb(null, {err: err, scanner: iwlist}
)
}
);
},
function (cb) {
exec(netsh.detector, function (err) {
cb(null, {err: err, scanner: netsh}
)
}
);
}
],
function (err, results) {
let res = _.find(results,
function (f) {
return !f.err
});
if (res) { fs.stat(nmcli.tool, function (err, stats) {
return callback(null, res.scanner); if (stats) {
return callback(null, nmcli);
} }
fs.stat(netsh.tool, function (err, stats) {
if (stats) {
return callback(null, netsh);
}
callback(new Error('No scanner found')); callback(new Error('No scanner found'));
}
);
}
/**
* Scan the networks with the scanner detected before
* @param {Function|any} callback
* @param {boolean} useSudo - Use sudo for access?
*/
function scanNetworks(callback, useSudo) {
const cmd = scanner.cmdLine.split(" ");
let args = cmd.slice(1);
if(useSudo)
args.unshift(cmd[0]);
const child = spawn(useSudo ? "sudo" : cmd[0], args, { stdio: ['ignore', 'pipe', 'pipe'], detached: true });
child.on("error", (err) => callback(err, null) );
let stdoutData = '';
child.stdout.on('data', (data) => {
stdoutData += data;
}); });
child.on('close', (code) => {
if (code === 0) {
// Prozess erfolgreich beendet, Ausgabe verarbeiten
scanner.parseOutput(stdoutData, callback);
} else {
// Prozess mit Fehler beendet
callback(new Error(`Exited with code ${code}`), null);
}
}); });
});
});
}
/*exec((useSudo ? "sudo ":"") + scanner.cmdLine, { shell: true }, function (err, stdout) { function scanNetworks(callback) {
exec(scanner.cmdLine, function (err, stdout) {
if (err) { if (err) {
callback(err, null); callback(err, null);
return; return;
} }
scanner.parseOutput(stdout, callback); scanner.parseOutput(stdout, callback);
});*/ });
} }
module.exports = { module.exports = {
/** /**
* Scan for wifi networks * Scan for wifis
* @param {boolean} useSudo? - Defaults to false | Should sudo be used to get the output? * @param callback
* @return {Promise<WifiNetwork[]|null>} WiFinetwork Array or null
* @rejects Returns error on reject
*/ */
scan: function (useSudo = false) { scan: function (callback) {
return new Promise( (resolve, reject) => {
if (!scanner) { if (!scanner) {
initTools(function (err, s) { initTools((err, s) => {
if (err) { if (err) {
return reject(err); return callback(err);
} }
scanner = s; scanner = s;
scanNetworks((err, result) => { scanNetworks(callback);
if(err)
return reject(err);
if(!result)
result = [];
resolve(result);
}, useSudo && scanner == iwlist);
}); });
return; return;
} }
scanNetworks((err, result) => { scanNetworks(callback);
if(err)
return reject(err);
if(!result)
result = [];
resolve(result);
}, useSudo && scanner == iwlist);
} );
} }
}; };

View File

@ -5,44 +5,45 @@
const tool = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport'; const tool = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport';
const cmdLine = tool + ' -s'; const cmdLine = tool + ' -s';
const detector = tool + ' -getInfo';
const macRegex = /([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}/;
/** /**
* Parsing the output of airport (Mac OS X) * Parsing the output of airport (Mac OS X)
* @param str output of the tool * @param str output of the tool
* @param callback * @param callback
*/ */
function parseOutput(str, callback) { function parseOutput(str, callback) {
let err = null; var err = null;
let wifis = [];
try { try {
let lines = str.split('\n'); var lines = str.split('\n');
var wifis = [];
for (let i = 1, l = lines.length; i < l; i++) { for (var i = 1, l = lines.length; i < l; i++) {
if (lines[i] === '') continue; var mac = lines[i].match(macRegex);
let elements = lines[i].substring(51).split(/[ ]+/); if (!mac) {
continue;
}
var macStart = lines[i].indexOf(mac[0]);
var elements = lines[i].substr(macStart).split(/[ ]+/);
wifis.push({ wifis.push({
'ssid' : lines[i].substring(0, 32).trim(), 'ssid' : lines[i].substr(0, macStart).trim(),
'mac' : '', // There is no more mac on a mac 'mac' : elements[0].trim(),
'channel': parseInt(elements[1].trim(), 10), 'channel' : parseInt(elements[2].trim(), 10),
'rssi' : parseInt(elements[0].trim(), 10), 'rssi' : parseInt(elements[1].trim())
'encrypted': false,
}); });
} }
} }
catch (ex) { catch (ex) {
err = ex; err = ex;
} }
finally {
callback(err, wifis); callback(err, wifis);
} }
}
module.exports = { module.exports = {
parseOutput: parseOutput, parseOutput: parseOutput,
cmdLine : cmdLine, cmdLine : cmdLine,
detector : detector,
tool : tool tool : tool
}; };

View File

@ -4,33 +4,26 @@
*/ */
const _ = require('lodash'); const _ = require('lodash');
// usually located in /usr/bin/ but as it could be at another location, allow all found in PATH (but we're in trouble const tool = '/usr/bin/iwlist';
// when the default location, /usr/bin/ is not in the PATH!). GitHub issue #1
const tool = 'iwlist';
const cmdLine = tool + ' scan'; const cmdLine = tool + ' scan';
const detector = tool + ' --help';
const macRegex = /([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}/; const macRegex = /([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}/;
const cellRegex = /Cell [0-9]{2,} - Address:/; const cellRegex = /Cell [0-9]{2,} - Address:/;
const encryptedRegex = /Encryption key:on/g;
/** /**
* Parsing the output of iwlist, tool having a lot of different faces :-( * Parsing the output of iwlist, tool having a lot of different faces :-(
* @param str output of the tool * @param str output of the tool
* @param callback * @param callback
*/ */
function parseOutput(str, callback) { function parseOutput(str, callback) {
let err = null; var err = null;
let wifis = []; var wifis = [];
try { try {
let blocks = str.split(cellRegex); var blocks = str.split(cellRegex);
blocks.forEach(block => { blocks.forEach(block => {
let network = {encrypted: encryptedRegex.test(block)}; var network = {};
var lines = block.split('\n');
let lines = block.split('\n');
if (macRegex.exec(lines[0])) { if (macRegex.exec(lines[0])) {
// First line is the mac address (always! (?)) // First line is the mac address (always! (?))
network.mac = lines[0].trim(); network.mac = lines[0].trim();
@ -46,8 +39,8 @@ function parseOutput(str, callback) {
} }
// Channel, an ugly thing to get it // Channel, an ugly thing to get it
else if (_.startsWith(line.trim(), 'Channel:')) { else if (_.startsWith(line.trim(), 'Frequency:')) {
network.channel = parseInt(_.trim(line, ' )').split(/:/)[1]); network.channel = parseInt(_.trim(line, ' )').split(/Channel/)[1], 10);
} }
// Another ugly thing, the signal which can have different formats, even worse als // Another ugly thing, the signal which can have different formats, even worse als
@ -56,14 +49,15 @@ function parseOutput(str, callback) {
if (line.indexOf('Quality') > -1) { if (line.indexOf('Quality') > -1) {
// This is a "Quality=40/70 Signal level=-70 dBm" line // This is a "Quality=40/70 Signal level=-70 dBm" line
network.rssi = parseInt(line.substr(line.indexOf('Signal level') + 13), 10); network.rssi = parseInt(line.substr(line.indexOf('Signal level') + 13), 10);
} else { }
else {
// This is a "Signal level=60/100" line // This is a "Signal level=60/100" line
let elements = line.split('='); var elements = line.split('=');
elements.forEach(e => { elements.forEach(e => {
if (e.indexOf('/') > 0) { if (e.indexOf('/') > 0) {
// that's our part // that's our part
let parts = e.split('/'); var parts = e.split('/');
let level = Math.floor(100 * parseInt(parts[0], 10) / parseInt(parts[1], 10)); var level = Math.floor(100 * parseInt(parts[0], 10) / parseInt(parts[1], 10));
network.rssi = level / 2 - 100; network.rssi = level / 2 - 100;
} }
}) })
@ -85,6 +79,5 @@ function parseOutput(str, callback) {
module.exports = { module.exports = {
parseOutput: parseOutput, parseOutput: parseOutput,
cmdLine : cmdLine, cmdLine : cmdLine,
detector : detector,
tool : tool tool : tool
}; };

View File

@ -6,7 +6,6 @@
const systemRoot = process.env.SystemRoot || 'C:\\Windows'; const systemRoot = process.env.SystemRoot || 'C:\\Windows';
const tool = systemRoot + '\\System32\\netsh.exe'; const tool = systemRoot + '\\System32\\netsh.exe';
const cmdLine = tool + ' wlan show networks mode=Bssid'; const cmdLine = tool + ' wlan show networks mode=Bssid';
const detector = tool + ' show alias';
/** /**
* Parsing netnsh output. Unfortunately netsh supplies the network information * Parsing netnsh output. Unfortunately netsh supplies the network information
@ -15,17 +14,13 @@ const detector = tool + ' show alias';
* an approach of analyzing the structure of the output * an approach of analyzing the structure of the output
*/ */
function parseOutput(str, callback) { function parseOutput(str, callback) {
let blocks = str.split('\n\n'); var blocks = str.split('\n\n');
let wifis = []; var wifis = [];
let err = null; var err = null;
try { try {
if (blocks.length < 2) {
// 2nd try, with \r\n
blocks = str.split('\r\n\r\n')
}
if (!blocks || blocks.length === 1) { if (!blocks || blocks.length === 1) {
// No WiFis found // No WiFis found
return callback(null, []); return [];
} }
// Each block has the same structure, while some parts might be available and others // Each block has the same structure, while some parts might be available and others
@ -40,18 +35,18 @@ function parseOutput(str, callback) {
// Channel : 6 // Channel : 6
// Basic rates (MBit/s) : 1 2 5.5 11 // Basic rates (MBit/s) : 1 2 5.5 11
// Other rates (MBit/s) : 6 9 12 18 24 36 48 54 // Other rates (MBit/s) : 6 9 12 18 24 36 48 54
for (let i = 1, l = blocks.length; i < l; i++) { for (var i = 1, l = blocks.length; i < l; i++) {
let network = {encrypted: false}; var network = {};
let lines = blocks[i].split('\n'); var lines = blocks[i].split('\n');
let regexChannel = /[a-zA-Z0-9()\s]+:[\s]*[0-9]+$/g; var regexChannel = /[a-zA-Z0-9()\s]+:[\s]*[0-9]+$/g;
if (!lines || lines.length < 2) { if (!lines || lines.length < 2) {
continue; continue;
} }
// First line is always the SSID (which can be empty) // First line is always the SSID (which can be empty)
let ssid = lines[0].substring(lines[0].indexOf(':') + 1).trim(); var ssid = lines[0].substring(lines[0].indexOf(':') + 1).trim();
for (let t = 1, n = lines.length; t < n; t++) { for (var t = 1, n = lines.length; t < n; t++) {
if (lines[t].split(':').length === 7) { if (lines[t].split(':').length === 7) {
// This is the mac address, use this one as trigger for a new network // This is the mac address, use this one as trigger for a new network
if (network.mac) { if (network.mac) {
@ -61,16 +56,18 @@ function parseOutput(str, callback) {
ssid: ssid, ssid: ssid,
mac : lines[t].substring(lines[t].indexOf(':') + 1).trim() mac : lines[t].substring(lines[t].indexOf(':') + 1).trim()
}; };
} else if (lines[t].indexOf('%') > 0) { }
else if (lines[t].indexOf('%') > 0) {
// Network signal strength, identified by '%' // Network signal strength, identified by '%'
let level = parseInt(lines[t].split(':')[1].split('%')[0].trim(), 10); var level = parseInt(lines[t].split(':')[1].split('%')[0].trim(), 10);
network.rssi = (level / 2) - 100; network.rssi = (level / 2) - 100;
} else if (!network.channel) { }
else if (!network.channel) {
// A tricky one: the channel is the first one having just ONE number. Set only // A tricky one: the channel is the first one having just ONE number. Set only
// if the channel is not already set ("Basic Rates" can be a single number also) // if the channel is not already set ("Basic Rates" can be a single number also)
if (regexChannel.exec(lines[t].trim())) { if (regexChannel.exec(lines[t].trim())) {
network.channel = parseInt(lines[t].split(':')[1].trim(), 10); network.channel = parseInt(lines[t].split(':')[1].trim());
} }
} }
} }
@ -89,6 +86,5 @@ function parseOutput(str, callback) {
module.exports = { module.exports = {
parseOutput: parseOutput, parseOutput: parseOutput,
cmdLine : cmdLine, cmdLine : cmdLine,
detector : detector,
tool : tool tool : tool
}; };

50
lib/nmcli.js Normal file
View File

@ -0,0 +1,50 @@
/**
* Scanning WiFis on Mac OS X using nmcli
* Created by kc on 04.04.16.
*/
const _ = require('lodash');
const tool = '/usr/bin/nmcli';
const cmdLine = tool + ' -m tabular -f SSID,BSSID,SIGNAL,FREQ device wifi';
const macRegex = /([0-9a-zA-Z]{1}[0-9a-zA-Z]{1}[:]{1}){5}[0-9a-zA-Z]{1}[0-9a-zA-Z]{1}/;
/**
* Parsing the output of nmcli
* @param str output of the tool
* @param callback
*/
function parseOutput(str, callback) {
var err = null;
try {
var lines = str.split('\n');
var wifis = [];
for (var i = 1, l = lines.length; i < l; i++) {
var mac = lines[i].match(macRegex);
if (!mac) {
continue;
}
var macStart = lines[i].indexOf(mac[0]);
var elements = lines[i].substr(macStart).split(/[ ]+/);
wifis.push({
'ssid' : _.trim(lines[i].substr(0, macStart), ' \''),
'mac' : elements[0].trim(),
'channel' : parseInt(elements[2].trim(), 10),
'rssi' : parseInt(elements[1].trim())
});
}
}
catch (ex) {
err = ex;
}
callback(err, wifis);
}
module.exports = {
parseOutput: parseOutput,
cmdLine : cmdLine,
tool : tool
};

3219
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,23 @@
{ {
"name": "node-wifi-scanner", "name": "node-wifi-scanner",
"version": "1.1.3", "version": "0.0.4",
"description": "node.js module for WiFi network detection", "description": "node.js module for WiFi network detection",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
"WiFi", "WiFi",
"Node.js", "Node.js",
"scanner", "scanner"
"airport",
"netsh",
"iwlist",
"nmcli"
], ],
"author": { "author": {
"name": "Christian Kuster, Tobias Hopp", "name": "Christian Kuster, CH-8342 Wernetshausen",
"email": "tobi@gaminggeneration.de" "email": "info@kusti.ch",
}, "url": "http://www.kusti.ch/"
"homepage": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner/",
"bugs": {
"url": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner/issues/",
"email": "info@ancasicolica.ch"
}, },
"homepage": "http://www.ferropoly.ch/",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner.git" "url": "https://github.com/ancasicolica/node-wifi-scanner.git"
}, },
"engines": { "engines": {
"node": ">= 4.0.0", "node": ">= 4.0.0",
@ -34,12 +27,10 @@
"test": "mocha test" "test": "mocha test"
}, },
"dependencies": { "dependencies": {
"async": "3.2.4", "lodash": "4.8.1"
"lodash": "4.17.21"
}, },
"devDependencies": { "devDependencies": {
"grunt": "1.5.3", "grunt": "0.4.5",
"grunt-bump": "0.8.0", "grunt-bump": "0.7.0"
"mocha": "10.2.0"
} }
} }

67
test/airport.js Normal file
View File

@ -0,0 +1,67 @@
/**
* Airport unit test
* Created by kc on 04.04.16.
*/
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const airport = require('../lib/airport');
describe('airport', () => {
it('parses the output of file 1', function(done) {
airport.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures','airport','airport01.txt'), { encoding: 'utf8' }), (err, info) => {
assert.ok(info);
assert.equal(info.length, 36);
var ap = info[0];
assert.equal(ap.mac, '00:35:1a:90:56:03');
assert.equal(ap.ssid, 'OurTest');
assert.equal(ap.rssi, -70);
assert.strictEqual(ap.channel, 112);
ap = info[19];
assert.equal(ap.mac, '00:35:1a:5b:45:b6');
assert.equal(ap.ssid, 'PDANet1');
assert.equal(ap.rssi, -78);
assert.strictEqual(ap.channel, 11);
ap = info[25];
assert.equal(ap.mac, '10:bd:18:ab:4d:8f');
assert.equal(ap.ssid, 'TEST Training');
assert.equal(ap.rssi, -71);
assert.strictEqual(ap.channel, 6);
ap = info[35];
assert.equal(ap.mac, '00:35:1a:90:56:00');
assert.equal(ap.ssid, 'TEST-Wifi');
assert.equal(ap.rssi, -67);
assert.strictEqual(ap.channel, 1);
done(err);
});
});
it('parses the output of file 2', function(done) {
airport.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures','airport','airport02.txt'), { encoding: 'utf8' }), (err, info) => {
assert.ok(info);
assert.equal(info.length, 4);
var ap = info[0];
assert.equal(ap.mac, '7c:b7:33:ae:3b:06');
assert.equal(ap.ssid, 'Raupo');
assert.equal(ap.rssi, -80);
assert.strictEqual(ap.channel, 64);
ap = info[3];
assert.equal(ap.mac, '7c:b7:33:ae:3b:04');
assert.equal(ap.ssid, 'Visitor Raupo');
assert.equal(ap.rssi, -66);
assert.strictEqual(ap.channel, 9);
done(err);
});
});
});

View File

@ -1,5 +1,5 @@
SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group) SSID BSSID RSSI CHANNEL HT CC SECURITY (auth/unicast/group)
OurTest -70 112 Y CH WPA2(PSK/AES/AES) OurTest 00:35:1a:90:56:03 -70 112 Y CH WPA2(PSK/AES/AES)
OurDev 00:35:1a:90:56:04 -70 112 Y CH WPA2(PSK/AES/AES) OurDev 00:35:1a:90:56:04 -70 112 Y CH WPA2(PSK/AES/AES)
PDANet1 00:35:1a:90:56:09 -70 112 Y CH WPA2(PSK/AES/AES) PDANet1 00:35:1a:90:56:09 -70 112 Y CH WPA2(PSK/AES/AES)
TEST-Wifi 00:35:1a:90:56:0f -70 112 Y CH WPA2(PSK/AES/AES) TEST-Wifi 00:35:1a:90:56:0f -70 112 Y CH WPA2(PSK/AES/AES)

20
test/fixtures/nmcli/nmcli01.txt vendored Normal file
View File

@ -0,0 +1,20 @@
SSID BSSID SIGNAL FREQUENZ
'PDANet1' 00:35:1A:90:56:06 100 2412 MHz
'ExoNet1' 00:35:1A:90:56:05 100 2412 MHz
'TEST-Wifi' 00:35:1A:90:56:00 96 2412 MHz
'OurTest' 00:35:1A:90:56:0C 96 2412 MHz
'OurDev' 00:35:1A:90:56:0B 76 2412 MHz
'PDANet1' 00:35:1A:6F:0F:46 48 2437 MHz
'TEST-Wifi' 00:35:1A:6F:0F:40 58 2437 MHz
'ExoNet1' 00:35:1A:6F:0F:45 58 2437 MHz
'OurDev' 00:35:1A:6F:0F:4B 58 2437 MHz
'OurTest' 00:35:1A:6F:0F:4C 60 2437 MHz
'TEST-Wifi' 00:F2:8B:8F:58:70 58 2462 MHz
'ExoNet1' 00:F2:8B:8F:58:75 72 2462 MHz
'PDANet1' 00:F2:8B:8F:58:76 58 2462 MHz
'PDANet1' 00:35:1A:5B:46:76 56 2412 MHz
'OurDev' 00:35:1A:5B:46:7B 48 2412 MHz
'OurDev' 00:F2:8B:8F:58:7B 58 2462 MHz
'OurTest' 00:F2:8B:8F:58:7C 72 2462 MHz
'TEST-Wifi' 00:35:1A:5B:46:70 56 2412 MHz
'OurTest' 00:35:1A:5B:46:7C 48 2412 MHz

View File

@ -22,7 +22,7 @@ describe('iwlist', () => {
assert.ok(info); assert.ok(info);
let ap = info[0]; var ap = info[0];
assert.equal(ap.mac, 'D4:D1:84:50:76:45'); assert.equal(ap.mac, 'D4:D1:84:50:76:45');
assert.equal(ap.ssid, 'gsy-97796'); assert.equal(ap.ssid, 'gsy-97796');
assert.equal(ap.rssi, -76); assert.equal(ap.rssi, -76);
@ -40,7 +40,7 @@ describe('iwlist', () => {
iwlist.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures','iwlist','iwlist03_raspi.txt'), { encoding: 'utf8' }), (err, info) => { iwlist.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures','iwlist','iwlist03_raspi.txt'), { encoding: 'utf8' }), (err, info) => {
assert.ok(info); assert.ok(info);
let ap = info[0]; var ap = info[0];
assert.equal(ap.mac, '00:35:1A:90:56:00'); assert.equal(ap.mac, '00:35:1A:90:56:00');
assert.equal(ap.ssid, 'LORA-Wifi'); assert.equal(ap.ssid, 'LORA-Wifi');
assert.equal(ap.rssi, -71); assert.equal(ap.rssi, -71);

View File

@ -16,7 +16,7 @@ describe('netsh', function () {
assert.ok(info); assert.ok(info);
assert.equal(info.length, 86); assert.equal(info.length, 86);
let ap = info[0]; var ap = info[0];
assert.equal(ap.mac, '00:f2:8b:8c:a6:88'); assert.equal(ap.mac, '00:f2:8b:8c:a6:88');
assert.equal(ap.ssid, ''); assert.equal(ap.ssid, '');
assert.equal(ap.rssi, -88.5); assert.equal(ap.rssi, -88.5);
@ -55,7 +55,7 @@ describe('netsh', function () {
assert.ok(info); assert.ok(info);
assert.equal(info.length, 86); assert.equal(info.length, 86);
let ap = info[0]; var ap = info[0];
assert.equal(ap.mac, '00:f2:8b:8c:a6:88'); assert.equal(ap.mac, '00:f2:8b:8c:a6:88');
assert.equal(ap.ssid, ''); assert.equal(ap.ssid, '');
assert.equal(ap.rssi, -88.5); assert.equal(ap.rssi, -88.5);
@ -93,8 +93,8 @@ describe('netsh', function () {
netsh.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures', 'netsh', 'netsh_sp.txt'), {encoding: 'utf8'}), (err, info) => { netsh.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures', 'netsh', 'netsh_sp.txt'), {encoding: 'utf8'}), (err, info) => {
assert.ok(info); assert.ok(info);
assert.equal(info.length, 8); assert.equal(info.length, 8);
console.log(info);
let ap = info[0]; var ap = info[0];
assert.equal(ap.mac, '98:fc:11:b6:88:9e'); assert.equal(ap.mac, '98:fc:11:b6:88:9e');
assert.equal(ap.ssid, 'CARAMANZANAS_BAJA'); assert.equal(ap.ssid, 'CARAMANZANAS_BAJA');
assert.equal(ap.rssi, -86); assert.equal(ap.rssi, -86);

30
test/nmcli.js Normal file
View File

@ -0,0 +1,30 @@
/**
* nmcli unit test
* Created by kc on 04.04.16.
*/
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const nmcli = require('../lib/nmcli');
describe.skip('nmcli', () => {
it('parses the output of file 1', function(done) {
nmcli.parseOutput(fs.readFileSync(path.join(__dirname, 'fixtures','nmcli','nmcli01.txt'), { encoding: 'utf8' }), (err, info) => {
console.log(info);
assert.ok(info);
assert.equal(info.length, 19);
var ap = info[0];
assert.equal(ap.mac, '00:35:1A:90:56:06');
assert.equal(ap.ssid, 'PDANet1');
//assert.equal(ap.rssi, -70);
assert.strictEqual(ap.channel, 112);
done(err);
});
});
});

41
types/index.d.ts vendored
View File

@ -1,41 +0,0 @@
declare module 'node-wifi-scanner' {
type Callback<T> = (error: Error | null, result: T | null) => void;
interface WifiNetwork {
ssid: string;
mac: string;
channel: number;
rssi: number;
}
interface Scanner {
cmdLine: string;
parseOutput(output: string, callback: Callback<WifiNetwork[]>): void;
}
interface Tool {
detector: string;
}
const airport: Tool;
const iwlist: Tool;
const netsh: Tool;
/**
* Initialize the scanner tools
* @param callback Callback function
*/
function initTools(callback: Callback<Scanner>): void;
/**
* Scan the networks
* @param callback Callback function
*/
function scanNetworks(callback: Callback<WifiNetwork[]>): void;
/**
* Scan for WiFi networks
* @param callback Callback function
*/
function scan(callback: Callback<WifiNetwork[]>): void;
}