Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
e5f9390ba1 | |||
c5cbde1a3c | |||
e69c735d64 | |||
40ab464995 | |||
0672168541 | |||
4b379b106a | |||
1f72f00d2d | |||
a5ad7ea8a5 | |||
c16a65dbcd | |||
debd06f258 | |||
4e8c3efe6f | |||
330e851545 | |||
897314ee52 | |||
4b751522b9 | |||
a4820acc34 | |||
b032feac3e | |||
4a53c2f42a | |||
7314228c91 | |||
95b62bfbb0 | |||
91c43c5aac | |||
|
0f1a6d6661 | ||
|
9d42fb9b5e | ||
|
0fe7bd8eed | ||
|
a8416e1a27 | ||
|
d7715d1cdf | ||
|
36e1f8ffaf | ||
|
cf885a3bdd | ||
|
ba0bfc7d42 | ||
|
d0f22a8ed2 | ||
|
a021a5d469 | ||
|
9fe4300976 | ||
|
8eeb0a9827 | ||
|
d140e224c9 | ||
|
ef25a7fb7c | ||
|
32b516e302 | ||
|
d1eac84058 | ||
|
50090aecda | ||
|
bc61dc2f02 | ||
|
5030d9f693 | ||
|
e874b44200 | ||
|
f1c0c014da | ||
|
29e715897e | ||
|
d302473da7 | ||
|
77da84a261 | ||
|
9669064662 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.idea
|
.idea
|
||||||
node_modules
|
node_modules
|
||||||
|
/yarn.lock
|
||||||
|
@ -4,5 +4,5 @@ branches:
|
|||||||
- master
|
- master
|
||||||
- develop
|
- develop
|
||||||
node_js:
|
node_js:
|
||||||
- "4"
|
- "10"
|
||||||
- "5"
|
- "11"
|
||||||
|
85
README.md
85
README.md
@ -1,4 +1,43 @@
|
|||||||
#node-wifi-scanner
|
# Fork of 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
|
||||||
|
|
||||||
|
|
||||||
[](https://travis-ci.org/ancasicolica/node-wifi-scanner)
|
[](https://travis-ci.org/ancasicolica/node-wifi-scanner)
|
||||||
[]()
|
[]()
|
||||||
@ -16,33 +55,24 @@ system language. The adaptions needed would have been too comprehensive for a pu
|
|||||||
## Operating Systems
|
## Operating Systems
|
||||||
|
|
||||||
It was tested with the following operating systems:
|
It was tested with the following operating systems:
|
||||||
* Mac OS-X
|
* Mac OS-X [Not tested by fork author]
|
||||||
* Windows 10
|
* Windows 10 [Not tested by fork author]
|
||||||
* Ubuntu 14.04
|
* Ubuntu 14.04 [Tested by fork author]
|
||||||
* Raspbian "Jessie"
|
* Raspbian "Jessie" [Tested by fork author]
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
npm i node-wifi-scanner
|
yarn add git+https://git.gaminggeneration.de/tobiash/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
|
* mac: MAC Address of the network access point (if available, otherwise empty string)
|
||||||
* 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.
|
||||||
@ -53,17 +83,34 @@ 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 (1st choice) on Linux: `iwlist scan`
|
* iwlist on Linux: `iwlist scan`
|
||||||
|
|
||||||
|
|
||||||
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 Christian Kuster
|
Copyright (c) 2016-2024 Christian Kuster, Tobias Hopp
|
||||||
|
|
||||||
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
|
||||||
|
2
bin/scan
2
bin/scan
@ -5,7 +5,7 @@
|
|||||||
* Created by kc on 04.04.16.
|
* Created by kc on 04.04.16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var scanner = require('../index');
|
const scanner = require('../index');
|
||||||
|
|
||||||
scanner.scan((err, output) => {
|
scanner.scan((err, output) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
90
index.js
90
index.js
@ -1,10 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* node-wifi-scanner
|
* @typedef {Object} WifiNetwork
|
||||||
* Created by kc on 04.04.16.
|
* @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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const exec = require('child_process').exec;
|
/**
|
||||||
|
* node-wifi-scanner
|
||||||
|
* Created by kc on 04.04.16. - Forked and updated by Tobias Hopp 27.03.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
const {exec, spawn} = require('child_process');
|
||||||
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
// The tools
|
// The tools
|
||||||
@ -12,7 +22,7 @@ const airport = require('./lib/airport');
|
|||||||
const iwlist = require('./lib/iwlist');
|
const iwlist = require('./lib/iwlist');
|
||||||
const netsh = require('./lib/netsh');
|
const netsh = require('./lib/netsh');
|
||||||
|
|
||||||
var scanner;
|
let scanner;
|
||||||
|
|
||||||
// Initializing the tools
|
// Initializing the tools
|
||||||
function initTools(callback) {
|
function initTools(callback) {
|
||||||
@ -43,7 +53,7 @@ function initTools(callback) {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
function (err, results) {
|
function (err, results) {
|
||||||
var res = _.find(results,
|
let res = _.find(results,
|
||||||
function (f) {
|
function (f) {
|
||||||
return !f.err
|
return !f.err
|
||||||
});
|
});
|
||||||
@ -58,34 +68,76 @@ function initTools(callback) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan the networks with the scanner detected before
|
* Scan the networks with the scanner detected before
|
||||||
* @param callback
|
* @param {Function|any} callback
|
||||||
|
* @param {boolean} useSudo - Use sudo for access?
|
||||||
*/
|
*/
|
||||||
function scanNetworks(callback) {
|
function scanNetworks(callback, useSudo) {
|
||||||
exec(scanner.cmdLine, function (err, stdout) {
|
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) {
|
||||||
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 wifis
|
* Scan for wifi networks
|
||||||
* @param callback
|
* @param {boolean} useSudo? - Defaults to false | Should sudo be used to get the output?
|
||||||
*/
|
* @return {Promise<WifiNetwork[]|null>} WiFinetwork Array or null
|
||||||
scan: function (callback) {
|
* @rejects Returns error on reject
|
||||||
if (!scanner) {
|
*/
|
||||||
initTools(function (err, s) {
|
scan: function (useSudo = false) {
|
||||||
|
return new Promise( (resolve, reject) => {
|
||||||
|
if (!scanner) {
|
||||||
|
initTools(function (err, s) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
scanner = s;
|
scanner = s;
|
||||||
scanNetworks(callback);
|
scanNetworks((err, result) => {
|
||||||
|
if(err)
|
||||||
|
return reject(err);
|
||||||
|
if(!result)
|
||||||
|
result = [];
|
||||||
|
resolve(result);
|
||||||
|
}, useSudo && scanner == iwlist);
|
||||||
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scanNetworks(callback);
|
scanNetworks((err, result) => {
|
||||||
|
if(err)
|
||||||
|
return reject(err);
|
||||||
|
if(!result)
|
||||||
|
result = [];
|
||||||
|
resolve(result);
|
||||||
|
}, useSudo && scanner == iwlist);
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3,43 +3,40 @@
|
|||||||
* Created by kc on 04.04.16.
|
* Created by kc on 04.04.16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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 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) {
|
||||||
var err = null;
|
let err = null;
|
||||||
|
let wifis = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var lines = str.split('\n');
|
let lines = str.split('\n');
|
||||||
var wifis = [];
|
|
||||||
|
|
||||||
for (var i = 1, l = lines.length; i < l; i++) {
|
for (let i = 1, l = lines.length; i < l; i++) {
|
||||||
var mac = lines[i].match(macRegex);
|
if (lines[i] === '') continue;
|
||||||
if (!mac) {
|
let elements = lines[i].substring(51).split(/[ ]+/);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var macStart = lines[i].indexOf(mac[0]);
|
|
||||||
var elements = lines[i].substr(macStart).split(/[ ]+/);
|
|
||||||
wifis.push({
|
wifis.push({
|
||||||
'ssid' : lines[i].substr(0, macStart).trim(),
|
'ssid' : lines[i].substring(0, 32).trim(),
|
||||||
'mac' : elements[0].trim(),
|
'mac' : '', // There is no more mac on a mac
|
||||||
'channel' : parseInt(elements[2].trim(), 10),
|
'channel': parseInt(elements[1].trim(), 10),
|
||||||
'rssi' : parseInt(elements[1].trim(), 10)
|
'rssi' : parseInt(elements[0].trim(), 10),
|
||||||
|
'encrypted': false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
err = ex;
|
err = ex;
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
callback(err, wifis);
|
callback(err, wifis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,31 +3,34 @@
|
|||||||
* Created by kc on 04.04.16.
|
* Created by kc on 04.04.16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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
|
// usually located in /usr/bin/ but as it could be at another location, allow all found in PATH (but we're in trouble
|
||||||
// when the default location, /usr/bin/ is not in the PATH!). GitHub issue #1
|
// when the default location, /usr/bin/ is not in the PATH!). GitHub issue #1
|
||||||
const tool = 'iwlist';
|
const tool = 'iwlist';
|
||||||
const cmdLine = tool + ' scan';
|
const cmdLine = tool + ' scan';
|
||||||
const detector = tool + ' --help';
|
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) {
|
||||||
var err = null;
|
let err = null;
|
||||||
var wifis = [];
|
let wifis = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var blocks = str.split(cellRegex);
|
let blocks = str.split(cellRegex);
|
||||||
|
|
||||||
blocks.forEach(block => {
|
blocks.forEach(block => {
|
||||||
var network = {};
|
let network = {encrypted: encryptedRegex.test(block)};
|
||||||
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();
|
||||||
@ -43,8 +46,8 @@ function parseOutput(str, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Channel, an ugly thing to get it
|
// Channel, an ugly thing to get it
|
||||||
else if (_.startsWith(line.trim(), 'Frequency:')) {
|
else if (_.startsWith(line.trim(), 'Channel:')) {
|
||||||
network.channel = parseInt(_.trim(line, ' )').split(/Channel/)[1], 10);
|
network.channel = parseInt(_.trim(line, ' )').split(/:/)[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@ -53,15 +56,14 @@ 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
|
||||||
var elements = line.split('=');
|
let 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
|
||||||
var parts = e.split('/');
|
let parts = e.split('/');
|
||||||
var level = Math.floor(100 * parseInt(parts[0], 10) / parseInt(parts[1], 10));
|
let level = Math.floor(100 * parseInt(parts[0], 10) / parseInt(parts[1], 10));
|
||||||
network.rssi = level / 2 - 100;
|
network.rssi = level / 2 - 100;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
26
lib/netsh.js
26
lib/netsh.js
@ -15,9 +15,9 @@ 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) {
|
||||||
var blocks = str.split('\n\n');
|
let blocks = str.split('\n\n');
|
||||||
var wifis = [];
|
let wifis = [];
|
||||||
var err = null;
|
let err = null;
|
||||||
try {
|
try {
|
||||||
if (blocks.length < 2) {
|
if (blocks.length < 2) {
|
||||||
// 2nd try, with \r\n
|
// 2nd try, with \r\n
|
||||||
@ -40,18 +40,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 (var i = 1, l = blocks.length; i < l; i++) {
|
for (let i = 1, l = blocks.length; i < l; i++) {
|
||||||
var network = {};
|
let network = {encrypted: false};
|
||||||
var lines = blocks[i].split('\n');
|
let lines = blocks[i].split('\n');
|
||||||
var regexChannel = /[a-zA-Z0-9()\s]+:[\s]*[0-9]+$/g;
|
let 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)
|
||||||
var ssid = lines[0].substring(lines[0].indexOf(':') + 1).trim();
|
let ssid = lines[0].substring(lines[0].indexOf(':') + 1).trim();
|
||||||
|
|
||||||
for (var t = 1, n = lines.length; t < n; t++) {
|
for (let 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,14 +61,12 @@ 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 '%'
|
||||||
var level = parseInt(lines[t].split(':')[1].split('%')[0].trim(), 10);
|
let 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())) {
|
||||||
|
3219
package-lock.json
generated
Normal file
3219
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "node-wifi-scanner",
|
"name": "node-wifi-scanner",
|
||||||
"version": "1.1.0",
|
"version": "1.1.3",
|
||||||
"description": "node.js module for WiFi network detection",
|
"description": "node.js module for WiFi network detection",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@ -13,19 +13,18 @@
|
|||||||
"nmcli"
|
"nmcli"
|
||||||
],
|
],
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Christian Kuster, CH-8342 Wernetshausen",
|
"name": "Christian Kuster, Tobias Hopp",
|
||||||
"email": "info@kusti.ch",
|
"email": "tobi@gaminggeneration.de"
|
||||||
"url": "http://www.kusti.ch/"
|
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/ancasicolica/node-wifi-scanner",
|
"homepage": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner/",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/ancasicolica/node-wifi-scanner/issues",
|
"url": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner/issues/",
|
||||||
"email": "info@ancasicolica.ch"
|
"email": "info@ancasicolica.ch"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ancasicolica/node-wifi-scanner.git"
|
"url": "https://git.gaminggeneration.de/TobiasH/node-wifi-scanner.git"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 4.0.0",
|
"node": ">= 4.0.0",
|
||||||
@ -35,12 +34,12 @@
|
|||||||
"test": "mocha test"
|
"test": "mocha test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "2.1.4",
|
"async": "3.2.4",
|
||||||
"lodash": "4.17.2"
|
"lodash": "4.17.21"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"grunt": "0.4.5",
|
"grunt": "1.5.3",
|
||||||
"grunt-bump": "0.7.0",
|
"grunt-bump": "0.8.0",
|
||||||
"mocha": "2.2.5"
|
"mocha": "10.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
2
test/fixtures/airport/airport01.txt
vendored
2
test/fixtures/airport/airport01.txt
vendored
@ -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 00:35:1a:90:56:03 -70 112 Y CH WPA2(PSK/AES/AES)
|
OurTest -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)
|
||||||
|
@ -22,7 +22,7 @@ describe('iwlist', () => {
|
|||||||
|
|
||||||
assert.ok(info);
|
assert.ok(info);
|
||||||
|
|
||||||
var ap = info[0];
|
let 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);
|
||||||
|
|
||||||
var ap = info[0];
|
let 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);
|
||||||
|
@ -16,7 +16,7 @@ describe('netsh', function () {
|
|||||||
assert.ok(info);
|
assert.ok(info);
|
||||||
assert.equal(info.length, 86);
|
assert.equal(info.length, 86);
|
||||||
|
|
||||||
var ap = info[0];
|
let 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);
|
||||||
|
|
||||||
var ap = info[0];
|
let 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);
|
||||||
@ -94,7 +94,7 @@ describe('netsh', function () {
|
|||||||
assert.ok(info);
|
assert.ok(info);
|
||||||
assert.equal(info.length, 8);
|
assert.equal(info.length, 8);
|
||||||
|
|
||||||
var ap = info[0];
|
let 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);
|
||||||
|
41
types/index.d.ts
vendored
Normal file
41
types/index.d.ts
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user