From 41d5b0e399aa26011211a87e1e69320d6148c474 Mon Sep 17 00:00:00 2001 From: Sebastian Hildebrandt Date: Fri, 14 Jun 2019 22:56:11 +0200 Subject: [PATCH] wifi() added available wifi networks --- CHANGELOG.md | 1 + README.md | 21 ++++- docs/history.html | 5 + docs/index.html | 10 +- docs/main.js | 1 + docs/wifi.html | 228 ++++++++++++++++++++++++++++++++++++++++++++++ lib/index.d.ts | 15 +++ lib/util.js | 4 +- lib/wifi.js | 173 ++++++++++++++++++++++++++++++++--- 9 files changed, 438 insertions(+), 20 deletions(-) create mode 100644 docs/wifi.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfdd78..495fc8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ For major (breaking) changes - version 3 and 2 see end of page. | Version | Date | Comment | | -------------- | -------------- | -------- | +| 4.11.0 | 2019-06-14 | `wifi()` added available wifi networks | | 4.10.0 | 2019-06-14 | `graphics()` windows multiple display support | | 4.9.2 | 2019-06-12 | type definitions bug fix | | 4.9.1 | 2019-06-11 | `networkStats()` bug fix windows | diff --git a/README.md b/README.md index eea37ea..203c9fc 100644 --- a/README.md +++ b/README.md @@ -455,7 +455,22 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | ms | X | X | X | X | X | response time in ms | | si.inetLatency(host, cb) | : number | X | X | X | X | X | response-time (ms) to external resource
host parameter is optional (default 8.8.8.8)| -#### 11. Docker +#### 11. Wifi networks +| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments | +| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- | +| si.wifi(cb) | [{...}] | X | | X | X | | array of available wifi networks | +| | [0].ssid | X | | X | X | | Wifi network SSID | +| | [0].bssid | X | | X | X | | BSSID (mac) | +| | [0].mode | X | | | | | mode | +| | [0].channel | X | | X | X | | channel | +| | [0].frequency | X | | X | X | | frequengy in MHz | +| | [0].signalLevel | X | | X | X | | signal level in dB | +| | [0].quality | X | | X | X | | quaility in % | +| | [0].security | X | | X | X | | array e.g. WPA, WPA-2 | +| | [0].wpaFlags | X | | X | X | | array of WPA flags | +| | [0].rsnFlags | X | | | | | array of RDN flags | + +#### 12. Docker | Function | Result object | Linux | BSD | Mac | Win | Sun | Comments | | --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- | @@ -553,7 +568,7 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | [0].command | X | X | X | X | X | command and arguments | | si.dockerAll(cb) | {...} | X | X | X | X | X | list of all containers including their stats
and processes in one single array | -#### 12. Virtual Box +#### 13. Virtual Box | Function | Result object | Linux | BSD | Mac | Win | Sun | Comments | | --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- | @@ -595,7 +610,7 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | [0].timeOffset | X | X | X | X | X | time Offset | | | [0].RTC | X | X | X | X | X | RTC | -#### 13. "Get All at once" - functions +#### 14. "Get All at once" - functions | Function | Result object | Linux | BSD | Mac | Win | Sun | Comments | | --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- | diff --git a/docs/history.html b/docs/history.html index 1395be7..b1a3b96 100644 --- a/docs/history.html +++ b/docs/history.html @@ -80,6 +80,11 @@ + + 4.11.0 + 2019-06-14 + wifi() added available wifi networks + 4.10.0 2019-06-14 diff --git a/docs/index.html b/docs/index.html index b73ca3c..fd50ea2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -168,7 +168,7 @@
systeminformation
-
Current Version: 4.10.0
+
Current Version: 4.11.0
@@ -191,7 +191,7 @@
-
8,833
+
9,082
Lines of code
@@ -281,6 +281,12 @@
Network
+ +
+
+
Wifi
+
+
diff --git a/docs/main.js b/docs/main.js index f765e41..33a1c58 100644 --- a/docs/main.js +++ b/docs/main.js @@ -12,6 +12,7 @@ function createMenu() { [1, 'processes', 'Processes / Services'], [1, 'filesystem', 'Disks / FS'], [1, 'network', 'Network'], + [1, 'wifi', 'Wifi'], [1, 'docker', 'Docker'], [1, 'vbox', 'Virtual Box'], [0, '', 'More'], diff --git a/docs/wifi.html b/docs/wifi.html new file mode 100644 index 0000000..dec1959 --- /dev/null +++ b/docs/wifi.html @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + systeminformation + + + + +
+ +
+
+ +
+
+
+
Wifi
+
+

In this section you will learn how to get detailed information about available wifi networks:

+

For function reference and examples we assume, that we imported systeminformation as follows:

+
const si = require('systeminformation');
+

Wifi Networks

+

All functions in this section return a promise or can be called with a callback function (parameter cb in the function reference)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionResult objectLinuxBSDMacWinSunComments
si.wifi(cb)[{...}]XXXXXarray of available wifi networks
[0].ssidXXXWifi network SSID
[0].bssidXXXBSSID (mac)
[0].modeXmode
[0].channelXXXchannel
[0].frequencyXXXfrequengy in MHz
[0].signalLevelXXXsignal level in dB
[0].qualityXXXquaility in %
[0].securityXXXarray e.g. WPA, WPA-2
[0].wpaFlagsXXXarray of WPA flags
[0].rsnFlagsXarray of RDN flags +
+ +
+
+
+
+
+
+ + + + + + + diff --git a/lib/index.d.ts b/lib/index.d.ts index 7805714..eb94b8b 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -344,6 +344,19 @@ export namespace Systeminformation { ms: number; } + interface WifiNetworkData { + ssid: string; + bssid: string; + mode: string; + channel: number; + frequency: number; + signalLevel: number; + quality: number; + security: string[]; + wpaFlags: string[]; + rsnFlags: string[]; + } + // 7. Current Load, Processes & Services interface CurrentLoadData { @@ -626,6 +639,8 @@ export function networkConnections(cb?: (data: Systeminformation.NetworkConnecti export function inetChecksite(url: string, cb?: (data: Systeminformation.InetChecksiteData) => any): Promise; export function inetLatency(host?: string, cb?: (data: number) => any): Promise; +export function wifi(cb?: (data: Systeminformation.WifiNetworkData[]) => any): Promise; + export function users(cb?: (data: Systeminformation.UserData[]) => any): Promise; export function processes(cb?: (data: Systeminformation.ProcessesData) => any): Promise; diff --git a/lib/util.js b/lib/util.js index b0f7af6..022b0e2 100644 --- a/lib/util.js +++ b/lib/util.js @@ -18,6 +18,7 @@ const fs = require('fs'); const spawn = require('child_process').spawn; const exec = require('child_process').exec; const execSync = require('child_process').execSync; +const util = require('util'); let _platform = process.platform; const _linux = (_platform === 'linux'); @@ -35,7 +36,8 @@ let codepage = ''; const execOptsWin = { windowsHide: true, maxBuffer: 1024 * 2000, - encoding: 'UTF-8' + encoding: 'UTF-8', + env: util._extend(process.env, { LANG: 'en_US.UTF-8' }) }; diff --git a/lib/wifi.js b/lib/wifi.js index 44c792e..d6a0705 100644 --- a/lib/wifi.js +++ b/lib/wifi.js @@ -15,8 +15,6 @@ const os = require('os'); const exec = require('child_process').exec; -const execSync = require('child_process').execSync; -const fs = require('fs'); const util = require('./util'); let _platform = process.platform; @@ -24,10 +22,6 @@ let _platform = process.platform; const _linux = (_platform === 'linux'); const _darwin = (_platform === 'darwin'); const _windows = (_platform === 'win32'); -const _freebsd = (_platform === 'freebsd'); -const _openbsd = (_platform === 'openbsd'); -const _netbsd = (_platform === 'netbsd'); -const _sunos = (_platform === 'sunos'); function wifiDBFromQuality(quality) { return (parseFloat(quality) / 2 - 100); @@ -37,6 +31,85 @@ function wifiQualityFromDB(db) { return 2 * (parseFloat(db) + 100); } +function wifiFrequencyFromChannel(channel) { + const frequencies = { + 1: 2412, + 2: 2417, + 3: 2422, + 4: 2427, + 5: 2432, + 6: 2437, + 7: 2442, + 8: 2447, + 9: 2452, + 10: 2457, + 11: 2462, + 12: 2467, + 13: 2472, + 14: 2484, + 32: 5160, + 34: 5170, + 36: 5180, + 38: 5190, + 40: 5200, + 42: 5210, + 44: 5220, + 46: 5230, + 48: 5240, + 50: 5250, + 52: 5260, + 54: 5270, + 56: 5280, + 58: 5290, + 60: 5300, + 62: 5310, + 64: 5320, + 68: 5340, + 96: 5480, + 100: 5500, + 102: 5510, + 104: 5520, + 106: 5530, + 108: 5540, + 110: 5550, + 112: 5560, + 114: 5570, + 116: 5580, + 118: 5590, + 120: 5600, + 122: 5610, + 124: 5620, + 126: 5630, + 128: 5640, + 132: 5660, + 134: 5670, + 136: 5680, + 138: 5690, + 140: 5700, + 142: 5710, + 144: 5720, + 149: 5745, + 151: 5755, + 153: 5765, + 155: 5775, + 157: 5785, + 159: 5795, + 161: 5805, + 165: 5825, + 169: 5845, + 173: 5865, + 183: 4915, + 184: 4920, + 185: 4925, + 187: 4935, + 188: 4940, + 189: 4945, + 192: 4960, + 196: 4980 + }; + return frequencies.hasOwnProperty(channel) ? frequencies[channel] : -1; +} + function wifi(callback) { return new Promise((resolve) => { @@ -52,10 +125,10 @@ function wifi(callback) { part = 'ACTIVE:' + part; const lines = part.split(os.EOL); const channel = util.getValue(lines, 'CHAN'); - const frequency = util.getValue(lines, 'FREQ').toLowerCase().replace('mhz', '').trim() - const security = util.getValue(lines, 'SECURITY').replace('(', '').replace(')', '') - const wpaFlags = util.getValue(lines, 'WPA-FLAGS').replace('(', '').replace(')', '') - const rsnFlags = util.getValue(lines, 'RSN-FLAGS').replace('(', '').replace(')', '') + const frequency = util.getValue(lines, 'FREQ').toLowerCase().replace('mhz', '').trim(); + const security = util.getValue(lines, 'SECURITY').replace('(', '').replace(')', ''); + const wpaFlags = util.getValue(lines, 'WPA-FLAGS').replace('(', '').replace(')', ''); + const rsnFlags = util.getValue(lines, 'RSN-FLAGS').replace('(', '').replace(')', ''); result.push({ ssid: util.getValue(lines, 'SSID'), bssid: util.getValue(lines, 'BSSID'), @@ -67,17 +140,89 @@ function wifi(callback) { security: security && security !== 'none' ? security.split(' ') : [], wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [], rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : [] - }) - }) + }); + }); if (callback) { callback(result); } resolve(result); }); - } else if (_darwinx) { - let cmd = ''; + } else if (_darwin) { + let cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s'; exec(cmd, { maxBuffer: 1024 * 2000 }, function (error, stdout) { + const lines = stdout.toString().split(os.EOL); + if (lines && lines.length > 1) { + const parsedhead = util.parseHead(lines[0], 1); + if (parsedhead.length >= 7) { + lines.shift(); + lines.forEach(line => { + if (line.trim()) { + const channelStr = line.substring(parsedhead[3].from, parsedhead[3].to).trim(); + const channel = channelStr ? parseInt(channelStr, 10) : -1; + const signalLevel = line.substring(parsedhead[2].from, parsedhead[2].to).trim(); + const securityAll = line.substring(parsedhead[6].from, 1000).trim().split(' '); + let security = []; + let wpaFlags = []; + securityAll.forEach(securitySingle => { + if (securitySingle.indexOf('(') > 0) { + const parts = securitySingle.split('('); + security.push(parts[0]); + wpaFlags = wpaFlags.concat(parts[1].replace(')', '').split(',')); + } + }); + wpaFlags = [...new Set(wpaFlags)]; + result.push({ + ssid: line.substring(parsedhead[0].from, parsedhead[0].to).trim(), + bssid: line.substring(parsedhead[1].from, parsedhead[1].to).trim(), + mode: '', + channel, + frequency: wifiFrequencyFromChannel(channel), + signalLevel: signalLevel ? parseInt(signalLevel, 10) : -1, + quality: wifiQualityFromDB(signalLevel), + security, + wpaFlags, + rsnFlags: [] + }); + } + }); + } + } + if (callback) { + callback(result); + } + resolve(result); + }); + } else if (_windows) { + let cmd = 'chcp 65001 && netsh wlan show networks mode=Bssid'; + exec(cmd, util.execOptsWin, function (error, stdout) { + + const parts = stdout.toString('utf8').split(os.EOL + os.EOL + 'SSID '); + parts.shift(); + + parts.forEach(part => { + const lines = part.split(os.EOL); + if (lines && lines.length >= 8 && lines[0].indexOf(':') >= 0) { + let bssid = lines[4].split(':'); + bssid.shift(); + bssid = bssid.join(':').trim(); + const channel = lines[7].split(':').pop().trim(); + const quality = lines[5].split(':').pop().trim(); + result.push({ + ssid: lines[0].split(':').pop().trim(), + bssid, + mode: '', + channel: channel ? parseInt(channel, 10) : -1, + frequency: wifiFrequencyFromChannel(channel), + signalLevel: wifiDBFromQuality(quality), + quality: quality ? parseInt(quality, 10) : -1, + security: [lines[2].split(':').pop().trim()], + wpaFlags: [lines[3].split(':').pop().trim()], + rsnFlags: [] + }); + } + }); + if (callback) { callback(result); }