systeminformation
Advanced tools
Comparing version 3.22.0 to 3.23.0
@@ -19,2 +19,5 @@ # Changelog | ||
- `diskLayout`: returns hard disk layout (new in version 3.23) | ||
- `memLayout`: returns memory chip layout (new in version 3.23) | ||
- Windows support: for some basic functions (new in version 3.17 ff) | ||
- `cpuCache`: returns CPU cache (L1, L2, L3) sizes (new in version 3.14) | ||
@@ -99,2 +102,3 @@ - `cpuFlags`: returns CPU flags (new in version 3.14) | ||
| -------------- | -------------- | -------- | | ||
| 3.23.0 | 2017-06-22 | added `memLayout`, `diskLayout`, extended windows support (`inetChecksite`)| | ||
| 3.22.0 | 2017-06-19 | extended windows support (`users`, `inetLatency`) | | ||
@@ -101,0 +105,0 @@ | 3.21.0 | 2017-06-18 | extended time (timezone), extended windows support (battery, getAll...) | |
@@ -123,6 +123,7 @@ 'use strict'; | ||
let status = parseInt(getValue(lines, 'BatteryStatus', '=') || '2'); | ||
result.ischarging = (status >= 6 && status <= 9); | ||
result.hasbattery = true; | ||
result.maxcapacity = parseInt(getValue(lines, 'DesignCapacity', '=') || 0); | ||
result.percent = parseInt(getValue(lines, 'EstimatedChargeRemaining', '=') || 0); | ||
result.currentcapacity = parseInt(result.maxcapacity * result.percent / 100); | ||
result.ischarging = (status >= 6 && status <= 9) || (!(status === 3) && !(status === 1) && result.percent < 100); | ||
} | ||
@@ -129,0 +130,0 @@ if (callback) { callback(result) } |
@@ -17,2 +17,3 @@ 'use strict'; | ||
const exec = require('child_process').exec; | ||
const execSync = require('child_process').execSync; | ||
const fs = require('fs'); | ||
@@ -31,2 +32,23 @@ const util = require('./util'); | ||
function getValue(lines, property, separator, trimmed) { | ||
separator = separator || ':'; | ||
property = property.toLowerCase(); | ||
for (let i = 0; i < lines.length; i++) { | ||
let line = lines[i].toLowerCase(); | ||
if (trimmed) { | ||
line = line.trim(); | ||
} | ||
if (line.toLowerCase().startsWith(property)) { | ||
const parts = lines[i].split(separator); | ||
if (parts.length >= 2) { | ||
parts.shift(); | ||
return parts.join(':').trim(); | ||
} else { | ||
return '' | ||
} | ||
} | ||
} | ||
return ''; | ||
} | ||
// -------------------------- | ||
@@ -564,1 +586,120 @@ // FS - mounted file systems | ||
exports.disksIO = disksIO; | ||
function diskLayout(callback) { | ||
return new Promise((resolve, reject) => { | ||
process.nextTick(() => { | ||
let result = []; | ||
if (_linux) { | ||
exec("lshw -class disk", function (error, stdout) { | ||
if (!error) { | ||
let devices = stdout.toString().split('*-'); | ||
devices.shift(); | ||
devices.forEach(function (device) { | ||
let lines = device.split('\n'); | ||
const logical = getValue(lines, 'logical name', ':', true).trim().replace(/\/dev\//g, ''); | ||
const mediumType = execSync('cat /sys/block/' + logical + '/queue/rotational').toString().split('\n')[0]; | ||
const size = getValue(lines, 'size', ':', true).trim(); | ||
if (size && lines.length > 0 && lines[0].trim() === 'disk') { | ||
result.push({ | ||
type: (mediumType === '0' ? 'SSD' : (mediumType === '1' ? 'HD' : (device.indexOf('SSD') > -1 ? 'SSD' : 'HD'))), // to be tested ... /sys/block/sda/queue/rotational | ||
name: getValue(lines, 'product:', ':', true), | ||
vendor: getValue(lines, 'vendor:', ':', true), | ||
size: parseInt(size.match(/\(([^)]+)\)/)[1]) * 1000 * 1000 * 1000 * 1000, | ||
bytesPerSector: -1, | ||
totalCylinders: -1, | ||
totalHeads: -1, | ||
totalSectors: -1, | ||
totalTracks: -1, | ||
tracksPerCylinder: -1, | ||
sectorsPerTrack: -1, | ||
firmwareRevision: getValue(lines, 'version:', ':', true).trim(), | ||
serialNum: getValue(lines, 'serial:', ':', true).trim(), | ||
interfaceType: '', | ||
}) | ||
} | ||
}); | ||
} | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}); | ||
} | ||
if (_darwin) { | ||
exec("system_profiler SPSerialATADataType", function (error, stdout) { | ||
if (!error) { | ||
let devices = stdout.toString().split(' Physical Interconnect: SATA'); | ||
devices.shift(); | ||
devices.forEach(function (device) { | ||
let lines = device.split('\n'); | ||
const mediumType = getValue(lines, 'Medium Type', ':', true).trim(); | ||
const sizeStr = getValue(lines, 'capacity', ':', true).trim(); | ||
if (sizeStr) { | ||
let size = parseInt(sizeStr.match(/\(([^)]+)\)/)[1].replace(/\./g, "")); | ||
if (!size) { | ||
size = parseInt(sizeStr); | ||
} | ||
if (size) { | ||
result.push({ | ||
type: mediumType.startsWith('Solid') ? 'SSD' : 'HD', | ||
name: getValue(lines, 'Model', ':', true).trim(), | ||
vendor: '', | ||
size: size, | ||
bytesPerSector: -1, | ||
totalCylinders: -1, | ||
totalHeads: -1, | ||
totalSectors: -1, | ||
totalTracks: -1, | ||
tracksPerCylinder: -1, | ||
sectorsPerTrack: -1, | ||
firmwareRevision: getValue(lines, 'Revision', ':', true).trim(), | ||
serialNum: getValue(lines, 'Serial Number', ':', true).trim(), | ||
interfaceType: getValue(lines, 'InterfaceType', ':', true).trim() | ||
}) | ||
} | ||
} | ||
}); | ||
} | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}); | ||
} | ||
if (_windows) { | ||
exec("wmic diskdrive get /value", function (error, stdout) { | ||
if (!error) { | ||
let devices = stdout.toString().split('\r\n\r\n\r\n'); | ||
devices.forEach(function (device) { | ||
let lines = device.split('\r\n'); | ||
const size = getValue(lines, 'Size', '=').trim(); | ||
if (size) { | ||
result.push({ | ||
type: device.indexOf('SSD') > -1 ? 'SSD' : 'HD', // not really correct(!) ... maybe this obe is better: MSFT_PhysicalDisk - Media Type?? | ||
name: getValue(lines, 'Caption', '='), | ||
vendor: getValue(lines, 'Manufacturer', '='), | ||
size: parseInt(size), | ||
bytesPerSector: parseInt(getValue(lines, 'BytesPerSector', '=')), | ||
totalCylinders: parseInt(getValue(lines, 'TotalCylinders', '=')), | ||
totalHeads: parseInt(getValue(lines, 'TotalHeads', '=')), | ||
totalSectors: parseInt(getValue(lines, 'TotalSectors', '=')), | ||
totalTracks: parseInt(getValue(lines, 'TotalTracks', '=')), | ||
tracksPerCylinder: parseInt(getValue(lines, 'TracksPerCylinder', '=')), | ||
sectorsPerTrack: parseInt(getValue(lines, 'SectorsPerTrack', '=')), | ||
firmwareRevision: getValue(lines, 'FirmwareRevision', '=').trim(), | ||
serialNum: getValue(lines, 'SerialNumber', '=').trim(), | ||
interfaceType: getValue(lines, 'InterfaceType', '=').trim() | ||
}) | ||
} | ||
}); | ||
} | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
exports.diskLayout = diskLayout; |
@@ -145,4 +145,10 @@ 'use strict'; | ||
data.net = res; | ||
if (callback) { callback(data) } | ||
resolve(data); | ||
mem.memLayout().then(res => { | ||
data.memLayout = res; | ||
filesystem.diskLayout().then(res => { | ||
data.diskLayout = res; | ||
if (callback) { callback(data) } | ||
resolve(data); | ||
}) | ||
}) | ||
}) | ||
@@ -355,3 +361,4 @@ }) | ||
exports.mem = mem; | ||
exports.mem = mem.mem; | ||
exports.memLayout = mem.memLayout; | ||
@@ -366,2 +373,3 @@ exports.battery = battery; | ||
exports.disksIO = filesystem.disksIO; | ||
exports.diskLayout = filesystem.diskLayout; | ||
@@ -368,0 +376,0 @@ exports.networkInterfaceDefault = network.networkInterfaceDefault; |
@@ -33,7 +33,2 @@ 'use strict'; | ||
process.nextTick(() => { | ||
if (_windows) { | ||
let error = new Error(NOT_SUPPORTED); | ||
if (callback) { callback(NOT_SUPPORTED) } | ||
reject(error); | ||
} | ||
@@ -47,13 +42,47 @@ let result = { | ||
if (url) { | ||
url = url.toLowerCase(); | ||
let t = Date.now(); | ||
let args = " -I --connect-timeout 5 -m 5 " + url + " 2>/dev/null | head -n 1 | cut -d ' ' -f2"; | ||
let cmd = "curl"; | ||
exec(cmd + args, function (error, stdout) { | ||
let statusCode = parseInt(stdout.toString()); | ||
result.status = statusCode || 404; | ||
result.ok = !error && (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304); | ||
result.ms = (result.ok ? Date.now() - t : -1); | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}) | ||
if (_linux || _darwin) { | ||
let args = " -I --connect-timeout 5 -m 5 " + url + " 2>/dev/null | head -n 1 | cut -d ' ' -f2"; | ||
let cmd = "curl"; | ||
exec(cmd + args, function (error, stdout) { | ||
let statusCode = parseInt(stdout.toString()); | ||
result.status = statusCode || 404; | ||
result.ok = !error && (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304); | ||
result.ms = (result.ok ? Date.now() - t : -1); | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}) | ||
} | ||
if (_windows) { // if this is stable, this can be used for all OS types | ||
const http = (url.startsWith('https:') ? require('https') : require('http')); | ||
try { | ||
http.get(url, (res) => { | ||
const { statusCode } = res; | ||
result.status = statusCode || 404; | ||
result.ok = (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304); | ||
if (statusCode !== 200) { | ||
res.resume(); | ||
result.ms = (result.ok ? Date.now() - t : -1); | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
} else { | ||
res.on('data', (chunk) => { }); | ||
res.on('end', () => { | ||
result.ms = (result.ok ? Date.now() - t : -1); | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}) | ||
} | ||
}).on('error', err => { | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}); | ||
} catch (err) { | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
} | ||
} | ||
} else { | ||
@@ -60,0 +89,0 @@ if (callback) { callback(result) } |
@@ -27,2 +27,22 @@ 'use strict'; | ||
function getValue(lines, property, separator, trimmed) { | ||
separator = separator || ':'; | ||
property = property.toLowerCase(); | ||
for (let i = 0; i < lines.length; i++) { | ||
let line = lines[i].toLowerCase(); | ||
if (trimmed) { | ||
line = line.trim(); | ||
} | ||
if (line.toLowerCase().startsWith(property)) { | ||
const parts = lines[i].split(separator); | ||
if (parts.length >= 2) { | ||
parts.shift(); | ||
return parts.join(':').trim(); | ||
} else { | ||
return '' | ||
} | ||
} | ||
} | ||
return ''; | ||
} | ||
// _______________________________________________________________________________________ | ||
@@ -78,3 +98,3 @@ // | R A M | H D | | ||
module.exports = function (callback) { | ||
function mem(callback) { | ||
@@ -179,2 +199,101 @@ return new Promise((resolve, reject) => { | ||
}); | ||
}; | ||
} | ||
exports.mem = mem; | ||
function memLayout(callback) { | ||
return new Promise((resolve, reject) => { | ||
process.nextTick(() => { | ||
let result = []; | ||
if (_linux) { | ||
exec("dmidecode -t memory | grep -iE 'Size:|Type|Speed|Manufacturer|Form Factor|Locator|Memory Device|Serial Number|Voltage'", function (error, stdout) { | ||
if (!error) { | ||
let devices = stdout.toString().split('Memory Device'); | ||
devices.shift(); | ||
devices.forEach(function (device) { | ||
let lines = device.split('\n'); | ||
result.push({ | ||
size: parseInt(getValue(lines, ' Size'))*1024*1024, | ||
bank: getValue(lines, ' Bank Locator'), | ||
type: getValue(lines, ' Type:'), | ||
clockSpeed: (getValue(lines, ' Configured Clock Speed:') ? parseInt(getValue(lines, ' Configured Clock Speed:')) : parseInt(getValue(lines, ' Speed:'))), | ||
formFactor: getValue(lines, ' Form Factor:'), | ||
partNum: '', | ||
serialNum: getValue(lines, ' Serial Number:'), | ||
voltageConfigured: parseFloat(getValue(lines, ' Configured Voltage:')), | ||
voltageMin: parseFloat(getValue(lines, ' Minimum Voltage:')), | ||
voltageMax: parseFloat(getValue(lines, ' Maximum Voltage:')), | ||
}) | ||
}); | ||
} | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}); | ||
} | ||
if (_darwin) { | ||
exec("system_profiler SPMemoryDataType", function (error, stdout) { | ||
if (!error) { | ||
let devices = stdout.toString().split(' BANK '); | ||
devices.shift(); | ||
devices.forEach(function (device) { | ||
let lines = device.split('\n'); | ||
const size = parseInt(getValue(lines, ' Size')); | ||
if (size) { | ||
result.push({ | ||
size: size * 1024 * 1024 * 1024, | ||
bank: '', | ||
type: getValue(lines, ' Type:'), | ||
clockSpeed: parseInt(getValue(lines, ' Speed:')), | ||
formFactor: '', | ||
partNum: getValue(lines, ' Part Number:'), | ||
serialNum: getValue(lines, ' Serial Number:'), | ||
voltageConfigured: -1, | ||
voltageMin: -1, | ||
voltageMax: -1, | ||
}) | ||
} | ||
}); | ||
} | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}); | ||
} | ||
if (_windows) { | ||
const memoryTypes = 'Unknown|Other|DRAM|Synchronous DRAM|Cache DRAM|EDO|EDRAM|VRAM|SRAM|RAM|ROM|FLASH|EEPROM|FEPROM|EPROM|CDRAM|3DRAM|SDRAM|SGRAM|RDRAM|DDR|DDR2|DDR2 FB-DIMM|Reserved|DDR3|FBD2|DDR4|LPDDR|LPDDR2|LPDDR3|LPDDR4'.split('|') | ||
const FormFactors = 'Unknown|Other|SIP|DIP|ZIP|SOJ|Proprietary|SIMM|DIMM|TSOP|PGA|RIMM|SODIMM|SRIMM|SMD|SSMP|QFP|TQFP|SOIC|LCC|PLCC|BGA|FPBGA|LGA'.split('|'); | ||
exec("wmic memorychip get BankLabel, Capacity, ConfiguredClockSpeed, ConfiguredVoltage, MaxVoltage, MinVoltage, DataWidth, FormFactor, Manufacturer, MemoryType, PartNumber, SerialNumber, Speed, Tag /value", function (error, stdout) { | ||
if (!error) { | ||
let devices = stdout.toString().split('BankL'); | ||
devices.shift(); | ||
devices.forEach(function (device) { | ||
let lines = device.split('\r\n'); | ||
result.push({ | ||
size: parseInt(getValue(lines, 'Capacity', '=')), | ||
bank: getValue(lines, 'abel', '='), // BankLabel | ||
type: memoryTypes[parseInt(getValue(lines, 'MemoryType', '='))], | ||
clockSpeed: parseInt(getValue(lines, 'ConfiguredClockSpeed', '=')), | ||
formFactor: FormFactors[parseInt(getValue(lines, 'FormFactor', '='))], | ||
partNum: getValue(lines, 'PartNumber', '='), | ||
serialNum: getValue(lines, 'SerialNumber', '='), | ||
voltageConfigured: parseInt(getValue(lines, 'ConfiguredVoltage', '=')) / 1000.0, | ||
voltageMin: parseInt(getValue(lines, 'MinVoltage', '=')) / 1000.0, | ||
voltageMax: parseInt(getValue(lines, 'MaxVoltage', '=')) / 1000.0, | ||
}) | ||
}); | ||
} | ||
if (callback) { callback(result) } | ||
resolve(result); | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
exports.memLayout = memLayout; | ||
{ | ||
"name": "systeminformation", | ||
"version": "3.22.0", | ||
"version": "3.23.0", | ||
"description": "Simple system and OS information library", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -44,3 +44,3 @@ # systeminformation | ||
### Latest Activity | ||
- Version 3.23.0: added `memLayout`, `diskLayout`, extended windows support (`inetChecksite`) | ||
- Version 3.22.0: extended windows support (`users`, `inetLatency`) | ||
@@ -159,2 +159,27 @@ - Version 3.21.0: extended `time` (timezone), extended windows support (`battery`, `getAll...`) | ||
| | swapfree | X | X | X | | | ||
| si.memLayout(cb) | {...} | X | X | X | Memory Layout | | ||
| | size | X | X | X | size in bytes | | ||
| | bank | X | | X | memory bank | | ||
| | type | X | X | X | memory type | | ||
| | clockSpeed | X | X | X | clock speed | | ||
| | formFactor | X | | X | form factor | | ||
| | partNum | | X | X | part number | | ||
| | serialNum | X | X | X | serial number | | ||
| | voltageConfigured | X | | X | voltage conf. | | ||
| | voltageMin | X | | X | voltage min | | ||
| | voltageMax | X | | X | voltage max | | ||
| si.diskLayout(cb) | {...} | X | X | X | Physical Disk Layout (HD) | | ||
| | name | X | X | X | Disk Name | | ||
| | vendor | X | X | X | vendor/producer | | ||
| | firmwareRevision | X | X | X | firmware revision | | ||
| | serialNum | X | X | X | serial number | | ||
| | interfaceType | | X | X | | | ||
| | size | X | X | X | size in bytes | | ||
| | totalCylinders | | X | X | total cylinders | | ||
| | totalHeads | | X | X | total heads | | ||
| | totalTracks | | X | X | total tracks | | ||
| | tracksPerCylinder | | X | X | tracks per cylinder | | ||
| | sectorsPerTrack | | X | X | sectors per track | | ||
| | totalSectors | | X | X | total sectors | | ||
| | bytesPerSector | | X | X | bytes per sector | | ||
| si.battery(cb) | {...} | X | X | X | battery information | | ||
@@ -273,7 +298,7 @@ | | hasbattery | X | X | X | indicates presence of battery | | ||
| | [0].state | X | X | | like ESTABLISHED, TIME_WAIT, ... | | ||
| si.inetChecksite(url, cb) | {...} | X | X | | response-time (ms) to fetch given URL | | ||
| | url | X | X | | given url | | ||
| | ok | X | X | | status code OK (2xx, 3xx) | | ||
| | status | X | X | | status code | | ||
| | ms | X | X | | response time in ms | | ||
| si.inetChecksite(url, cb) | {...} | X | X | X | response-time (ms) to fetch given URL | | ||
| | url | X | X | X | given url | | ||
| | ok | X | X | X | status code OK (2xx, 3xx) | | ||
| | status | X | X | X | status code | | ||
| | ms | X | X | X | response time in ms | | ||
| si.inetLatency(host, cb) | : number | X | X | X | response-time (ms) to external resource<br>host parameter is optional (default 8.8.8.8)| | ||
@@ -280,0 +305,0 @@ |
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
204679
4327
566
16