diff --git a/CHANGELOG.md b/CHANGELOG.md
index b14716a..cf9b243 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,35 +1,59 @@
# Changelog
-### Major Changes - Version 4
+### Major Changes - Version 5
**New Functions**
-- `chassis()`: chassis information
+- `audio()` detailed audio information
+- `bluetoothDevices()` detailed information detected bluetooth devices
+- `printers()` detailed printer information
+- `usb()` detailed USB information
+- `wifiInterfaces()` detected Wi-Fi interfaces
+- `wifiConnections()` active Wi-Fi connections
**Breaking Changes**
-- `networkStats()`: will provide an **array** of stats for all given interfaces. In previous versions only one interface was provided as a parameter. Pass '*' for all interfaces
-- `networkStats()`: `rx` and `tx` changed to `rx_bytes` and `tx_bytes`
-- `dockerContainerStats()`: will provide an **array** of stats for all given docker containers. In previous versions only one interface was provided as a parameter. Pass '*' for all docker containers
+**Be aware**, that the new version 5.x **is NOT fully backward compatible** to version 4.x ...
-**Other Changes**
+We had to make several interface changes to keep systeminformation as consistent as possible. We highly recommend to go [through the complete list](https://systeminformation.io/changes.html) and adapt your own code to be again compatible to the new version 5.
-- `system()` optimized system detection (e.g. new Raspberry Pi models, ...), additional flags
-- `system()`, `bios()`, `baseboard()` information also as non-root (linux)
-- `graphics()` better controller and display detection, fixes
-- `versions()` optimization, fixes
-- `networkInterfaces()` added `operstate`, `type`, `duplex`, `mtu`, `speed`, `carrierChanges`
-- `networkStats()` added stats for `errors`, `dropped`
-- added TypeScript definitions
+**Other Improvements and Changes**
-**Be aware**, that the new version 4.x is **NOT fully backward compatible** to version 3.x ...
+- `baseboard(): added memMax, memSlots
+- `bios()`: added language and features (linux)
+- `cpu()`: extended AMD processor list
+- `cpu()`: extended socket list (win)
+- `cpu()`: added virtualization if cpu supports virtualization
+- `cpu()`: now flags are part of this function
+- `fsSize()`: added available
+- `fsSize()`: improved calculation of used
+- `getData()`: support for passing parameters and filters (see section General / getData)
+- `graphics()`: extended nvidia-smi parsing
+- `networkInterfaces()`: type detection improved (win - wireless)
+- `memoryLayout()`: extended manufacturer list (decoding)
+- `memoryLayout()`: added ECC flag
+- `osInfo()`: better fqdn (win)
+- `osinfo()`: added hypervizor if hyper-v is enabled (win only)
+- `system()`: better Raspberry PI detection
+- `system()`: added virtual and virtualHost (if system is virtual instance)
+- `uuid()`: better value support
+- `uuid()`: added MACs
+- `uuid()`: better Raspberry Pi hardware ID
+- `Apple M1 Silicon extended support (now everything supported except of cpu temperature)
+- `updated TypeScript definitions
-For major (breaking) changes - version 3 and 2 see end of page.
+**Test Full Version 5 Functionality**
+
+If you want to see all function results on your machine, please head over to (Testing section)[https://systeminformation.io/tests.html]. We implemented a tiny test suite where you can easily go through all functions and test resuls on your machine without coding.
+
+
+For major (breaking) changes - **version 4, 3 and 2** - see end of page.
## Version history
| Version | Date | Comment |
| -------------- | -------------- | -------- |
+| 5.2.0 | 2020-02-10 | `wifiInterfces()` and `wifiConnections()` added |
| 5.1.2 | 2020-02-08 | fixed node 4 compatibility issue |
| 5.1.1 | 2020-02-08 | `baseboard()` added memMax, memSlots, smaller improvements Raspberry |
| 5.1.0 | 2020-02-08 | `memLayout()` added ECC flag, `bios()` added language, features (linux) |
@@ -436,6 +460,29 @@ For major (breaking) changes - version 3 and 2 see end of page.
| 0.0.2 | 2014-03-14 | Optimization FS-Speed & CPU current speed |
| 0.0.1 | 2014-03-13 | initial release |
+### Major C`hanges - Version 4
+
+**New Functions**
+
+- `chassis()`: chassis information
+
+**Breaking Changes**
+
+- `networkStats()`: will provide an **array** of stats for all given interfaces. In previous versions only one interface was provided as a parameter. Pass '*' for all interfaces
+- `networkStats()`: `rx` and `tx` changed to `rx_bytes` and `tx_bytes`
+- `dockerContainerStats()`: will provide an **array** of stats for all given docker containers. In previous versions only one interface was provided as a parameter. Pass '*' for all docker containers
+
+**Other Changes**
+
+- `system()` optimized system detection (e.g. new Raspberry Pi models, ...), additional flags
+- `system()`, `bios()`, `baseboard()` information also as non-root (linux)
+- `graphics()` better controller and display detection, fixes
+- `versions()` optimization, fixes
+- `networkInterfaces()` added `operstate`, `type`, `duplex`, `mtu`, `speed`, `carrierChanges`
+- `networkStats()` added stats for `errors`, `dropped`
+- added TypeScript definitions
+
+**Be aware**, that the new version 4.x is **NOT fully backward compatible** to version 3.x ...
### Major (breaking) Changes - Version 3
- works only with [node.js][nodejs-url] **v4.0.0** and above (using now internal ES6 promise function, arrow functions, ...)
diff --git a/README.md b/README.md
index c82a98b..d614a0c 100644
--- a/README.md
+++ b/README.md
@@ -565,7 +565,7 @@ Full function reference with examples can be found at [https://systeminformation
| | 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)|
-#### 14. Wifi networks
+#### 14. Wifi
| Function | Result object | Linux | BSD | Mac | Win | Sun | Comments |
| --------------- | ------------- | ----- | ------- | --- | --- | --- | -------- |
@@ -580,6 +580,25 @@ Full function reference with examples can be found at [https://systeminformation
| | [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 |
+| si.wifiInterfaces(cb) | [{...}] | X | | X | X | | array of detected wifi interfaces |
+| | [0].id | X | | X | X | | ID |
+| | [0].iface | X | | X | X | | interface |
+| | [0].model | X | | X | X | | model |
+| | [0].vendor | X | | X | X | | vendor |
+| | [0].mac | X | | X | X | | MAC address |
+| si.wifiConnections(cb) | [{...}] | X | | X | X | | array of active wifi connections |
+| | [0].id | X | | X | X | | ID |
+| | [0].iface | X | | X | X | | interface |
+| | [0].name | X | | X | X | | name |
+| | [0].mode | X | | X | X | | model |
+| | [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].txRate | X | | X | X | | transfer rate MBit/s |
#### 15. Bluetooth
diff --git a/docs/changes.html b/docs/changes.html
index 705501b..2d21469 100644
--- a/docs/changes.html
+++ b/docs/changes.html
@@ -47,9 +47,11 @@
New Functions
audio() detailed audio information
+ bluetoothDevices() detailed information detected bluetooth devices
printers() detailed printer information
usb() detailed USB information
- bluetoothDevices() detailed information detected bluetooth devices
+ wifiInterfaces() detected Wi-Fi interfaces
+ wifiConnections() active Wi-Fi connections
Breaking Changes
Be aware , that the new version 5.x is NOT fully backward compatible to version 4.x ...
@@ -185,6 +187,7 @@
uuid() : better value support
uuid() : added MACs
uuid() : better Raspberry Pi hardware ID
+ versions() : added bash, zsh, fish, powershell, dotnet
Apple M1 Silicon extended support (now everything supported except of cpu temperature)
updated TypeScript definitions
diff --git a/docs/history.html b/docs/history.html
index 5c2fa28..946f916 100644
--- a/docs/history.html
+++ b/docs/history.html
@@ -56,6 +56,11 @@
+
+ 5.2.0
+ 2020-02-10
+ wifiInterfces() and wifiConnections() added
+
5.1.2
2020-02-08
diff --git a/docs/index.html b/docs/index.html
index 0f800d8..e7ecea6 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -170,7 +170,7 @@
systeminformation
- New Version: 5.1.2
+ New Version: 5.2.0
View on Github
@@ -201,7 +201,7 @@
-
13,280
+
13,533
Lines of code
diff --git a/docs/os.html b/docs/os.html
index efd21b8..c88e68d 100644
--- a/docs/os.html
+++ b/docs/os.html
@@ -550,6 +550,56 @@ si.osInfo().then(data => console.log(data));
X
virtualbox version
+
+
+ bash
+ X
+ X
+ X
+ X
+ X
+ bash version
+
+
+
+ zsh
+ X
+ X
+ X
+ X
+ X
+ zsh version
+
+
+
+ fish
+ X
+ X
+ X
+ X
+ X
+ fish version
+
+
+
+ powershell
+
+
+
+ X
+
+ powershell version
+
+
+
+ dotnet
+
+
+
+ X
+
+ dotnet version
+
@@ -587,7 +637,12 @@ si.versions().then(data => console.log(data));
pip3: '19.0.3',
java: '',
gcc: '4.2.1',
- virtualbox: ''
+ virtualbox: '',
+ bash: '3.2.57',
+ zsh: '5.8',
+ fish: '',
+ powershell: '',
+ dotnet: ''
}
Example 2
const si = require('systeminformation');
diff --git a/docs/tests.html b/docs/tests.html
index 3bbed17..117f10d 100644
--- a/docs/tests.html
+++ b/docs/tests.html
@@ -63,8 +63,8 @@
═══════════════════════════════════════════════════════════
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│ a ... Audio h ... Bluetooth s ... Services ? ... Get Object │
-│ b ... BIOS i ... INET Latency S ... Shell , ... All Static │
+│ a ... Audio h ... Bluetooth s ... Services Y ... Battery ? ... Get Object │
+│ b ... BIOS i ... INET Latency S ... Shell z ... Users , ... All Static │
│ B ... Baseboard I ... INET Check Site t ... time 1 ... NET Iface Default . ... All Dynamic │
│ C ... Chassis j ... CPU Current Speed T ... CPU Temperature 2 ... NET Gateway Default / ... All │
│ c ... CPU l ... CPU Current Load u ... USB 3 ... NET Interfaces │
@@ -72,9 +72,9 @@
│ D ... DiskIO m ... Memory v ... Versions 5 ... NET Connections │
│ e ... Block Devices M ... MEM Layout V ... Virtual Box 6 ... Docker Info │
│ E ... Open Files o ... OS Info w ... WIFI networks 7 ... Docker Container │
-│ f ... FS Size p ... Processes y ... System 8 ... Docker Cont Stats │
-│ F ... FS Stats P ... Process Load Y ... Battery 9 ... Docker Cont Proc │
-│ g ... Graphics r ... Printer z ... Users 0 ... Docker All q >>> QUIT │
+│ f ... FS Size p ... Processes W ... WIFI interfaces 8 ... Docker Cont Stats │
+│ F ... FS Stats P ... Process Load x ... WIFI connections 9 ... Docker Cont Proc │
+│ g ... Graphics r ... Printer y ... System 0 ... Docker All q >>> QUIT │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Press q to exit the test suite
Here a sample output for the e.g. c ... CPU
diff --git a/docs/wifi.html b/docs/wifi.html
index f4acf3c..7408574 100644
--- a/docs/wifi.html
+++ b/docs/wifi.html
@@ -47,7 +47,7 @@
+ Wifi Interfaces
+ All functions in this section return a promise or can be called with a callback function (parameter cb in the function reference)
+
+
+
+ Function
+ Result object
+ Linux
+ BSD
+ Mac
+ Win
+ Sun
+ Comments
+
+
+
+
+ si.wifiInterfaces(cb)
+ [{...}]
+ X
+
+ X
+ X
+
+ array of detected wifi interfaces
+
+
+
+ [0].id
+ X
+
+ X
+ X
+
+ Wifi ID
+
+
+
+ [0].iface
+ X
+
+ X
+ X
+
+ interface
+
+
+
+ [0].model
+ X
+
+ X
+ X
+
+ model
+
+
+
+ [0].vendor
+ X
+
+ X
+ X
+
+ vendor
+
+
+
+ [0].mac
+ X
+
+ X
+ X
+
+ interface MAC
+
+
+
+
+ Example
+ const si = require('systeminformation');
+si.wifiInterfaces().then(data => console.log(data));
+
+[
+ {
+ id: 'Wi-Fi',
+ iface: 'en0',
+ model: 'AirPort',
+ vendor: '',
+ mac: 'a0:b1:c2:d3:e4:f5'
+ },
+ ...
+]
+
+
+
+
+ Wifi Connections
+ All functions in this section return a promise or can be called with a callback function (parameter cb in the function reference)
+
+
+
+ Function
+ Result object
+ Linux
+ BSD
+ Mac
+ Win
+ Sun
+ Comments
+
+
+
+
+ si.wifiConnections(cb)
+ [{...}]
+ X
+
+ X
+ X
+
+ array of active wifi connections
+
+
+
+ [0].id
+ X
+
+ X
+ X
+
+ Wifi ID
+
+
+
+ [0].iface
+ X
+
+ X
+ X
+
+ interface
+
+
+
+ [0].name
+ X
+
+ X
+ X
+
+ name
+
+
+
+ [0].model
+ X
+
+ X
+ X
+
+ model
+
+
+
+ [0].ssid
+ X
+
+ X
+ X
+
+ Wifi network SSID
+
+
+
+ [0].bssid
+ X
+
+ X
+ X
+
+ BSSID (mac)
+
+
+
+ [0].channel
+ X
+
+ X
+ X
+
+ channel
+
+
+
+ [0].frequency
+ X
+
+ X
+ X
+
+ frequency
+
+
+
+ [0].type
+ X
+
+ X
+ X
+
+ WiFi type
+
+
+
+ [0].security
+ X
+
+ X
+ X
+
+ WiFi security
+
+
+
+ [0].signalLevel
+ X
+
+ X
+ X
+
+ signal level in dB
+
+
+
+ [0].txRate
+ X
+
+ X
+ X
+
+ transfer rate Mbit/s
+
+
+
+
+ Example
+ const si = require('systeminformation');
+si.wifiConnections().then(data => console.log(data));
+
+[
+ {
+ id: 'Wi-Fi',
+ iface: 'en0',
+ name: 'AirPort',
+ model: 'AirPort',
+ ssid: 'my-own-internet',
+ bssid: '01:23:45:67:89:0a',
+ channel: 36,
+ frequency: 5180,
+ type: '802.11',
+ security: 'wpa2-psk',
+ signalLevel: 46,
+ txRate: '405'
+ },
+ ...
+]
+
+
+
+
diff --git a/lib/cpu.js b/lib/cpu.js
index 0a7f1b7..c554e43 100644
--- a/lib/cpu.js
+++ b/lib/cpu.js
@@ -552,7 +552,7 @@ function getCpu() {
result.virtualization = flags.indexOf('vmx') > -1 || flags.indexOf('svm') > -1;
if (_windows) {
try {
- const systeminfo = execSync('systeminfo').toString();
+ const systeminfo = execSync('systeminfo', util.execOptsWin).toString();
result.virtualization = result.virtualization || (systeminfo.indexOf('Virtualization Enabled In Firmware: Yes') !== -1) || (systeminfo.indexOf('Virtualisierung in Firmware aktiviert: Ja') !== -1) || (systeminfo.indexOf('Virtualisation activée dans le microprogramme : Qiu') !== -1);
} catch (e) {
util.noop();
diff --git a/lib/graphics.js b/lib/graphics.js
index 1f263b4..06c3b80 100644
--- a/lib/graphics.js
+++ b/lib/graphics.js
@@ -408,6 +408,7 @@ function graphics(callback) {
function nvidiaSmi(options) {
const nvidiaSmiExe = getNvidiaSmi();
+ options = options || util.execOptsWin;
if (nvidiaSmiExe) {
const nvidiaSmiOpts = '--query-gpu=driver_version,pci.sub_device_id,name,pci.bus_id,fan.speed,memory.total,memory.used,memory.free,utilization.gpu,utilization.memory,temperature.gpu,temperature.memory,power.draw,power.limit,clocks.gr,clocks.mem --format=csv,noheader,nounits';
const cmd = nvidiaSmiExe + ' ' + nvidiaSmiOpts + (_linux ? ' 2>/dev/null' : '');
diff --git a/lib/index.d.ts b/lib/index.d.ts
index e756431..1ba79b1 100644
--- a/lib/index.d.ts
+++ b/lib/index.d.ts
@@ -487,6 +487,27 @@ export namespace Systeminformation {
rsnFlags: string[];
}
+ interface WifiInterfaceData {
+ id: string;
+ iface: string;
+ model: string;
+ vendor: string;
+ }
+
+ interface WifiConnectionData {
+ id: string;
+ iface: string;
+ model: string;
+ ssid: string;
+ bssid: string;
+ channel: number;
+ type: string;
+ security: string;
+ frequency: number;
+ signalLevel: number;
+ txRate: number;
+ }
+
// 7. Current Load, Processes & Services
interface CurrentLoadData {
diff --git a/lib/index.js b/lib/index.js
index 8cce78e..dc2a67b 100755
--- a/lib/index.js
+++ b/lib/index.js
@@ -469,6 +469,8 @@ exports.networkStats = network.networkStats;
exports.networkConnections = network.networkConnections;
exports.wifiNetworks = wifi.wifiNetworks;
+exports.wifiInterfaces = wifi.wifiInterfaces;
+exports.wifiConnections = wifi.wifiConnections;
exports.services = processes.services;
exports.processes = processes.processes;
diff --git a/lib/network.js b/lib/network.js
index 4482d31..4e10af7 100644
--- a/lib/network.js
+++ b/lib/network.js
@@ -805,7 +805,8 @@ function networkInterfaces(callback, rescan = true) {
}
mac = details.mac;
// fallback due to https://github.com/nodejs/node/issues/13581 (node 8.1 - node 8.2)
- if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && parseInt(process.versions.node.split('.'), 10) === 8) {
+ const nodeMainVersion = parseInt(process.versions.node.split('.'), 10);
+ if (mac.indexOf('00:00:0') > -1 && (_linux || _darwin) && (!details.internal) && nodeMainVersion >= 8 && nodeMainVersion <= 11) {
if (Object.keys(_mac).length === 0) {
_mac = getMacAddresses();
}
diff --git a/lib/osinfo.js b/lib/osinfo.js
index 6682f9b..fad42e6 100644
--- a/lib/osinfo.js
+++ b/lib/osinfo.js
@@ -178,7 +178,7 @@ function getFQDN() {
}
if (_windows) {
try {
- const stdout = execSync('echo %COMPUTERNAME%.%USERDNSDOMAIN%');
+ const stdout = execSync('echo %COMPUTERNAME%.%USERDNSDOMAIN%', util.execOptsWin);
fqdn = stdout.toString().replace('.%USERDNSDOMAIN%', '').split(os.EOL)[0];
} catch (e) {
util.noop();
@@ -323,7 +323,7 @@ function osInfo(callback) {
try {
const workload = [];
workload.push(util.wmic('os get /value'));
- workload.push(execPromise('systeminfo'));
+ workload.push(execPromise('systeminfo', util.execOptsWin));
util.promiseAll(
workload
).then(data => {
@@ -433,6 +433,10 @@ function versions(apps, callback) {
java: '',
gcc: '',
virtualbox: '',
+ bash: '',
+ zsh: '',
+ fish: '',
+ powershell: '',
dotnet: ''
};
@@ -440,7 +444,7 @@ function versions(apps, callback) {
if (apps === '*') {
return {
versions: versionObject,
- counter: 26
+ counter: 30
};
}
if (!Array.isArray(apps)) {
@@ -607,7 +611,7 @@ function versions(apps, callback) {
exec('apachectl -v 2>&1', function (error, stdout) {
if (!error) {
const apache = (stdout.toString().split('\n')[0] || '').split(':');
- appsObj.versions.apache = (apache.length > 1 ? apache[1].replace('Apache', '').replace('/', '').trim() : '');
+ appsObj.versions.apache = (apache.length > 1 ? apache[1].replace('Apache', '').replace('/', '').split('(')[0].trim() : '');
}
functionProcessed();
});
@@ -926,15 +930,66 @@ function versions(apps, callback) {
functionProcessed();
});
}
- if ({}.hasOwnProperty.call(appsObj.versions, 'dotnet')) {
- exec('dotnet --version 2>&1', function (error, stdout) {
+ if ({}.hasOwnProperty.call(appsObj.versions, 'bash')) {
+ exec('bash --version', function (error, stdout) {
if (!error) {
- const dotnet = stdout.toString().split('\n')[0] || '';
- appsObj.versions.dotnet = dotnet.trim();
+ const line = stdout.toString().split('\n')[0];
+ const parts = line.split(' version ');
+ if (parts.length > 1) {
+ appsObj.versions.bash = parts[1].split(' ')[0].split('(')[0];
+ }
}
functionProcessed();
});
}
+ if ({}.hasOwnProperty.call(appsObj.versions, 'zsh')) {
+ exec('zsh --version', function (error, stdout) {
+ if (!error) {
+ const line = stdout.toString().split('\n')[0];
+ const parts = line.split('zsh ');
+ if (parts.length > 1) {
+ appsObj.versions.zsh = parts[1].split(' ')[0];
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'fish')) {
+ exec('fish --version', function (error, stdout) {
+ if (!error) {
+ const line = stdout.toString().split('\n')[0];
+ const parts = line.split(' version ');
+ if (parts.length > 1) {
+ appsObj.versions.fish = parts[1].split(' ')[0];
+ }
+ }
+ functionProcessed();
+ });
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'powershell')) {
+ if (_windows) {
+ util.powerShell('$PSVersionTable').then(stdout => {
+ const lines = stdout.toString().split('\n').map(line => line.replace(/ +/g, ' ').replace(/ +/g, ':'));
+ appsObj.versions.powershell = util.getVersion(lines, 'psversion');
+ functionProcessed();
+ });
+ } else {
+ functionProcessed();
+ }
+ }
+ if ({}.hasOwnProperty.call(appsObj.versions, 'dotnet')) {
+ util.powerShell('gci "HKLM:\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP" -recurse | gp -name Version,Release -EA 0 | where { $_.PSChildName -match "^(?!S)\\p{L}"} | select PSChildName, Version, Release').then(stdout => {
+ const lines = stdout.toString().split('\r\n');
+ let dotnet = '';
+ lines.forEach(line => {
+ line = line.replace(/ +/g, ' ');
+ const parts = line.split(' ');
+ dotnet = dotnet || ((parts[0].toLowerCase().startsWith('client') && parts.length > 2 ? parts[1].trim() : (parts[0].toLowerCase().startsWith('full') && parts.length > 2 ? parts[1].trim() : '')));
+ });
+ appsObj.versions.dotnet = dotnet.trim();
+ functionProcessed();
+ });
+ }
} catch (e) {
if (callback) { callback(appsObj.versions); }
resolve(appsObj.versions);
diff --git a/lib/util.js b/lib/util.js
index 00debc9..b1e2175 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -301,7 +301,7 @@ function getWmic() {
wmicPath = WINDIR + '\\system32\\wbem\\wmic.exe';
if (!fs.existsSync(wmicPath)) {
try {
- const wmicPathArray = execSync('WHERE WMIC').toString().split('\r\n');
+ const wmicPathArray = execSync('WHERE WMIC', execOptsWin).toString().split('\r\n');
if (wmicPathArray && wmicPathArray.length) {
wmicPath = wmicPathArray[0];
} else {
@@ -392,7 +392,7 @@ function getCodepage() {
if (_windows) {
if (!codepage) {
try {
- const stdout = execSync('chcp');
+ const stdout = execSync('chcp', execOptsWin);
const lines = stdout.toString().split('\r\n');
const parts = lines[0].split(':');
codepage = parts.length > 1 ? parts[1].replace('.', '') : '';
diff --git a/lib/wifi.js b/lib/wifi.js
index bec0888..20b4777 100644
--- a/lib/wifi.js
+++ b/lib/wifi.js
@@ -112,7 +112,116 @@ function wifiFrequencyFromChannel(channel) {
return {}.hasOwnProperty.call(frequencies, channel) ? frequencies[channel] : null;
}
-function getWifiNetworkAlt(iface) {
+function ifaceListLinux() {
+ const result = [];
+ const cmd = 'iw dev';
+ try {
+ const all = execSync(cmd).toString().split('\n').map(line => line.trim()).join('\n');
+ const parts = all.split('\nInterface ');
+ parts.shift();
+ parts.foreach(ifaceDetails => {
+ const lines = ifaceDetails.split('\n');
+ const iface = lines[0];
+ const id = util.toInt(util.getValue(lines, 'ifindex', ' '));
+ const mac = util.getValue(lines, 'addr', ' ');
+ const channel = util.toInt(util.getValue(lines, 'channel', ' '));
+ result.push({
+ id,
+ iface,
+ mac,
+ channel
+ });
+ });
+ return result;
+ } catch (e) {
+ return [];
+ }
+}
+
+function nmiDeviceLinux(iface) {
+ const cmd = 'nmcli -t -f general,wifi-properties,capabilities,ip4,ip6 device show ' + iface;
+ try {
+ const lines = execSync(cmd).toString().split('\n');
+ return {
+ iface,
+ type: util.getValue(lines, 'GENERAL.TYPE'),
+ vendor: util.getValue(lines, 'GENERAL.VENDOR'),
+ product: util.getValue(lines, 'GENERAL.PRODUCT'),
+ mac: util.getValue(lines, 'GENERAL.HWADDR').toLowerCase(),
+ ssid: util.getValue(lines, 'GENERAL.CONNECTION'),
+ };
+ } catch (e) {
+ return {};
+ }
+}
+
+function nmiConnectionLinux(ssid) {
+ const cmd = 'nmcli -t --show-secrets connection show ' + ssid;
+ try {
+ const lines = execSync(cmd).toString().split('\n');
+ return {
+ ssid,
+ uuid: util.getValue(lines, 'connection.uuid'),
+ type: util.getValue(lines, 'connection.type'),
+ autoconnect: util.getValue(lines, 'connection.autoconnect') === 'yes',
+ security: util.getValue(lines, '802-11-wireless-security.key-mgmt'),
+ bssid: util.getValue(lines, '802-11-wireless.seen-bssids').toLowerCase()
+ };
+ } catch (e) {
+ return {};
+ }
+}
+
+function wpaConnectionLinux(iface) {
+ const cmd = `wpa_cli -i ${iface} status`;
+ try {
+ const lines = execSync(cmd).toString().split('\n');
+ return {
+ ssid: util.getValue(lines, 'ssid', '='),
+ uuid: util.getValue(lines, 'uuid', '='),
+ security: util.getValue(lines, 'key_mgmt', '='),
+ freq: util.getValue(lines, 'freq', '='),
+ bssid: util.getValue(lines, 'bssid', '=').toLowerCase()
+ };
+ } catch (e) {
+ return {};
+ }
+}
+
+function getWifiNetworkListNmi() {
+ const result = [];
+ const cmd = 'nmcli -t -m multiline --fields active,ssid,bssid,mode,chan,freq,signal,security,wpa-flags,rsn-flags device wifi list 2>/dev/null';
+ try {
+ const stdout = execSync(cmd, { maxBuffer: 1024 * 20000 });
+ const parts = stdout.toString().split('ACTIVE:');
+ parts.shift();
+ parts.forEach(part => {
+ 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(')', '');
+ result.push({
+ ssid: util.getValue(lines, 'SSID'),
+ bssid: util.getValue(lines, 'BSSID').toLowerCase(),
+ mode: util.getValue(lines, 'MODE'),
+ channel: channel ? parseInt(channel, 10) : null,
+ frequency: frequency ? parseInt(frequency, 10) : null,
+ signalLevel: wifiDBFromQuality(util.getValue(lines, 'SIGNAL')),
+ quality: parseFloat(util.getValue(lines, 'SIGNAL')),
+ security: security && security !== 'none' ? security.split(' ') : [],
+ wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [],
+ rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : []
+ });
+ });
+ } catch (e) {
+ return [];
+ }
+}
+
+function getWifiNetworkListIw(iface) {
const result = [];
try {
let iwlistParts = execSync(`export LC_ALL=C; iwlist ${iface} scan 2>&1; unset LC_ALL`).toString().split(' Cell ');
@@ -196,80 +305,53 @@ function wifiNetworks(callback) {
process.nextTick(() => {
let result = [];
if (_linux) {
- let cmd = 'nmcli --terse --fields active,ssid,bssid,mode,chan,freq,signal,security,wpa-flags,rsn-flags device wifi list 2>/dev/null';
- exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
-
- const parts = stdout.toString().split('ACTIVE:');
- parts.shift();
- parts.forEach(part => {
- 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(')', '');
- result.push({
- ssid: util.getValue(lines, 'SSID'),
- bssid: util.getValue(lines, 'BSSID').toLowerCase(),
- mode: util.getValue(lines, 'MODE'),
- channel: channel ? parseInt(channel, 10) : null,
- frequency: frequency ? parseInt(frequency, 10) : null,
- signalLevel: wifiDBFromQuality(util.getValue(lines, 'SIGNAL')),
- quality: parseFloat(util.getValue(lines, 'SIGNAL')),
- security: security && security !== 'none' ? security.split(' ') : [],
- wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [],
- rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : []
- });
- });
-
- if (result.length === 0) {
- try {
- const iwconfigParts = execSync('export LC_ALL=C; iwconfig 2>/dev/null; unset LC_ALL').toString().split('\n\n');
- let iface = '';
- for (let i = 0; i < iwconfigParts.length; i++) {
- if (iwconfigParts[i].indexOf('no wireless') === -1) {
- iface = iwconfigParts[i].split(' ')[0];
- }
+ result = getWifiNetworkListNmi();
+ if (result.length === 0) {
+ try {
+ const iwconfigParts = execSync('export LC_ALL=C; iwconfig 2>/dev/null; unset LC_ALL').toString().split('\n\n');
+ let iface = '';
+ for (let i = 0; i < iwconfigParts.length; i++) {
+ if (iwconfigParts[i].indexOf('no wireless') === -1) {
+ iface = iwconfigParts[i].split(' ')[0];
}
- if (iface) {
- const res = getWifiNetworkAlt(iface);
- if (res === -1) {
- // try again after 4 secs
- setTimeout(function (iface) {
- const res = getWifiNetworkAlt(iface);
- if (res != -1) { result = res; }
- if (callback) {
- callback(result);
- }
- resolve(result);
- }, 4000);
- } else {
- result = res;
+ }
+ if (iface) {
+ const res = getWifiNetworkListIw(iface);
+ if (res === -1) {
+ // try again after 4 secs
+ setTimeout(function (iface) {
+ const res = getWifiNetworkListIw(iface);
+ if (res != -1) { result = res; }
if (callback) {
callback(result);
}
resolve(result);
- }
+ }, 4000);
} else {
+ result = res;
if (callback) {
callback(result);
}
resolve(result);
}
- } catch (e) {
+ } else {
if (callback) {
callback(result);
}
resolve(result);
}
- } else {
+ } catch (e) {
if (callback) {
callback(result);
}
resolve(result);
}
- });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
} else if (_darwin) {
let cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s';
exec(cmd, { maxBuffer: 1024 * 20000 }, function (error, stdout) {
@@ -361,3 +443,240 @@ function wifiNetworks(callback) {
}
exports.wifiNetworks = wifiNetworks;
+
+function getVendor(model) {
+ model = model.toLowerCase();
+ let result = '';
+ if (model.indexOf('intel') >= 0) { result = 'Intel'; }
+ else if (model.indexOf('realtek') >= 0) { result = 'Realtek'; }
+ else if (model.indexOf('qualcom') >= 0) { result = 'Qualcom'; }
+ else if (model.indexOf('broadcom') >= 0) { result = 'Broadcom'; }
+ else if (model.indexOf('cavium') >= 0) { result = 'Cavium'; }
+ else if (model.indexOf('cisco') >= 0) { result = 'Cisco'; }
+ else if (model.indexOf('marvel') >= 0) { result = 'Marvel'; }
+ else if (model.indexOf('zyxel') >= 0) { result = 'Zyxel'; }
+ else if (model.indexOf('melanox') >= 0) { result = 'Melanox'; }
+ else if (model.indexOf('d-link') >= 0) { result = 'D-Link'; }
+ else if (model.indexOf('tp-link') >= 0) { result = 'TP-Link'; }
+ else if (model.indexOf('asus') >= 0) { result = 'Asus'; }
+ else if (model.indexOf('linksys') >= 0) { result = 'Linksys'; }
+ return result;
+}
+
+function wifiConnections(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ const result = [];
+
+ if (_linux) {
+ const ifaces = ifaceListLinux();
+ const networkList = getWifiNetworkListNmi();
+ ifaces.forEach(ifaceDetail => {
+ const nmiDetails = nmiDeviceLinux(ifaceDetail.iface);
+ const wpaDetails = wpaConnectionLinux(ifaceDetail.iface);
+ const ssid = nmiDetails.ssid;
+ const network = networkList.filter(nw => nw.ssid === ssid);
+ const nmiConnection = nmiConnectionLinux(ssid);
+ const channel = network && network.length && network[0].channel ? network[0].channel : null;
+ result.push({
+ id: ifaceDetail.id,
+ iface: ifaceDetail.iface,
+ model: nmiDetails.product,
+ ssid,
+ bssid: network && network.length && network[0].bssid ? network[0].bssid : (wpaDetails && wpaDetails.bssid ? wpaDetails.bssid : null),
+ channel,
+ frequency: channel ? wifiFrequencyFromChannel(channel) : null,
+ type: nmiConnection && nmiConnection.type ? nmiConnection.type : '802.11',
+ security: nmiConnection && nmiConnection.security ? nmiConnection.security : (wpaDetails && wpaDetails.security ? wpaDetails.security : null),
+ signalLevel: network && network.length && network[0].signalLevel ? network[0].signalLevel : null,
+ txRate: null
+ });
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else if (_darwin) {
+ let cmd = 'system_profiler SPNetworkDataType';
+ exec(cmd, function (error, stdout) {
+ const parts1 = stdout.toString().split('\n\n Wi-Fi:\n\n');
+ if (parts1.length > 1) {
+ const lines = parts1[1].split('\n\n')[0].split('\n');
+ const iface = util.getValue(lines, 'BSD Device Name', ':', true);
+ const model = util.getValue(lines, 'hardware', ':', true);
+ cmd = '/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I';
+ exec(cmd, function (error, stdout) {
+ const lines2 = stdout.toString().split('\n');
+ if (lines.length > 10) {
+ const ssid = util.getValue(lines2, 'ssid', ':', true);
+ const bssid = util.getValue(lines2, 'bssid', ':', true);
+ const security = util.getValue(lines2, 'link auth', ':', true);
+ const txRate = util.getValue(lines2, 'lastTxRate', ':', true);
+ const channel = util.getValue(lines2, 'channel', ':', true).split(',')[0];
+ const type = '802.11';
+ const rssi = util.toInt(util.getValue(lines2, 'agrCtlRSSI', ':', true));
+ const noise = util.toInt(util.getValue(lines2, 'agrCtlNoise', ':', true));
+ const signalLevel = rssi - noise;
+ // const signal = wifiQualityFromDB(signalLevel);
+ if (ssid && bssid) {
+ result.push({
+ id: 'Wi-Fi',
+ iface,
+ model,
+ ssid,
+ bssid,
+ channel: util.toInt(channel),
+ frequency: channel ? wifiFrequencyFromChannel(channel) : null,
+ type,
+ security,
+ signalLevel,
+ txRate
+ });
+
+ }
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ }
+ });
+ } else if (_windows) {
+ let cmd = 'netsh wlan show interfaces';
+ exec(cmd, util.execOptsWin, function (error, stdout) {
+ const parts = stdout.toString().split(':\r\n\r\n');
+ parts.shift();
+ parts.forEach(part => {
+ const lines = part.split('\r\n');
+ if (lines.length >= 5) {
+ const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
+ const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
+ const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
+ const ssid = util.getValue(lines, 'SSID', ':', true);
+ const bssid = util.getValue(lines, 'BSSID', ':', true);
+ const signalLevel = util.getValue(lines, 'Signal', ':', true);
+ const type = util.getValue(lines, 'Radio type', ':', true) || util.getValue(lines, 'Type de radio', ':', true) || util.getValue(lines, 'Funktyp', ':', true) || null;
+ const security = util.getValue(lines, 'authentication', ':', true) || util.getValue(lines, 'Authentification', ':', true) || util.getValue(lines, 'Authentifizierung', ':', true) || null;
+ const channel = util.getValue(lines, 'Channel', ':', true) || util.getValue(lines, 'Canal', ':', true) || util.getValue(lines, 'Kanal', ':', true) || null;
+ const txRate = util.getValue(lines, 'Transmit rate (mbps)', ':', true) || util.getValue(lines, 'Transmission (mbit/s)', ':', true) || util.getValue(lines, 'Übertragungsrate (MBit/s)', ':', true) || null;
+ if (model && id && ssid && bssid) {
+ result.push({
+ id,
+ iface,
+ model,
+ ssid,
+ bssid,
+ channel: util.toInt(channel),
+ frequency: channel ? wifiFrequencyFromChannel(channel) : null,
+ type,
+ security,
+ signalLevel,
+ txRate
+ });
+ }
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.wifiConnections = wifiConnections;
+
+function wifiInterfaces(callback) {
+
+ return new Promise((resolve) => {
+ process.nextTick(() => {
+ const result = [];
+
+ if (_linux) {
+ const ifaces = ifaceListLinux();
+ ifaces.forEach(ifaceDetail => {
+ const nmiDetails = nmiDeviceLinux(ifaceDetail.iface);
+ result.push({
+ id: ifaceDetail.id,
+ iface: ifaceDetail.iface,
+ name: ifaceDetail.name,
+ model: nmiDetails.product,
+ vendor: nmiDetails.vendor,
+ mac: ifaceDetail.mac,
+ });
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ } else if (_darwin) {
+ let cmd = 'system_profiler SPNetworkDataType';
+ exec(cmd, function (error, stdout) {
+ const parts1 = stdout.toString().split('\n\n Wi-Fi:\n\n');
+ if (parts1.length > 1) {
+ const lines = parts1[1].split('\n\n')[0].split('\n');
+ const iface = util.getValue(lines, 'BSD Device Name', ':', true);
+ const mac = util.getValue(lines, 'MAC Address', ':', true);
+ const model = util.getValue(lines, 'hardware', ':', true);
+ result.push({
+ id: 'Wi-Fi',
+ iface,
+ model,
+ vendor: '',
+ mac
+ });
+ }
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else if (_windows) {
+ let cmd = 'netsh wlan show interfaces';
+ exec(cmd, util.execOptsWin, function (error, stdout) {
+ const parts = stdout.toString().split(':\r\n\r\n');
+ parts.shift();
+ parts.forEach(part => {
+ const lines = part.split('\r\n');
+ if (lines.length >= 5) {
+ const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
+ const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
+ const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
+ const mac = lines[3].indexOf(':') >= 0 ? lines[3].split(':')[1].trim() : '';
+ const vendor = getVendor(model);
+ if (iface && model && id && mac) {
+ result.push({
+ id,
+ iface,
+ model,
+ vendor,
+ mac,
+ });
+ }
+ }
+ });
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ });
+ } else {
+ if (callback) {
+ callback(result);
+ }
+ resolve(result);
+ }
+ });
+ });
+}
+
+exports.wifiInterfaces = wifiInterfaces;
diff --git a/test/si.js b/test/si.js
index 0151d62..c1e85fe 100644
--- a/test/si.js
+++ b/test/si.js
@@ -38,6 +38,8 @@ function test(f) {
else if (f === 'v') { si.versions().then(data => { if (data !== null) { resolve({ data, title: 'Versions' }); } else { resolve('not_supported'); } }); }
else if (f === 'V') { si.vboxInfo().then(data => { if (data !== null) { resolve({ data, title: 'Virtual Box' }); } else { resolve('not_supported'); } }); }
else if (f === 'w') { si.wifiNetworks().then(data => { if (data !== null) { resolve({ data, title: 'WIFI Networks' }); } else { resolve('not_supported'); } }); }
+ else if (f === 'W') { si.wifiInterfaces().then(data => { if (data !== null) { resolve({ data, title: 'WIFI Interfaces' }); } else { resolve('not_supported'); } }); }
+ else if (f === 'x') { si.wifiConnections().then(data => { if (data !== null) { resolve({ data, title: 'WIFI Connections' }); } else { resolve('not_supported'); } }); }
else if (f === 'y') { si.system().then(data => { if (data !== null) { resolve({ data, title: 'System' }); } else { resolve('not_supported'); } }); }
else if (f === 'Y') { si.battery().then(data => { if (data !== null) { resolve({ data, title: 'Battery' }); } else { resolve('not_supported'); } }); }
else if (f === 'z') { si.users().then(data => { if (data !== null) { resolve({ data, title: 'Users' }); } else { resolve('not_supported'); } }); }
diff --git a/test/test.js b/test/test.js
index 89b62d6..98775db 100644
--- a/test/test.js
+++ b/test/test.js
@@ -16,8 +16,8 @@ function printHeader() {
function printMenu() {
console.log('');
console.log('┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐');
- console.log('│ a ... Audio h ... Bluetooth s ... Services ? ... Get Object │');
- console.log('│ b ... BIOS i ... INET Latency S ... Shell , ... All Static │');
+ console.log('│ a ... Audio h ... Bluetooth s ... Services Y ... Battery ? ... Get Object │');
+ console.log('│ b ... BIOS i ... INET Latency S ... Shell z ... Users , ... All Static │');
console.log('│ B ... Baseboard I ... INET Check Site t ... time 1 ... NET Iface Default . ... All Dynamic │');
console.log('│ C ... Chassis j ... CPU Current Speed T ... CPU Temperature 2 ... NET Gateway Default / ... All │');
console.log('│ c ... CPU l ... CPU Current Load u ... USB 3 ... NET Interfaces │');
@@ -25,10 +25,11 @@ function printMenu() {
console.log('│ D ... DiskIO m ... Memory v ... Versions 5 ... NET Connections │');
console.log('│ e ... Block Devices M ... MEM Layout V ... Virtual Box 6 ... Docker Info │');
console.log('│ E ... Open Files o ... OS Info w ... WIFI networks 7 ... Docker Container │');
- console.log('│ f ... FS Size p ... Processes y ... System 8 ... Docker Cont Stats │');
- console.log('│ F ... FS Stats P ... Process Load Y ... Battery 9 ... Docker Cont Proc │');
- console.log('│ g ... Graphics r ... Printer z ... Users 0 ... Docker All q >>> QUIT │');
+ console.log('│ f ... FS Size p ... Processes W ... WIFI interfaces 8 ... Docker Cont Stats │');
+ console.log('│ F ... FS Stats P ... Process Load x ... WIFI connections 9 ... Docker Cont Proc │');
+ console.log('│ g ... Graphics r ... Printer y ... System 0 ... Docker All q >>> QUIT │');
console.log('└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘');
+
}
function EnableUserInput() {
@@ -75,6 +76,7 @@ process.stdin.on('keypress', (key, data) => {
if (!waiting) {
waiting = true;
+ console.time(['Time to complete']);
startDots();
const siPath = path.join(__dirname, 'si.js');
exec(`node ${siPath} '${key}'`, { timeout: 30000 }, (error, stdout) => {
@@ -89,9 +91,11 @@ process.stdin.on('keypress', (key, data) => {
try {
if (stdout.toString().startsWith('"no_key')) {
console.log();
+ console.timeEnd(['Time to complete']);
console.log('Menu item not found. Please select valid menu item ... Press q to quit');
} else if (stdout.toString().startsWith('"not_supported')) {
console.log();
+ console.timeEnd(['Time to complete']);
console.log('Key: ' + key);
console.log('Not supported');
} else if (stdout.toString()) {
@@ -99,6 +103,7 @@ process.stdin.on('keypress', (key, data) => {
console.log();
printTitle(data.title);
console.log(util.inspect(data.data, { colors: true, depth: 4 }));
+ console.timeEnd(['Time to complete']);
printMenu();
}
} catch (e) {
@@ -107,6 +112,7 @@ process.stdin.on('keypress', (key, data) => {
console.log('ERROR');
console.log('----------------------------------------------------------------------------------------------------');
console.log(stdout.toString());
+ console.timeEnd(['Time to complete']);
console.log();
}
}