diff --git a/.gitignore b/.gitignore index b66f952..ab247e3 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,6 @@ CVS package-lock.json yarn.lock -test/ dist/ tsconfig.json typings.d.ts diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cb124c2..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: node_js - -os: - - windows - - linux - - osx - -node_js: - - "6" - - "8" - - "10" - -sudo: false - -after_success: npm run coverage diff --git a/README.md b/README.md index 33a05ea..9ceba6e 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ I also created a nice little command line tool called [mmon][mmon-github-url] (m | | raspberry | X | | | | | optional raspberry revision data | | si.bios(cb) | {...} | X | X | X | X | | bios information | | | vendor | X | X | X | X | | e.g. 'AMI' | -| | version | X | X | | X | | version | +| | version | X | X | X | X | | version | | | releaseDate | X | X | | X | | release date | | | revision | X | X | | X | | revision | | si.baseboard(cb) | {...} | X | X | X | X | | baseboard information | diff --git a/docs/system.html b/docs/system.html index 8d973e9..4bba4df 100644 --- a/docs/system.html +++ b/docs/system.html @@ -199,7 +199,7 @@ si.system().then(data => console.log(data)); version X X - + X X version diff --git a/lib/filesystem.js b/lib/filesystem.js index 86846a9..bdd1f9c 100755 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -28,8 +28,6 @@ const _openbsd = (_platform === 'openbsd'); const _netbsd = (_platform === 'netbsd'); const _sunos = (_platform === 'sunos'); -const NOT_SUPPORTED = 'not supported'; - let _fs_speed = {}; let _disk_io = {}; @@ -463,14 +461,10 @@ function calcFsSpeed(rx, wx) { function fsStats(callback) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { process.nextTick(() => { if (_windows) { - let error = new Error(NOT_SUPPORTED); - if (callback) { - callback(NOT_SUPPORTED); - } - reject(error); + resolve(null); } let result = { @@ -609,21 +603,13 @@ function calcDiskIO(rIO, wIO) { function disksIO(callback) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { process.nextTick(() => { if (_windows) { - let error = new Error(NOT_SUPPORTED); - if (callback) { - callback(NOT_SUPPORTED); - } - reject(error); + resolve(null); } if (_sunos) { - let error = new Error(NOT_SUPPORTED); - if (callback) { - callback(NOT_SUPPORTED); - } - reject(error); + resolve(null); } let result = { diff --git a/lib/graphics.js b/lib/graphics.js index 21df1d7..3680847 100644 --- a/lib/graphics.js +++ b/lib/graphics.js @@ -181,12 +181,17 @@ function graphics(callback) { if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('framebufferdepth') !== -1) currentDisplay.pixeldepth = parseInt(parts[1]); // in BIT if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('maindisplay') !== -1 && parts[1].replace(/ +/g, '').toLowerCase() === 'yes') currentDisplay.main = true; if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('built-in') !== -1 && parts[1].replace(/ +/g, '').toLowerCase() === 'yes') { + currentDisplay.vendor = 'Apple'; currentDisplay.builtin = true; currentDisplay.connection = ''; } if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('connectiontype') !== -1) { currentDisplay.builtin = false; currentDisplay.connection = parts[1].trim(); + if (currentDisplay.connection === 'Internal') { + currentDisplay.vendor = 'Apple'; + currentDisplay.builtin = true; + } } } } diff --git a/lib/internet.js b/lib/internet.js index 9cfba16..1cc520c 100644 --- a/lib/internet.js +++ b/lib/internet.js @@ -131,21 +131,26 @@ function inetLatency(host, callback) { return new Promise((resolve) => { process.nextTick(() => { let params; + let filt; if (_linux || _freebsd || _openbsd || _netbsd || _darwin) { if (_linux) { - params = '-c 2 -w 3 ' + hostSanitized + ' | grep rtt'; + params = '-c 2 -w 3 ' + hostSanitized; + filt = 'rtt'; } if (_freebsd || _openbsd || _netbsd) { - params = '-c 2 -t 3 ' + hostSanitized + ' | grep round-trip'; + params = '-c 2 -t 3 ' + hostSanitized; + filt = 'round-trip'; } if (_darwin) { - params = '-c 2 -t 3 ' + hostSanitized + ' | grep avg'; + params = '-c2 -t3 ' + hostSanitized; + filt = 'avg'; } - execFile('ping', params.split(' '), function (error, stdout) { let result = null; if (!error) { - const line = stdout.toString().split('='); + const lines = stdout.toString().split('\n').filter(line => line.indexOf(filt) >= 0).join('\n'); + + const line = lines.split('='); if (line.length > 1) { const parts = line[1].split('/'); if (parts.length > 1) { diff --git a/lib/osinfo.js b/lib/osinfo.js index 658be84..a9821b2 100644 --- a/lib/osinfo.js +++ b/lib/osinfo.js @@ -29,8 +29,6 @@ const _openbsd = (_platform === 'openbsd'); const _netbsd = (_platform === 'netbsd'); const _sunos = (_platform === 'sunos'); -const NOT_SUPPORTED = 'not supported'; - // -------------------------- // Get current time and OS uptime @@ -926,14 +924,10 @@ function versions(apps, callback) { exports.versions = versions; function shell(callback) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { process.nextTick(() => { if (_windows) { - let error = new Error(NOT_SUPPORTED); - if (callback) { - callback(NOT_SUPPORTED); - } - reject(error); + resolve(null); } let result = ''; @@ -969,7 +963,6 @@ function uuid(callback) { const jsonObj = JSON.parse(stdout.toString()); if (jsonObj.SPHardwareDataType && jsonObj.SPHardwareDataType.length > 0) { const spHardware = jsonObj.SPHardwareDataType[0]; - console.log(spHardware); // result.os = parts.length > 1 ? parts[1].trim().toLowerCase() : ''; result.os = spHardware.platform_UUID; result.hardware = spHardware.serial_number; @@ -987,9 +980,9 @@ function uuid(callback) { if (_linux) { const cmd = `echo -n "os: "; cat /var/lib/dbus/machine-id 2> /dev/null; echo; echo -n "os: "; cat /etc/machine-id 2> /dev/null; echo; -echo -n "machine: "; cat /sys/class/dmi/id/product_uuid 2> /dev/null; echo;`; +echo -n "hardware: "; cat /sys/class/dmi/id/product_uuid 2> /dev/null; echo;`; exec(cmd, function (error, stdout) { - const lines = stdout.toString.split('\n'); + const lines = stdout.toString().split('\n'); result.os = util.getValue(lines, 'os').toLowerCase(); result.hardware = util.getValue(lines, 'hardware').toLowerCase(); if (callback) { @@ -1002,7 +995,7 @@ echo -n "machine: "; cat /sys/class/dmi/id/product_uuid 2> /dev/null; echo;`; const cmd = `echo -n "os: "; sysctl -n kern.hostid; echo; echo -n "hardware: "; sysctl -n kern.hostuuid; echo;`; exec(cmd, function (error, stdout) { - const lines = stdout.toString.split('\n'); + const lines = stdout.toString().split('\n'); result.os = util.getValue(lines, 'os').toLowerCase(); result.hardware = util.getValue(lines, 'hardware').toLowerCase(); if (result.os.indexOf('unknown') >= 0) { result.os = ''; } diff --git a/lib/printer.js b/lib/printer.js index 9a126b5..e272f05 100644 --- a/lib/printer.js +++ b/lib/printer.js @@ -28,8 +28,6 @@ const _openbsd = (_platform === 'openbsd'); const _netbsd = (_platform === 'netbsd'); const _sunos = (_platform === 'sunos'); -const NOT_SUPPORTED = 'not supported'; - const winPrinterStatus = { 1: 'Other', 2: 'Unknown', @@ -117,7 +115,7 @@ function parseWindowsPrinters(lines, id) { function printer(callback) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { process.nextTick(() => { let result = []; if (_linux || _freebsd || _openbsd || _netbsd) { @@ -145,6 +143,10 @@ function printer(callback) { result.push(printers); } }); + if (callback) { + callback(result); + } + resolve(result); } else { if (callback) { callback(result); @@ -196,11 +198,7 @@ function printer(callback) { }); } if (_sunos) { - let error = new Error(NOT_SUPPORTED); - if (callback) { - callback(NOT_SUPPORTED); - } - reject(error); + resolve(null); } }); }); diff --git a/lib/processes.js b/lib/processes.js index cd24ddb..886af59 100644 --- a/lib/processes.js +++ b/lib/processes.js @@ -973,10 +973,10 @@ function processLoad(proc, callback) { } if (_darwin || _linux) { - const params = '-axo pid,pcpu,pmem,comm | grep -i ' + procSanitized + ' | grep -v grep'; + const params = '-axo pid,pcpu,pmem,comm'; execFile('ps', params.split(' '), { maxBuffer: 1024 * 20000 }, function (error, stdout) { if (!error) { - let lines = stdout.toString().split('\n'); + let lines = stdout.toString().split('\n').filter(line => line.toLowerCase().indexOf(procSanitized.toLowerCase()) >= 0 && line.toLowerCase().indexOf('grep') === -1); let pid = 0; let pids = []; diff --git a/lib/system.js b/lib/system.js index bd50102..e33664f 100644 --- a/lib/system.js +++ b/lib/system.js @@ -449,8 +449,21 @@ function bios(callback) { } if (_darwin) { result.vendor = 'Apple Inc.'; - if (callback) { callback(result); } - resolve(result); + exec( + 'system_profiler SPHardwareDataType -json', function (error, stdout) { + try { + const hardwareData = JSON.parse(stdout.toString()); + if (hardwareData && hardwareData.SPHardwareDataType && hardwareData.SPHardwareDataType.length) { + let bootRomVersion = hardwareData.SPHardwareDataType[0].boot_rom_version; + bootRomVersion = bootRomVersion ? bootRomVersion.split('(')[0].trim() : null + result.version = bootRomVersion; + } + } catch (e) { + util.noop() + } + if (callback) { callback(result); } + resolve(result); + }); } if (_sunos) { result.vendor = 'Sun Microsystems'; diff --git a/lib/usb.js b/lib/usb.js index ee88bae..ef0143f 100644 --- a/lib/usb.js +++ b/lib/usb.js @@ -28,7 +28,21 @@ const _openbsd = (_platform === 'openbsd'); const _netbsd = (_platform === 'netbsd'); const _sunos = (_platform === 'sunos'); -const NOT_SUPPORTED = 'not supported'; +function getLinuxUsbType(type, name) { + let result = type; + const str = (name + ' ' + type).toLowerCase(); + if (str.indexOf('camera') >= 0) { result = 'Camera'; } + else if (str.indexOf('hub') >= 0) { result = 'Hub'; } + else if (str.indexOf('keybrd') >= 0) { result = 'Keyboard'; } + else if (str.indexOf('keybroard') >= 0) { result = 'Keyboard'; } + else if (str.indexOf('mouse') >= 0) { result = 'Mouse'; } + else if (str.indexOf('stora') >= 0) { result = 'Storage'; } + else if (str.indexOf('mic') >= 0) { result = 'Microphone'; } + else if (str.indexOf('headset') >= 0) { result = 'Audio'; } + else if (str.indexOf('audio') >= 0) { result = 'Audio'; } + + return result; +} function parseLinuxUsb(usb) { const result = {}; @@ -45,29 +59,29 @@ function parseLinuxUsb(usb) { result.bus = null; result.deviceId = null; } - const idVendor = util.getValue(lines, 'idVendor', ' ', true); + const idVendor = util.getValue(lines, 'idVendor', ' ', true).trim(); let vendorParts = idVendor.split(' '); vendorParts.shift(); const vendor = vendorParts.join(' '); - const idProduct = util.getValue(lines, 'idProduct', ' ', true); + const idProduct = util.getValue(lines, 'idProduct', ' ', true).trim(); let productParts = idProduct.split(' '); productParts.shift(); const product = productParts.join(' '); - const interfaceClass = util.getValue(lines, 'bInterfaceClass', ' ', true); + const interfaceClass = util.getValue(lines, 'bInterfaceClass', ' ', true).trim(); let interfaceClassParts = interfaceClass.split(' '); interfaceClassParts.shift(); const usbType = interfaceClassParts.join(' '); - const iManufacturer = util.getValue(lines, 'iManufacturer', ' ', true); + const iManufacturer = util.getValue(lines, 'iManufacturer', ' ', true).trim(); let iManufacturerParts = iManufacturer.split(' '); iManufacturerParts.shift(); const manufacturer = iManufacturerParts.join(' '); - result.id = idVendor.startWith('0x') ? idVendor.split(' ').substr(2, 10) : '' + ':' + idProduct.startWith('0x') ? idProduct.split(' ').substr(2, 10) : ''; + result.id = (idVendor.startsWith('0x') ? idVendor.split(' ')[0].substr(2, 10) : '') + ':' + (idProduct.startsWith('0x') ? idProduct.split(' ')[0].substr(2, 10) : ''); result.name = product - result.type = usbType; + result.type = getLinuxUsbType(usbType, product); result.removable = null; result.vendor = vendor; result.manufacturer = manufacturer @@ -100,6 +114,9 @@ function getDarwinUsbType(name) { else if (name.indexOf('bth') >= 0) { result = 'Bluetooth'; } else if (name.indexOf('rfcomm') >= 0) { result = 'Bluetooth'; } else if (name.indexOf('usbhub') >= 0) { result = 'Hub'; } + else if (name.indexOf(' hub') >= 0) { result = 'Hub'; } + else if (name.indexOf('mouse') >= 0) { result = 'Mouse'; } + else if (name.indexOf('mic') >= 0) { result = 'Microphone'; } return result; } @@ -119,18 +136,19 @@ function parseDarwinUsb(usb, id) { if (lines[i] !== '{' && lines[i] !== '}' && lines[i + 1] && lines[i + 1].trim() !== '}') { lines[i] = lines[i] + ','; } - lines[i] = lines[i].replace(' Yes,', '"Yes",'); + lines[i] = lines[i].replace(': Yes,', ': "Yes",'); + lines[i] = lines[i].replace(': No,', ': "No",'); } const usbObj = JSON.parse(lines.join('\n')); result.bus = null; result.deviceId = null; - result.id = usbObj['USB Address']; - result.name = usbObj['kUSBProductString']; - result.type = getDarwinUsbType(usbObj['kUSBProductString'].toLowerCase()); + result.id = usbObj['USB Address'] || null; + result.name = usbObj['kUSBProductString'] || usbObj['USB Product Name'] || null; + result.type = getDarwinUsbType((usbObj['kUSBProductString'] || usbObj['USB Product Name'] || '').toLowerCase()); result.removable = usbObj['Built-In'].toLowerCase() !== 'yes'; - result.vendor = usbObj['kUSBVendorString']; - result.manufacturer = usbObj['kUSBVendorString']; + result.vendor = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null; + result.manufacturer = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null; result.maxPower = null; result.serialNumber = usbObj['kUSBSerialNumberString'] || null; @@ -185,7 +203,7 @@ function parseWindowsUsb(lines, id) { function usb(callback) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { process.nextTick(() => { let result = []; if (_linux) { @@ -209,7 +227,7 @@ function usb(callback) { exec(cmd, {maxBuffer: 1024 * 1024 * 128}, function (error, stdout) { if (!error) { const parts = (stdout.toString()).split(' +-o '); - for (let i = 2; i < parts.length; i++) { + for (let i = 1; i < parts.length; i++) { const usb = parseDarwinUsb(parts[i]); if (usb) { result.push(usb) @@ -244,11 +262,7 @@ function usb(callback) { }); } if (_sunos || _freebsd || _openbsd || _netbsd) { - let error = new Error(NOT_SUPPORTED); - if (callback) { - callback(NOT_SUPPORTED); - } - reject(error); + resolve(null); } }); }); diff --git a/lib/util.js b/lib/util.js index 736da8e..93dd839 100644 --- a/lib/util.js +++ b/lib/util.js @@ -109,7 +109,7 @@ function getValue(lines, property, separator, trimmed) { line = line.trim(); } if (line.startsWith(property)) { - const parts = lines[i].split(separator); + const parts = trimmed ? lines[i].trim().split(separator) : lines[i].split(separator); if (parts.length >= 2) { parts.shift(); return parts.join(separator).trim(); diff --git a/package.json b/package.json index eae28d6..538c424 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "network connections", "network stats", "iface", + "printer", "processes", "users", "internet", @@ -66,6 +67,9 @@ "display", "smart", "disk layout", + "usb", + "audio", + "bluetooth", "wifi", "wifinetworks", "virtual box", @@ -91,34 +95,5 @@ ], "engines": { "node": ">=4.0.0" - }, - "devDependencies": { - "@types/chai": "^4.1.7", - "@types/mocha": "^5.2.5", - "@types/node": "^10.12.18", - "chai": "^4.2.0", - "coveralls": "^3.0.2", - "mocha": "^5.2.0", - "nyc": "^13.1.0", - "rimraf": "^2.6.2", - "source-map-support": "^0.5.9", - "ts-node": "^7.0.1", - "typescript": "^3.2.2" - }, - "nyc": { - "extension": [ - ".js" - ], - "include": [ - "lib/**" - ], - "exclude": [ - "**/*.d.ts" - ], - "reporter": [ - "html", - "text" - ], - "all": true } } diff --git a/test/si.js b/test/si.js new file mode 100644 index 0000000..b49ad6a --- /dev/null +++ b/test/si.js @@ -0,0 +1,51 @@ +const si = require('../lib/index'); + +function test(f) { + return new Promise((resolve) => { + process.nextTick(() => { + if (f === 'a') { si.audio().then(data => resolve({ data, title: 'Audio' }) )} + else if (f === 'b') { si.bios().then(data => resolve({ data, title: 'BIOS' })) } + else if (f === 'B') { si.baseboard().then(data => resolve({ data, title: 'Baseboard' })) } + else if (f === 'C') { si.chassis().then(data => resolve({ data, title: 'Chassis' })) } + else if (f === 'c') { si.cpu().then(data => resolve({ data, title: 'CPU' })) } + else if (f === 'd') { si.diskLayout().then(data => resolve({ data, title: 'Disk Layout' })) } + else if (f === 'D') { si.disksIO().then(data => resolve({ data, title: 'Disks IO' })) } + else if (f === 'e') { si.blockDevices().then(data => resolve({ data, title: 'Block Devices' })) } + else if (f === 'E') { si.fsOpenFiles().then(data => resolve({ data, title: 'Open Files' })) } + else if (f === 'f') { si.fsSize().then(data => resolve({ data, title: 'File System' })) } + else if (f === 'F') { si.fsStats().then(data => resolve({ data, title: 'FS Stats' })) } + else if (f === 'g') { si.graphics().then(data => resolve({ data, title: 'Graphics' })) } + else if (f === 'h') { si.bluetooth().then(data => resolve({ data, title: 'Bluetooth' })) } + else if (f === 'i') { si.inetLatency().then(data => resolve({ data, title: 'Internet Latency' })) } + else if (f === 'I') { si.inetChecksite('www.plus-innovations.com').then(data => resolve({ data, title: 'Internet Check Site' })) } + else if (f === 'l') { si.cpuCurrentspeed().then(data => resolve({ data, title: 'CPU Current Speed' })) } + else if (f === 'L') { si.fullLoad().then(data => resolve({ data, title: 'CPU Full Load' })) } + else if (f === 'm') { si.mem().then(data => resolve({ data, title: 'Memory' })) } + else if (f === 'M') { si.memLayout().then(data => resolve({ data, title: 'Memory Layout' })) } + else if (f === 'o') { si.osInfo().then(data => resolve({ data, title: 'OS Info' })) } + else if (f === 'p') { si.processes().then(data => resolve({ data, title: 'Processes' })) } + else if (f === 'P') { si.processLoad('postgres').then(data => resolve({ data, title: 'Process Load' })) } + else if (f === 'r') { si.printer().then(data => resolve({ data, title: 'Printer' })) } + else if (f === 's') { si.services('apache2, postgres').then(data => resolve({ data, title: 'Services' })) } + else if (f === 'S') { si.shell().then(data => resolve({ data, title: 'Shell' })) } + else if (f === 't') { resolve({ data: si.time(), title: 'Time' }) } + else if (f === 'T') { si.cpuTemperature().then(data => resolve({ data, title: 'CPU Temperature' })) } + else if (f === 'u') { si.usb().then(data => resolve({ data, title: 'USB' })) } + else if (f === 'U') { si.uuid().then(data => resolve({ data, title: 'UUID' })) } + else if (f === 'v') { si.versions().then(data => resolve({ data, title: 'Versions' })) } + else if (f === 'V') { si.vboxInfo().then(data => resolve({ data, title: 'Virtual Box' })) } + else if (f === 'w') { si.wifiNetworks().then(data => resolve({ data, title: 'WIFI Networks' })) } + else if (f === 'y') { si.battery().then(data => resolve({ data, title: 'Battery' })) } + else if (f === 'z') { si.users().then(data => resolve({ data, title: 'Users' })) } + else resolve(); + }) + }) +} + +const key = process.argv[2]; + +// console.log(process.argv); + +test(key).then(data => { + console.log(JSON.stringify(data)); +}) diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..9462f06 --- /dev/null +++ b/test/test.js @@ -0,0 +1,57 @@ +const readline = require('readline'); +const util = require('util'); +const { exec } = require('child_process'); + +function printMenu() { + console.log(''); + console.log('-----------------------------------------------------------------------------------------------------------------------------------'); + console.log('a ... Audio g ... Graphics p ... Processes w ... WIFI networks 1 ... NET Iface Default'); + console.log('b ... BIOS h ... Bluetooth P ... Process Load y ... Battery 2 ... NET Gateway Default'); + console.log('B ... Baseboard i ... INET Latency r ... Printer z ... Users 3 ... NET Interfaces'); + console.log('C ... Chassis I ... INET Check Site s ... Services 4 ... NET Stats'); + console.log('c ... CPU l ... CPU Load S ... Shell 5 ... NET Connections'); + console.log('d ... DiskLayout L ... Full Load t ... time 6 ... Docker Info'); + console.log('D ... DiskIO n ... T ... CPU Temperature + ... All Static 7 ... Docker Container'); + console.log('e ... Block Devices m ... Memory u ... USB - ... All Dynamic 8 ... Docker Cont Stats'); + console.log('E ... Open Files M ... MEM Layout U ... UUID # ... All 9 ... Docker Cont Proc'); + console.log('f ... FS Size o ... OS Info v ... Versions , ... Get Object 0 ... Docker All'); + console.log('F ... FS Stats O ... V ... VirtualBox . ... Observe q >>> Quit'); + console.log('-----------------------------------------------------------------------------------------------------------------------------------'); +} + +function EnableUserInput() { + readline.emitKeypressEvents(process.stdin); + process.stdin.setRawMode(true); +} + +// function DisableUserInput() { +// process.stdin.removeAllListeners() +// } +function noop() { } + +process.stdin.on('keypress', (key, data) => { + // console.log(data); + if (data.name === 'q' && !data.shift) { + // shut down + process.exit() + } + + exec('node si.js ' + key, (error, stdout) => { + try { + if (stdout.toString()) { + data = JSON.parse(stdout.toString()); + console.log(); + console.log('==============================='); + console.log('[ ' + data.title + ' ]'); + console.log('==============================='); + console.log(util.inspect(data.data, { colors: true, depth: 4 })); + printMenu(); + } + } catch (e) { + noop(); + } + }) +}); + +printMenu(); +EnableUserInput();