added graphics info (controller and display)
This commit is contained in:
parent
705ec26e98
commit
1db7161687
18
README.md
18
README.md
@ -42,6 +42,7 @@ si.cpu()
|
||||
|
||||
### Latest Activity
|
||||
|
||||
- Version 3.5.0: added graphics info (controller and display).
|
||||
- Version 3.4.0: rewritten currentLoad and CPU load for processes (linux). This is now much more accurate.
|
||||
- Version 3.3.0: added process list. Get full process list including details like cpu and mem usage, status, command, ...
|
||||
- Version 3.2.0: added battery support. If a battery is installed, you get information about status and current capacity level
|
||||
@ -68,6 +69,7 @@ Here all changes more detailed:
|
||||
|
||||
New Functions
|
||||
|
||||
- `graphics`: returns arrays of graphics controllers and displays (new in version 3.5)
|
||||
- `networkInterfaceDefault`: returns default network interface (new in version 3.4)
|
||||
- `processes`: now returns also a process list with all process details (new in version 3.3)
|
||||
- `battery`: retrieves battery status and charging level (new in version 3.2)
|
||||
@ -215,6 +217,21 @@ This library is splitted in several sections:
|
||||
| - maxcapacity | X | X | max capacity of battery |
|
||||
| - currentcapacity | X | X | current capacity of battery |
|
||||
| - percent | X | X | charging level in percent |
|
||||
| si.graphics(cb) | X | X | arrays of graphics controllers and displays |
|
||||
| - controllers[0].model | X | X | graphics controller model |
|
||||
| - controllers[0].vendor | X | X | e.g. ATI |
|
||||
| - controllers[0].bus | X | X | on which bus (e.g. PCIe) |
|
||||
| - controllers[0].vram | X | X | VRAM size (in MB) |
|
||||
| - controllers[0].vramDynamic | X | X | true if dynamicly allocated ram |
|
||||
| - displays[0].model | X | X | Monitor/Display Model |
|
||||
| - displays[0].main | X | X | true if main monitor |
|
||||
| - displays[0].builtin | X | X | true if built in monitor |
|
||||
| - displays[0].connection | X | X | e.g. DisplayPort or HDMI |
|
||||
| - displays[0].resolutionx | X | X | pixel horizontal |
|
||||
| - displays[0].resolutiony | X | X | pixel vertical |
|
||||
| - displays[0].depth | X | X | color depth in bits |
|
||||
| - displays[0].sizex | X | X | size in mm horizontal |
|
||||
| - displays[0].sizey | X | X | size in mm vertical |
|
||||
| si.fsSize(cb) | X | X | returns array of mounted file systems |
|
||||
| - [0].fs | X | X | name of file system |
|
||||
| - [0].size | X | X | sizes in Bytes |
|
||||
@ -377,6 +394,7 @@ I am happy to discuss any comments and suggestions. Please feel free to contact
|
||||
|
||||
| Version | Date | Comment |
|
||||
| -------------- | -------------- | -------- |
|
||||
| 3.5.0 | 2016-09-14 | added graphics info (controller, display) |
|
||||
| 3.4.4 | 2016-09-02 | tiny fixes system.model, getDefaultNetworkInterface |
|
||||
| 3.4.3 | 2016-09-02 | tiny bug fix fsStats, disksIO OSX |
|
||||
| 3.4.2 | 2016-09-01 | improved default network interface |
|
||||
|
||||
328
lib/index.js
328
lib/index.js
@ -23,13 +23,14 @@
|
||||
// 4. CPU
|
||||
// 5. Memory
|
||||
// 6. Battery
|
||||
// 7. File System
|
||||
// 8. Network
|
||||
// 9. Processes
|
||||
// 10. Users/Sessions
|
||||
// 11. Internet
|
||||
// 12. Docker
|
||||
// 13. GetAll - get all data
|
||||
// 7. Graphics
|
||||
// 8. File System
|
||||
// 9. Network
|
||||
// 10. Processes
|
||||
// 11. Users/Sessions
|
||||
// 12. Internet
|
||||
// 13. Docker
|
||||
// 14. GetAll - get all data
|
||||
//
|
||||
// ==================================================================================
|
||||
//
|
||||
@ -80,6 +81,7 @@
|
||||
// --------------------------------
|
||||
//
|
||||
// version date comment
|
||||
// 3.5.0 2016-09-14 added graphics info (controller, display)
|
||||
// 3.4.4 2016-09-02 tiny fixes system.model, getDefaultNetworkInterface
|
||||
// 3.4.3 2016-09-02 tiny bug fix fsStats, disksIO OSX
|
||||
// 3.4.2 2016-09-01 improved default network interface
|
||||
@ -908,7 +910,294 @@ function battery(callback) {
|
||||
exports.battery = battery;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 7. File System
|
||||
// 7. Graphics (controller, display)
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
function graphics(callback) {
|
||||
|
||||
function parseLinesDarwin(lines) {
|
||||
let starts = [];
|
||||
let level = -1;
|
||||
let lastlevel = -1;
|
||||
let controllers = [];
|
||||
let displays = [];
|
||||
let currentController = {};
|
||||
let currentDisplay = {};
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if ('' != lines[i].trim()) {
|
||||
let start = lines[i].search(/\S|$/);
|
||||
if (-1 == starts.indexOf(start)) {
|
||||
starts.push(start);
|
||||
}
|
||||
level = starts.indexOf(start);
|
||||
if (level < lastlevel) {
|
||||
if (Object.keys(currentController).length > 0) {// just changed to Displays
|
||||
controllers.push(currentController);
|
||||
currentController = {};
|
||||
}
|
||||
if (Object.keys(currentDisplay).length > 0) {// just changed to Displays
|
||||
displays.push(currentDisplay);
|
||||
currentDisplay = {};
|
||||
}
|
||||
}
|
||||
lastlevel = level;
|
||||
let parts = lines[i].split(':');
|
||||
if (2 == level) { // grafics controller level
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('chipsetmodel') != -1) currentController.model = parts[1].trim();
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('bus') != -1) currentController.bus = parts[1].trim();
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('vendor') != -1) currentController.vendor = parts[1].split('(')[0].trim();
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('vram(total)') != -1) {
|
||||
currentController.vram = parseInt(parts[1]); // in MB
|
||||
currentController.vramDynamic = false;
|
||||
}
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('vram(dynamic,max)') != -1) {
|
||||
currentController.vram = parseInt(parts[1]); // in MB
|
||||
currentController.vramDynamic = true;
|
||||
}
|
||||
}
|
||||
if (3 == level) { // display controller level
|
||||
if (parts.length > 1 && '' == parts[1]) {
|
||||
currentDisplay.model = parts[0].trim();
|
||||
currentDisplay.main = false;
|
||||
currentDisplay.builtin = false;
|
||||
currentDisplay.connection = '';
|
||||
currentDisplay.sizex = -1;
|
||||
currentDisplay.sizey = -1;
|
||||
}
|
||||
}
|
||||
if (4 == level) { // display controller details level
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('resolution') != -1) {
|
||||
let resolution = parts[1].split('x');
|
||||
currentDisplay.resolutionx = (resolution.length > 1 ? parseInt(resolution[0]) : 0);
|
||||
currentDisplay.resolutiony = (resolution.length > 1 ? parseInt(resolution[1]) : 0);
|
||||
}
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('pixeldepth') != -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.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 (Object.keys(currentController).length > 0) {// just changed to Displays
|
||||
controllers.push(currentController);
|
||||
}
|
||||
if (Object.keys(currentDisplay).length > 0) {// just changed to Displays
|
||||
displays.push(currentDisplay);
|
||||
}
|
||||
return ({
|
||||
controllers: controllers,
|
||||
displays: displays
|
||||
})
|
||||
}
|
||||
|
||||
function parseLinesLinuxControllers(lines) {
|
||||
let controllers = [];
|
||||
let currentController = {};
|
||||
let is_vga = false;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if ('' != lines[i].trim()) {
|
||||
if (' ' != lines[i][0] && '\t' != lines[i][0]) { // first line of new entry
|
||||
let vgapos = lines[i].toLowerCase().indexOf('vga');
|
||||
if (vgapos != -1) { // VGA
|
||||
if (Object.keys(currentController).length > 0) {// already a controller found
|
||||
controllers.push(currentController);
|
||||
currentController = {};
|
||||
}
|
||||
is_vga = true;
|
||||
let endpos = lines[i].search(/\[[0-9a-f]{4}:[0-9a-f]{4}]|$/);
|
||||
let parts = lines[i].substr(vgapos, endpos - vgapos).split(':');
|
||||
if (parts.length > 1)
|
||||
{
|
||||
parts[1] = parts[1].trim();
|
||||
if (parts[1].toLowerCase().indexOf('corporation')) {
|
||||
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf('corporation') + 11).trim();
|
||||
currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf('corporation') + 11, 200).trim().split('(')[0];
|
||||
currentController.bus = '';
|
||||
currentController.vram = -1;
|
||||
currentController.vramDynamic = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
is_vga = false;
|
||||
}
|
||||
}
|
||||
if (is_vga) { // within VGA details
|
||||
let parts = lines[i].split(':');
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('devicename') != -1 && parts[0].toLowerCase().indexOf('onboard') != -1) currentController.bus = 'Onboard';
|
||||
if (parts.length > 1 && parts[0].replace(/ +/g, "").toLowerCase().indexOf('region') != -1 && parts[1].toLowerCase().indexOf('memory') != -1) {
|
||||
let memparts = parts[1].split("=");
|
||||
if (memparts.length > 1) {
|
||||
currentController.vram = parseInt(memparts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(currentController).length > 0) {// still controller information available
|
||||
controllers.push(currentController);
|
||||
}
|
||||
return (controllers)
|
||||
}
|
||||
|
||||
function parseLinesLinuxEdid(edid) {
|
||||
// parsen EDID
|
||||
// --> model
|
||||
// --> resolutionx
|
||||
// --> resolutiony
|
||||
// --> builtin = false
|
||||
// --> pixeldepth (?)
|
||||
// --> sizex
|
||||
// --> sizey
|
||||
let result = {};
|
||||
// find first "Detailed Timing Description"
|
||||
let start = 108;
|
||||
if (edid.substr(start,6) == '000000') {
|
||||
start += 36;
|
||||
}
|
||||
if (edid.substr(start,6) == '000000') {
|
||||
start += 36;
|
||||
}
|
||||
if (edid.substr(start,6) == '000000') {
|
||||
start += 36;
|
||||
}
|
||||
if (edid.substr(start,6) == '000000') {
|
||||
start += 36;
|
||||
}
|
||||
result.resolutionx = parseInt('0x0' + edid.substr(start + 8,1) + edid.substr(start + 4,2));
|
||||
result.resolutiony = parseInt('0x0' + edid.substr(start + 14,1) + edid.substr(start + 10,2));
|
||||
result.sizex = parseInt('0x0' + edid.substr(start + 28,1) + edid.substr(start + 24,2));
|
||||
result.sizey = parseInt('0x0' + edid.substr(start + 29,1) + edid.substr(start + 26,2));
|
||||
// monitor name
|
||||
start = edid.indexOf('000000fc00'); // find first "Monitor Description Data"
|
||||
if (start >= 0) {
|
||||
let model_raw = edid.substr(start+10, 26);
|
||||
if (model_raw.indexOf('0a') != -1) {
|
||||
model_raw = model_raw.substr(0,model_raw.indexOf('0a'))
|
||||
}
|
||||
result.model = model_raw.match(/.{1,2}/g).map(function(v){
|
||||
return String.fromCharCode(parseInt(v, 16));
|
||||
}).join('');
|
||||
} else {
|
||||
result.model = '';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseLinesLinuxDisplays(lines, depth) {
|
||||
let displays = [];
|
||||
let currentDisplay = {};
|
||||
let is_edid = false;
|
||||
let edid_raw = '';
|
||||
let start = 0;
|
||||
for (let i = 1; i < lines.length; i++) { // start with second line
|
||||
if ('' != lines[i].trim()) {
|
||||
if (' ' != lines[i][0] && '\t' != lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') != -1 ) { // first line of new entry
|
||||
if (Object.keys(currentDisplay).length > 0) { // push last display to array
|
||||
displays.push(currentDisplay);
|
||||
currentDisplay = {};
|
||||
}
|
||||
let parts = lines[i].split(' ');
|
||||
currentDisplay.connection = parts[0];
|
||||
currentDisplay.main = (parts[2] == 'primary');
|
||||
currentDisplay.builtin = (parts[0].toLowerCase().indexOf('edp') >= 0)
|
||||
}
|
||||
|
||||
// try to read EDID information
|
||||
if (is_edid) {
|
||||
if (lines[i].search(/\S|$/) > start) {
|
||||
edid_raw += lines[i].toLowerCase().trim();
|
||||
} else {
|
||||
// parsen EDID
|
||||
let edid_decoded = parseLinesLinuxEdid(edid_raw);
|
||||
currentDisplay.model = edid_decoded.model;
|
||||
currentDisplay.resolutionx = edid_decoded.resolutionx;
|
||||
currentDisplay.resolutiony = edid_decoded.resolutiony;
|
||||
currentDisplay.sizex = edid_decoded.sizex;
|
||||
currentDisplay.sizey = edid_decoded.sizey;
|
||||
currentDisplay.pixeldepth = depth;
|
||||
is_edid = false;
|
||||
}
|
||||
}
|
||||
if (lines[i].toLowerCase().indexOf('edid:') != -1 ) {
|
||||
is_edid = true;
|
||||
start = lines[i].search(/\S|$/);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pushen displays
|
||||
if (Object.keys(currentDisplay).length > 0) { // still information there
|
||||
displays.push(currentDisplay);
|
||||
}
|
||||
return displays
|
||||
}
|
||||
|
||||
// function starts here
|
||||
return new Promise((resolve, reject) => {
|
||||
process.nextTick(() => {
|
||||
if (_windows) {
|
||||
let error = new Error(NOT_SUPPORTED);
|
||||
if (callback) {
|
||||
callback(NOT_SUPPORTED)
|
||||
}
|
||||
reject(error);
|
||||
}
|
||||
let result = {};
|
||||
if (_darwin) {
|
||||
let cmd = 'system_profiler SPDisplaysDataType';
|
||||
exec(cmd, function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result = parseLinesDarwin(lines);
|
||||
}
|
||||
if (callback) {
|
||||
callback(result)
|
||||
}
|
||||
resolve(result);
|
||||
})
|
||||
}
|
||||
if (_linux) {
|
||||
let cmd = 'lspci -vvv 2>/dev/null';
|
||||
exec(cmd, function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result.controllers = parseLinesLinuxControllers(lines);
|
||||
let cmd = "xdpyinfo 2>/dev/null | grep 'depth of root window' | awk '{ print $5 }'";
|
||||
exec(cmd, function (error, stdout) {
|
||||
let depth = 0;
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
depth = parseInt(lines[0]) || 0;
|
||||
}
|
||||
let cmd = 'xrandr --verbose 2>/dev/null';
|
||||
exec(cmd, function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result.displays = parseLinesLinuxDisplays(lines, depth);
|
||||
}
|
||||
if (callback) {
|
||||
callback(result)
|
||||
}
|
||||
resolve(result);
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.graphics = graphics;
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 8. File System
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------
|
||||
@ -1166,7 +1455,7 @@ function disksIO(callback) {
|
||||
exports.disksIO = disksIO;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 8. Network
|
||||
// 9. Network
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
function getDefaultNetworkInterface() {
|
||||
@ -1528,7 +1817,7 @@ function networkConnections(callback) {
|
||||
exports.networkConnections = networkConnections;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 9. Processes
|
||||
// 10. Processes
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------
|
||||
@ -2057,7 +2346,7 @@ function processLoad(proc, callback) {
|
||||
exports.processLoad = processLoad;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 10. Users/Sessions
|
||||
// 11. Users/Sessions
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------
|
||||
@ -2240,7 +2529,7 @@ function users(callback) {
|
||||
exports.users = users;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 11. Internet
|
||||
// 12. Internet
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------
|
||||
@ -2329,7 +2618,7 @@ function inetLatency(host, callback) {
|
||||
exports.inetLatency = inetLatency;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 12. Docker
|
||||
// 13. Docker
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------
|
||||
@ -2615,7 +2904,7 @@ function dockerAll(callback) {
|
||||
exports.dockerAll = dockerAll;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// 13. get all
|
||||
// 14. get all
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------
|
||||
@ -2641,10 +2930,13 @@ function getStaticData(callback) {
|
||||
data.os = res;
|
||||
cpu().then(res => {
|
||||
data.cpu = res;
|
||||
networkInterfaces().then(res => {
|
||||
data.net = res;
|
||||
if (callback) { callback(data) }
|
||||
resolve(data);
|
||||
graphics().then(res => {
|
||||
data.graphics = res;
|
||||
networkInterfaces().then(res => {
|
||||
data.net = res;
|
||||
if (callback) { callback(data) }
|
||||
resolve(data);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -30,7 +30,11 @@
|
||||
"users",
|
||||
"internet",
|
||||
"battery",
|
||||
"docker"
|
||||
"docker",
|
||||
"graphics",
|
||||
"graphic card",
|
||||
"graphic controller",
|
||||
"display"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user