1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | const os = require('os');
|
17 | const exec = require('child_process').exec;
|
18 | const util = require('./util');
|
19 |
|
20 | let _platform = process.platform;
|
21 |
|
22 | const _linux = (_platform === 'linux');
|
23 | const _darwin = (_platform === 'darwin');
|
24 | const _windows = (_platform === 'win32');
|
25 |
|
26 | function wifiDBFromQuality(quality) {
|
27 | return (parseFloat(quality) / 2 - 100);
|
28 | }
|
29 |
|
30 | function wifiQualityFromDB(db) {
|
31 | const result = 2 * (parseFloat(db) + 100);
|
32 | return result <= 100 ? result : 100;
|
33 | }
|
34 |
|
35 | function wifiFrequencyFromChannel(channel) {
|
36 | const frequencies = {
|
37 | 1: 2412,
|
38 | 2: 2417,
|
39 | 3: 2422,
|
40 | 4: 2427,
|
41 | 5: 2432,
|
42 | 6: 2437,
|
43 | 7: 2442,
|
44 | 8: 2447,
|
45 | 9: 2452,
|
46 | 10: 2457,
|
47 | 11: 2462,
|
48 | 12: 2467,
|
49 | 13: 2472,
|
50 | 14: 2484,
|
51 | 32: 5160,
|
52 | 34: 5170,
|
53 | 36: 5180,
|
54 | 38: 5190,
|
55 | 40: 5200,
|
56 | 42: 5210,
|
57 | 44: 5220,
|
58 | 46: 5230,
|
59 | 48: 5240,
|
60 | 50: 5250,
|
61 | 52: 5260,
|
62 | 54: 5270,
|
63 | 56: 5280,
|
64 | 58: 5290,
|
65 | 60: 5300,
|
66 | 62: 5310,
|
67 | 64: 5320,
|
68 | 68: 5340,
|
69 | 96: 5480,
|
70 | 100: 5500,
|
71 | 102: 5510,
|
72 | 104: 5520,
|
73 | 106: 5530,
|
74 | 108: 5540,
|
75 | 110: 5550,
|
76 | 112: 5560,
|
77 | 114: 5570,
|
78 | 116: 5580,
|
79 | 118: 5590,
|
80 | 120: 5600,
|
81 | 122: 5610,
|
82 | 124: 5620,
|
83 | 126: 5630,
|
84 | 128: 5640,
|
85 | 132: 5660,
|
86 | 134: 5670,
|
87 | 136: 5680,
|
88 | 138: 5690,
|
89 | 140: 5700,
|
90 | 142: 5710,
|
91 | 144: 5720,
|
92 | 149: 5745,
|
93 | 151: 5755,
|
94 | 153: 5765,
|
95 | 155: 5775,
|
96 | 157: 5785,
|
97 | 159: 5795,
|
98 | 161: 5805,
|
99 | 165: 5825,
|
100 | 169: 5845,
|
101 | 173: 5865,
|
102 | 183: 4915,
|
103 | 184: 4920,
|
104 | 185: 4925,
|
105 | 187: 4935,
|
106 | 188: 4940,
|
107 | 189: 4945,
|
108 | 192: 4960,
|
109 | 196: 4980
|
110 | };
|
111 | return {}.hasOwnProperty.call(frequencies, channel) ? frequencies[channel] : -1;
|
112 | }
|
113 |
|
114 | function wifiNetworks(callback) {
|
115 |
|
116 | return new Promise((resolve) => {
|
117 | process.nextTick(() => {
|
118 | let result = [];
|
119 | if (_linux) {
|
120 | let cmd = 'nmcli --terse --fields active,ssid,bssid,mode,chan,freq,signal,security,wpa-flags,rsn-flags device wifi list 2>/dev/null';
|
121 | exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
122 |
|
123 | const parts = stdout.toString().split('ACTIVE:');
|
124 | parts.shift();
|
125 | parts.forEach(part => {
|
126 | part = 'ACTIVE:' + part;
|
127 | const lines = part.split(os.EOL);
|
128 | const channel = util.getValue(lines, 'CHAN');
|
129 | const frequency = util.getValue(lines, 'FREQ').toLowerCase().replace('mhz', '').trim();
|
130 | const security = util.getValue(lines, 'SECURITY').replace('(', '').replace(')', '');
|
131 | const wpaFlags = util.getValue(lines, 'WPA-FLAGS').replace('(', '').replace(')', '');
|
132 | const rsnFlags = util.getValue(lines, 'RSN-FLAGS').replace('(', '').replace(')', '');
|
133 | result.push({
|
134 | ssid: util.getValue(lines, 'SSID'),
|
135 | bssid: util.getValue(lines, 'BSSID'),
|
136 | mode: util.getValue(lines, 'MODE'),
|
137 | channel: channel ? parseInt(channel, 10) : -1,
|
138 | frequency: frequency ? parseInt(frequency, 10) : -1,
|
139 | signalLevel: wifiDBFromQuality(util.getValue(lines, 'SIGNAL')),
|
140 | quality: parseFloat(util.getValue(lines, 'SIGNAL')),
|
141 | security: security && security !== 'none' ? security.split(' ') : [],
|
142 | wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [],
|
143 | rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : []
|
144 | });
|
145 | });
|
146 |
|
147 | if (callback) {
|
148 | callback(result);
|
149 | }
|
150 | resolve(result);
|
151 | });
|
152 | } else if (_darwin) {
|
153 | let cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s';
|
154 | exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
|
155 | const lines = stdout.toString().split(os.EOL);
|
156 | if (lines && lines.length > 1) {
|
157 | const parsedhead = util.parseHead(lines[0], 1);
|
158 | if (parsedhead.length >= 7) {
|
159 | lines.shift();
|
160 | lines.forEach(line => {
|
161 | if (line.trim()) {
|
162 | const channelStr = line.substring(parsedhead[3].from, parsedhead[3].to).trim();
|
163 | const channel = channelStr ? parseInt(channelStr, 10) : -1;
|
164 | const signalLevel = line.substring(parsedhead[2].from, parsedhead[2].to).trim();
|
165 | const securityAll = line.substring(parsedhead[6].from, 1000).trim().split(' ');
|
166 | let security = [];
|
167 | let wpaFlags = [];
|
168 | securityAll.forEach(securitySingle => {
|
169 | if (securitySingle.indexOf('(') > 0) {
|
170 | const parts = securitySingle.split('(');
|
171 | security.push(parts[0]);
|
172 | wpaFlags = wpaFlags.concat(parts[1].replace(')', '').split(','));
|
173 | }
|
174 | });
|
175 | wpaFlags = Array.from(new Set(wpaFlags));
|
176 | result.push({
|
177 | ssid: line.substring(parsedhead[0].from, parsedhead[0].to).trim(),
|
178 | bssid: line.substring(parsedhead[1].from, parsedhead[1].to).trim(),
|
179 | mode: '',
|
180 | channel,
|
181 | frequency: wifiFrequencyFromChannel(channel),
|
182 | signalLevel: signalLevel ? parseInt(signalLevel, 10) : -1,
|
183 | quality: wifiQualityFromDB(signalLevel),
|
184 | security,
|
185 | wpaFlags,
|
186 | rsnFlags: []
|
187 | });
|
188 | }
|
189 | });
|
190 | }
|
191 | }
|
192 | if (callback) {
|
193 | callback(result);
|
194 | }
|
195 | resolve(result);
|
196 | });
|
197 | } else if (_windows) {
|
198 | let cmd = 'chcp 65001 && netsh wlan show networks mode=Bssid';
|
199 | exec(cmd, util.execOptsWin, function (error, stdout) {
|
200 |
|
201 | const parts = stdout.toString('utf8').split(os.EOL + os.EOL + 'SSID ');
|
202 | parts.shift();
|
203 |
|
204 | parts.forEach(part => {
|
205 | const lines = part.split(os.EOL);
|
206 | if (lines && lines.length >= 8 && lines[0].indexOf(':') >= 0) {
|
207 | let bssid = lines[4].split(':');
|
208 | bssid.shift();
|
209 | bssid = bssid.join(':').trim();
|
210 | const channel = lines[7].split(':').pop().trim();
|
211 | const quality = lines[5].split(':').pop().trim();
|
212 | result.push({
|
213 | ssid: lines[0].split(':').pop().trim(),
|
214 | bssid,
|
215 | mode: '',
|
216 | channel: channel ? parseInt(channel, 10) : -1,
|
217 | frequency: wifiFrequencyFromChannel(channel),
|
218 | signalLevel: wifiDBFromQuality(quality),
|
219 | quality: quality ? parseInt(quality, 10) : -1,
|
220 | security: [lines[2].split(':').pop().trim()],
|
221 | wpaFlags: [lines[3].split(':').pop().trim()],
|
222 | rsnFlags: []
|
223 | });
|
224 | }
|
225 | });
|
226 |
|
227 | if (callback) {
|
228 | callback(result);
|
229 | }
|
230 | resolve(result);
|
231 | });
|
232 | } else {
|
233 | if (callback) {
|
234 | callback(result);
|
235 | }
|
236 | resolve(result);
|
237 | }
|
238 | });
|
239 | });
|
240 | }
|
241 |
|
242 | exports.wifiNetworks = wifiNetworks;
|