fix GPU getNvidiaSmi directory tracing
This commit is contained in:
parent
2677324976
commit
1a9f434335
597
lib/graphics.js
597
lib/graphics.js
@ -21,13 +21,13 @@ const util = require('./util');
|
|||||||
let _platform = process.platform;
|
let _platform = process.platform;
|
||||||
let _nvidiaSmiPath = '';
|
let _nvidiaSmiPath = '';
|
||||||
|
|
||||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
const _linux = _platform === 'linux' || _platform === 'android';
|
||||||
const _darwin = (_platform === 'darwin');
|
const _darwin = _platform === 'darwin';
|
||||||
const _windows = (_platform === 'win32');
|
const _windows = _platform === 'win32';
|
||||||
const _freebsd = (_platform === 'freebsd');
|
const _freebsd = _platform === 'freebsd';
|
||||||
const _openbsd = (_platform === 'openbsd');
|
const _openbsd = _platform === 'openbsd';
|
||||||
const _netbsd = (_platform === 'netbsd');
|
const _netbsd = _platform === 'netbsd';
|
||||||
const _sunos = (_platform === 'sunos');
|
const _sunos = _platform === 'sunos';
|
||||||
|
|
||||||
let _resolutionX = 0;
|
let _resolutionX = 0;
|
||||||
let _resolutionY = 0;
|
let _resolutionY = 0;
|
||||||
@ -37,22 +37,22 @@ let _refreshRate = 0;
|
|||||||
const videoTypes = {
|
const videoTypes = {
|
||||||
'-2': 'UNINITIALIZED',
|
'-2': 'UNINITIALIZED',
|
||||||
'-1': 'OTHER',
|
'-1': 'OTHER',
|
||||||
'0': 'HD15',
|
0: 'HD15',
|
||||||
'1': 'SVIDEO',
|
1: 'SVIDEO',
|
||||||
'2': 'Composite video',
|
2: 'Composite video',
|
||||||
'3': 'Component video',
|
3: 'Component video',
|
||||||
'4': 'DVI',
|
4: 'DVI',
|
||||||
'5': 'HDMI',
|
5: 'HDMI',
|
||||||
'6': 'LVDS',
|
6: 'LVDS',
|
||||||
'8': 'D_JPN',
|
8: 'D_JPN',
|
||||||
'9': 'SDI',
|
9: 'SDI',
|
||||||
'10': 'DP',
|
10: 'DP',
|
||||||
'11': 'DP embedded',
|
11: 'DP embedded',
|
||||||
'12': 'UDI',
|
12: 'UDI',
|
||||||
'13': 'UDI embedded',
|
13: 'UDI embedded',
|
||||||
'14': 'SDTVDONGLE',
|
14: 'SDTVDONGLE',
|
||||||
'15': 'MIRACAST',
|
15: 'MIRACAST',
|
||||||
'2147483648': 'INTERNAL'
|
2147483648: 'INTERNAL'
|
||||||
};
|
};
|
||||||
|
|
||||||
function getVendorFromModel(model) {
|
function getVendorFromModel(model) {
|
||||||
@ -77,7 +77,7 @@ function getVendorFromModel(model) {
|
|||||||
{ pattern: 'APPLE.?', manufacturer: 'Apple' },
|
{ pattern: 'APPLE.?', manufacturer: 'Apple' },
|
||||||
{ pattern: 'INTEL.?', manufacturer: 'Intel' },
|
{ pattern: 'INTEL.?', manufacturer: 'Intel' },
|
||||||
{ pattern: 'AMD.?', manufacturer: 'AMD' },
|
{ pattern: 'AMD.?', manufacturer: 'AMD' },
|
||||||
{ pattern: 'NVIDIA.?', manufacturer: 'NVDIA' },
|
{ pattern: 'NVIDIA.?', manufacturer: 'NVDIA' }
|
||||||
];
|
];
|
||||||
|
|
||||||
let result = '';
|
let result = '';
|
||||||
@ -85,7 +85,9 @@ function getVendorFromModel(model) {
|
|||||||
model = model.toUpperCase();
|
model = model.toUpperCase();
|
||||||
manufacturers.forEach((manufacturer) => {
|
manufacturers.forEach((manufacturer) => {
|
||||||
const re = RegExp(manufacturer.pattern);
|
const re = RegExp(manufacturer.pattern);
|
||||||
if (re.test(model)) { result = manufacturer.manufacturer; }
|
if (re.test(model)) {
|
||||||
|
result = manufacturer.manufacturer;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -93,11 +95,11 @@ function getVendorFromModel(model) {
|
|||||||
|
|
||||||
function getVendorFromId(id) {
|
function getVendorFromId(id) {
|
||||||
const vendors = {
|
const vendors = {
|
||||||
'610': 'Apple',
|
610: 'Apple',
|
||||||
'1e6d': 'LG',
|
'1e6d': 'LG',
|
||||||
'10ac': 'DELL',
|
'10ac': 'DELL',
|
||||||
'4dd9': 'Sony',
|
'4dd9': 'Sony',
|
||||||
'38a3': 'NEC',
|
'38a3': 'NEC'
|
||||||
};
|
};
|
||||||
return vendors[id] || '';
|
return vendors[id] || '';
|
||||||
}
|
}
|
||||||
@ -105,47 +107,51 @@ function getVendorFromId(id) {
|
|||||||
function vendorToId(str) {
|
function vendorToId(str) {
|
||||||
let result = '';
|
let result = '';
|
||||||
str = (str || '').toLowerCase();
|
str = (str || '').toLowerCase();
|
||||||
if (str.indexOf('apple') >= 0) { result = '0x05ac'; }
|
if (str.indexOf('apple') >= 0) {
|
||||||
else if (str.indexOf('nvidia') >= 0) { result = '0x10de'; }
|
result = '0x05ac';
|
||||||
else if (str.indexOf('intel') >= 0) { result = '0x8086'; }
|
} else if (str.indexOf('nvidia') >= 0) {
|
||||||
else if (str.indexOf('ati') >= 0 || str.indexOf('amd') >= 0) { result = '0x1002'; }
|
result = '0x10de';
|
||||||
|
} else if (str.indexOf('intel') >= 0) {
|
||||||
|
result = '0x8086';
|
||||||
|
} else if (str.indexOf('ati') >= 0 || str.indexOf('amd') >= 0) {
|
||||||
|
result = '0x1002';
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMetalVersion(id) {
|
function getMetalVersion(id) {
|
||||||
const families = {
|
const families = {
|
||||||
'spdisplays_mtlgpufamilymac1': 'mac1',
|
spdisplays_mtlgpufamilymac1: 'mac1',
|
||||||
'spdisplays_mtlgpufamilymac2': 'mac2',
|
spdisplays_mtlgpufamilymac2: 'mac2',
|
||||||
'spdisplays_mtlgpufamilyapple1': 'apple1',
|
spdisplays_mtlgpufamilyapple1: 'apple1',
|
||||||
'spdisplays_mtlgpufamilyapple2': 'apple2',
|
spdisplays_mtlgpufamilyapple2: 'apple2',
|
||||||
'spdisplays_mtlgpufamilyapple3': 'apple3',
|
spdisplays_mtlgpufamilyapple3: 'apple3',
|
||||||
'spdisplays_mtlgpufamilyapple4': 'apple4',
|
spdisplays_mtlgpufamilyapple4: 'apple4',
|
||||||
'spdisplays_mtlgpufamilyapple5': 'apple5',
|
spdisplays_mtlgpufamilyapple5: 'apple5',
|
||||||
'spdisplays_mtlgpufamilyapple6': 'apple6',
|
spdisplays_mtlgpufamilyapple6: 'apple6',
|
||||||
'spdisplays_mtlgpufamilyapple7': 'apple7',
|
spdisplays_mtlgpufamilyapple7: 'apple7',
|
||||||
'spdisplays_metalfeaturesetfamily11': 'family1_v1',
|
spdisplays_metalfeaturesetfamily11: 'family1_v1',
|
||||||
'spdisplays_metalfeaturesetfamily12': 'family1_v2',
|
spdisplays_metalfeaturesetfamily12: 'family1_v2',
|
||||||
'spdisplays_metalfeaturesetfamily13': 'family1_v3',
|
spdisplays_metalfeaturesetfamily13: 'family1_v3',
|
||||||
'spdisplays_metalfeaturesetfamily14': 'family1_v4',
|
spdisplays_metalfeaturesetfamily14: 'family1_v4',
|
||||||
'spdisplays_metalfeaturesetfamily21': 'family2_v1'
|
spdisplays_metalfeaturesetfamily21: 'family2_v1'
|
||||||
};
|
};
|
||||||
return families[id] || '';
|
return families[id] || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function graphics(callback) {
|
function graphics(callback) {
|
||||||
|
|
||||||
function parseLinesDarwin(graphicsArr) {
|
function parseLinesDarwin(graphicsArr) {
|
||||||
const res = {
|
const res = {
|
||||||
controllers: [],
|
controllers: [],
|
||||||
displays: []
|
displays: []
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
graphicsArr.forEach(function (item) {
|
graphicsArr.forEach( (item) => {
|
||||||
// controllers
|
// controllers
|
||||||
const bus = ((item.sppci_bus || '').indexOf('builtin') > -1 ? 'Built-In' : ((item.sppci_bus || '').indexOf('pcie') > -1 ? 'PCIe' : ''));
|
const bus = (item.sppci_bus || '').indexOf('builtin') > -1 ? 'Built-In' : (item.sppci_bus || '').indexOf('pcie') > -1 ? 'PCIe' : '';
|
||||||
const vram = (parseInt((item.spdisplays_vram || ''), 10) || 0) * (((item.spdisplays_vram || '').indexOf('GB') > -1) ? 1024 : 1);
|
const vram = (parseInt(item.spdisplays_vram || '', 10) || 0) * ((item.spdisplays_vram || '').indexOf('GB') > -1 ? 1024 : 1);
|
||||||
const vramDyn = (parseInt((item.spdisplays_vram_shared || ''), 10) || 0) * (((item.spdisplays_vram_shared || '').indexOf('GB') > -1) ? 1024 : 1);
|
const vramDyn = (parseInt(item.spdisplays_vram_shared || '', 10) || 0) * ((item.spdisplays_vram_shared || '').indexOf('GB') > -1 ? 1024 : 1);
|
||||||
let metalVersion = getMetalVersion(item.spdisplays_metal || item.spdisplays_metalfamily || '');
|
let metalVersion = getMetalVersion(item.spdisplays_metal || item.spdisplays_metalfamily || '');
|
||||||
res.controllers.push({
|
res.controllers.push({
|
||||||
vendor: getVendorFromModel(item.spdisplays_vendor || '') || item.spdisplays_vendor || '',
|
vendor: getVendorFromModel(item.spdisplays_vendor || '') || item.spdisplays_vendor || '',
|
||||||
@ -155,14 +161,14 @@ function graphics(callback) {
|
|||||||
vram: vram || vramDyn || null,
|
vram: vram || vramDyn || null,
|
||||||
deviceId: item['spdisplays_device-id'] || '',
|
deviceId: item['spdisplays_device-id'] || '',
|
||||||
vendorId: item['spdisplays_vendor-id'] || vendorToId((item['spdisplays_vendor'] || '') + (item.sppci_model || '')),
|
vendorId: item['spdisplays_vendor-id'] || vendorToId((item['spdisplays_vendor'] || '') + (item.sppci_model || '')),
|
||||||
external: (item.sppci_device_type === 'spdisplays_egpu'),
|
external: item.sppci_device_type === 'spdisplays_egpu',
|
||||||
cores: item['sppci_cores'] || null,
|
cores: item['sppci_cores'] || null,
|
||||||
metalVersion
|
metalVersion
|
||||||
});
|
});
|
||||||
|
|
||||||
// displays
|
// displays
|
||||||
if (item.spdisplays_ndrvs && item.spdisplays_ndrvs.length) {
|
if (item.spdisplays_ndrvs && item.spdisplays_ndrvs.length) {
|
||||||
item.spdisplays_ndrvs.forEach(function (displayItem) {
|
item.spdisplays_ndrvs.forEach( (displayItem) => {
|
||||||
const connectionType = displayItem['spdisplays_connection_type'] || '';
|
const connectionType = displayItem['spdisplays_connection_type'] || '';
|
||||||
const currentResolutionParts = (displayItem['_spdisplays_resolution'] || '').split('@');
|
const currentResolutionParts = (displayItem['_spdisplays_resolution'] || '').split('@');
|
||||||
const currentResolution = currentResolutionParts[0].split('x');
|
const currentResolution = currentResolutionParts[0].split('x');
|
||||||
@ -178,18 +184,17 @@ function graphics(callback) {
|
|||||||
displayId: displayItem['_spdisplays_displayID'] || null,
|
displayId: displayItem['_spdisplays_displayID'] || null,
|
||||||
main: displayItem['spdisplays_main'] ? displayItem['spdisplays_main'] === 'spdisplays_yes' : false,
|
main: displayItem['spdisplays_main'] ? displayItem['spdisplays_main'] === 'spdisplays_yes' : false,
|
||||||
builtin: (displayItem['spdisplays_display_type'] || '').indexOf('built-in') > -1,
|
builtin: (displayItem['spdisplays_display_type'] || '').indexOf('built-in') > -1,
|
||||||
connection: ((connectionType.indexOf('_internal') > -1) ? 'Internal' : ((connectionType.indexOf('_displayport') > -1) ? 'Display Port' : ((connectionType.indexOf('_hdmi') > -1) ? 'HDMI' : null))),
|
connection: connectionType.indexOf('_internal') > -1 ? 'Internal' : connectionType.indexOf('_displayport') > -1 ? 'Display Port' : connectionType.indexOf('_hdmi') > -1 ? 'HDMI' : null,
|
||||||
sizeX: null,
|
sizeX: null,
|
||||||
sizeY: null,
|
sizeY: null,
|
||||||
pixelDepth: (pixelDepthString === 'CGSThirtyBitColor' ? 30 : (pixelDepthString === 'CGSThirtytwoBitColor' ? 32 : (pixelDepthString === 'CGSTwentyfourBitColor' ? 24 : null))),
|
pixelDepth: pixelDepthString === 'CGSThirtyBitColor' ? 30 : pixelDepthString === 'CGSThirtytwoBitColor' ? 32 : pixelDepthString === 'CGSTwentyfourBitColor' ? 24 : null,
|
||||||
resolutionX: pixelParts.length > 1 ? parseInt(pixelParts[0], 10) : null,
|
resolutionX: pixelParts.length > 1 ? parseInt(pixelParts[0], 10) : null,
|
||||||
resolutionY: pixelParts.length > 1 ? parseInt(pixelParts[1], 10) : null,
|
resolutionY: pixelParts.length > 1 ? parseInt(pixelParts[1], 10) : null,
|
||||||
currentResX: currentResolution.length > 1 ? parseInt(currentResolution[0], 10) : null,
|
currentResX: currentResolution.length > 1 ? parseInt(currentResolution[0], 10) : null,
|
||||||
currentResY: currentResolution.length > 1 ? parseInt(currentResolution[1], 10) : null,
|
currentResY: currentResolution.length > 1 ? parseInt(currentResolution[1], 10) : null,
|
||||||
positionX: 0,
|
positionX: 0,
|
||||||
positionY: 0,
|
positionY: 0,
|
||||||
currentRefreshRate: currentResolutionParts.length > 1 ? parseInt(currentResolutionParts[1], 10) : null,
|
currentRefreshRate: currentResolutionParts.length > 1 ? parseInt(currentResolutionParts[1], 10) : null
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -229,22 +234,26 @@ function graphics(callback) {
|
|||||||
let i = 1;
|
let i = 1;
|
||||||
lines.forEach((line) => {
|
lines.forEach((line) => {
|
||||||
let subsystem = '';
|
let subsystem = '';
|
||||||
if (i < lines.length && lines[i]) { // get next line;
|
if (i < lines.length && lines[i]) {
|
||||||
|
// get next line;
|
||||||
subsystem = lines[i];
|
subsystem = lines[i];
|
||||||
if (subsystem.indexOf(':') > 0) {
|
if (subsystem.indexOf(':') > 0) {
|
||||||
subsystem = subsystem.split(':')[1];
|
subsystem = subsystem.split(':')[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ('' !== line.trim()) {
|
if ('' !== line.trim()) {
|
||||||
if (' ' !== line[0] && '\t' !== line[0]) { // first line of new entry
|
if (' ' !== line[0] && '\t' !== line[0]) {
|
||||||
let isExternal = (pciIDs.indexOf(line.split(' ')[0]) >= 0);
|
// first line of new entry
|
||||||
|
let isExternal = pciIDs.indexOf(line.split(' ')[0]) >= 0;
|
||||||
let vgapos = line.toLowerCase().indexOf(' vga ');
|
let vgapos = line.toLowerCase().indexOf(' vga ');
|
||||||
let _3dcontrollerpos = line.toLowerCase().indexOf('3d controller');
|
let _3dcontrollerpos = line.toLowerCase().indexOf('3d controller');
|
||||||
if (vgapos !== -1 || _3dcontrollerpos !== -1) { // VGA
|
if (vgapos !== -1 || _3dcontrollerpos !== -1) {
|
||||||
|
// VGA
|
||||||
if (_3dcontrollerpos !== -1 && vgapos === -1) {
|
if (_3dcontrollerpos !== -1 && vgapos === -1) {
|
||||||
vgapos = _3dcontrollerpos;
|
vgapos = _3dcontrollerpos;
|
||||||
}
|
}
|
||||||
if (currentController.vendor || currentController.model || currentController.bus || currentController.vram !== null || currentController.vramDynamic) { // already a controller found
|
if (currentController.vendor || currentController.model || currentController.bus || currentController.vram !== null || currentController.vramDynamic) {
|
||||||
|
// already a controller found
|
||||||
controllers.push(currentController);
|
controllers.push(currentController);
|
||||||
currentController = {
|
currentController = {
|
||||||
vendor: '',
|
vendor: '',
|
||||||
@ -252,7 +261,7 @@ function graphics(callback) {
|
|||||||
bus: '',
|
bus: '',
|
||||||
busAddress: '',
|
busAddress: '',
|
||||||
vram: null,
|
vram: null,
|
||||||
vramDynamic: false,
|
vramDynamic: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,28 +277,47 @@ function graphics(callback) {
|
|||||||
parts[1] = parts[1].trim();
|
parts[1] = parts[1].trim();
|
||||||
if (parts[1].toLowerCase().indexOf('corporation') >= 0) {
|
if (parts[1].toLowerCase().indexOf('corporation') >= 0) {
|
||||||
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf('corporation') + 11).trim();
|
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).split('(')[0].trim();
|
currentController.model = parts[1]
|
||||||
currentController.bus = (pciIDs.length > 0 && isExternal) ? 'PCIe' : 'Onboard';
|
.substr(parts[1].toLowerCase().indexOf('corporation') + 11, 200)
|
||||||
|
.split('(')[0]
|
||||||
|
.trim();
|
||||||
|
currentController.bus = pciIDs.length > 0 && isExternal ? 'PCIe' : 'Onboard';
|
||||||
currentController.vram = null;
|
currentController.vram = null;
|
||||||
currentController.vramDynamic = false;
|
currentController.vramDynamic = false;
|
||||||
} else if (parts[1].toLowerCase().indexOf(' inc.') >= 0) {
|
} else if (parts[1].toLowerCase().indexOf(' inc.') >= 0) {
|
||||||
if ((parts[1].match(/]/g) || []).length > 1) {
|
if ((parts[1].match(/]/g) || []).length > 1) {
|
||||||
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
|
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
|
||||||
currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(']') + 1, 200).trim().split('(')[0].trim();
|
currentController.model = parts[1]
|
||||||
|
.substr(parts[1].toLowerCase().indexOf(']') + 1, 200)
|
||||||
|
.trim()
|
||||||
|
.split('(')[0]
|
||||||
|
.trim();
|
||||||
} else {
|
} else {
|
||||||
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' inc.') + 5).trim();
|
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' inc.') + 5).trim();
|
||||||
currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(' inc.') + 5, 200).trim().split('(')[0].trim();
|
currentController.model = parts[1]
|
||||||
|
.substr(parts[1].toLowerCase().indexOf(' inc.') + 5, 200)
|
||||||
|
.trim()
|
||||||
|
.split('(')[0]
|
||||||
|
.trim();
|
||||||
}
|
}
|
||||||
currentController.bus = (pciIDs.length > 0 && isExternal) ? 'PCIe' : 'Onboard';
|
currentController.bus = pciIDs.length > 0 && isExternal ? 'PCIe' : 'Onboard';
|
||||||
currentController.vram = null;
|
currentController.vram = null;
|
||||||
currentController.vramDynamic = false;
|
currentController.vramDynamic = false;
|
||||||
} else if (parts[1].toLowerCase().indexOf(' ltd.') >= 0) {
|
} else if (parts[1].toLowerCase().indexOf(' ltd.') >= 0) {
|
||||||
if ((parts[1].match(/]/g) || []).length > 1) {
|
if ((parts[1].match(/]/g) || []).length > 1) {
|
||||||
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
|
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
|
||||||
currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(']') + 1, 200).trim().split('(')[0].trim();
|
currentController.model = parts[1]
|
||||||
|
.substr(parts[1].toLowerCase().indexOf(']') + 1, 200)
|
||||||
|
.trim()
|
||||||
|
.split('(')[0]
|
||||||
|
.trim();
|
||||||
} else {
|
} else {
|
||||||
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' ltd.') + 5).trim();
|
currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' ltd.') + 5).trim();
|
||||||
currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(' ltd.') + 5, 200).trim().split('(')[0].trim();
|
currentController.model = parts[1]
|
||||||
|
.substr(parts[1].toLowerCase().indexOf(' ltd.') + 5, 200)
|
||||||
|
.trim()
|
||||||
|
.split('(')[0]
|
||||||
|
.trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentController.model && subsystem.indexOf(currentController.model) !== -1) {
|
if (currentController.model && subsystem.indexOf(currentController.model) !== -1) {
|
||||||
@ -299,14 +327,16 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
isGraphicsController = false;
|
isGraphicsController = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isGraphicsController) { // within VGA details
|
if (isGraphicsController) {
|
||||||
|
// within VGA details
|
||||||
let parts = line.split(':');
|
let parts = line.split(':');
|
||||||
if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('devicename') !== -1 && parts[1].toLowerCase().indexOf('onboard') !== -1) { currentController.bus = 'Onboard'; }
|
if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('devicename') !== -1 && parts[1].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) {
|
if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('region') !== -1 && parts[1].toLowerCase().indexOf('memory') !== -1) {
|
||||||
let memparts = parts[1].split('=');
|
let memparts = parts[1].split('=');
|
||||||
if (memparts.length > 1) {
|
if (memparts.length > 1) {
|
||||||
@ -318,10 +348,11 @@ function graphics(callback) {
|
|||||||
i++;
|
i++;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentController.vendor || currentController.model || currentController.bus || currentController.busAddress || currentController.vram !== null || currentController.vramDynamic) { // already a controller found
|
if (currentController.vendor || currentController.model || currentController.bus || currentController.busAddress || currentController.vram !== null || currentController.vramDynamic) {
|
||||||
|
// already a controller found
|
||||||
controllers.push(currentController);
|
controllers.push(currentController);
|
||||||
}
|
}
|
||||||
return (controllers);
|
return controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseLinesLinuxClinfo(controllers, lines) {
|
function parseLinesLinuxClinfo(controllers, lines) {
|
||||||
@ -356,7 +387,7 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (busAddress) {
|
if (busAddress) {
|
||||||
let controller = controllers.find(controller => controller.busAddress === busAddress);
|
let controller = controllers.find((controller) => controller.busAddress === busAddress);
|
||||||
if (!controller) {
|
if (!controller) {
|
||||||
controller = {
|
controller = {
|
||||||
vendor: '',
|
vendor: '',
|
||||||
@ -391,22 +422,27 @@ function graphics(callback) {
|
|||||||
|
|
||||||
if (_windows) {
|
if (_windows) {
|
||||||
try {
|
try {
|
||||||
const basePath = util.WINDIR + '\\System32\\DriverStore\\FileRepository';
|
const basePath = util.WINDIR + String.raw`\System32\DriverStore\FileRepository`;
|
||||||
// find all directories that have an nvidia-smi.exe file
|
// find all directories that have an nvidia-smi.exe file
|
||||||
const candidateDirs = fs.readdirSync(basePath).filter(dir => {
|
|
||||||
return fs.readdirSync([basePath, dir].join('/')).includes('nvidia-smi.exe');
|
const candidateDirs = fs.readdirSync(basePath).filter((dir) => {
|
||||||
|
if (fs.statSync([basePath, dir].join('/')).isDirectory()) {
|
||||||
|
return fs.readdirSync([basePath, dir].join('/')).includes('nvidia-smi.exe');
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// use the directory with the most recently created nvidia-smi.exe file
|
// use the directory with the most recently created nvidia-smi.exe file
|
||||||
const targetDir = candidateDirs.reduce((prevDir, currentDir) => {
|
const targetDir = candidateDirs.reduce((prevDir, currentDir) => {
|
||||||
const previousNvidiaSmi = fs.statSync([basePath, prevDir, 'nvidia-smi.exe'].join('/'));
|
const previousNvidiaSmi = fs.statSync([basePath, prevDir, 'nvidia-smi.exe'].join('/'));
|
||||||
const currentNvidiaSmi = fs.statSync([basePath, currentDir, 'nvidia-smi.exe'].join('/'));
|
const currentNvidiaSmi = fs.statSync([basePath, currentDir, 'nvidia-smi.exe'].join('/'));
|
||||||
return (previousNvidiaSmi.ctimeMs > currentNvidiaSmi.ctimeMs) ? prevDir : currentDir;
|
return previousNvidiaSmi.ctimeMs > currentNvidiaSmi.ctimeMs ? prevDir : currentDir;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (targetDir) {
|
if (targetDir) {
|
||||||
_nvidiaSmiPath = [basePath, targetDir, 'nvidia-smi.exe'].join('/');
|
_nvidiaSmiPath = [basePath, targetDir, 'nvidia-smi.exe'].join('/');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch {
|
||||||
util.noop();
|
util.noop();
|
||||||
}
|
}
|
||||||
} else if (_linux) {
|
} else if (_linux) {
|
||||||
@ -419,7 +455,8 @@ function graphics(callback) {
|
|||||||
const nvidiaSmiExe = getNvidiaSmi();
|
const nvidiaSmiExe = getNvidiaSmi();
|
||||||
options = options || util.execOptsWin;
|
options = options || util.execOptsWin;
|
||||||
if (nvidiaSmiExe) {
|
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 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' : '');
|
const cmd = nvidiaSmiExe + ' ' + nvidiaSmiOpts + (_linux ? ' 2>/dev/null' : '');
|
||||||
if (_linux) {
|
if (_linux) {
|
||||||
options.stdio = ['pipe', 'pipe', 'ignore'];
|
options.stdio = ['pipe', 'pipe', 'ignore'];
|
||||||
@ -428,7 +465,7 @@ function graphics(callback) {
|
|||||||
const sanitized = util.sanitizeShellString(cmd);
|
const sanitized = util.sanitizeShellString(cmd);
|
||||||
const res = execSync(sanitized, options).toString();
|
const res = execSync(sanitized, options).toString();
|
||||||
return res;
|
return res;
|
||||||
} catch (e) {
|
} catch {
|
||||||
util.noop();
|
util.noop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,7 +473,6 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function nvidiaDevices() {
|
function nvidiaDevices() {
|
||||||
|
|
||||||
function safeParseNumber(value) {
|
function safeParseNumber(value) {
|
||||||
if ([null, undefined].includes(value)) {
|
if ([null, undefined].includes(value)) {
|
||||||
return value;
|
return value;
|
||||||
@ -450,8 +486,8 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const gpus = stdout.split('\n').filter(Boolean);
|
const gpus = stdout.split('\n').filter(Boolean);
|
||||||
let results = gpus.map(gpu => {
|
let results = gpus.map((gpu) => {
|
||||||
const splittedData = gpu.split(', ').map(value => value.includes('N/A') ? undefined : value);
|
const splittedData = gpu.split(', ').map((value) => (value.includes('N/A') ? undefined : value));
|
||||||
if (splittedData.length === 16) {
|
if (splittedData.length === 16) {
|
||||||
return {
|
return {
|
||||||
driverVersion: splittedData[0],
|
driverVersion: splittedData[0],
|
||||||
@ -469,39 +505,69 @@ function graphics(callback) {
|
|||||||
powerDraw: safeParseNumber(splittedData[12]),
|
powerDraw: safeParseNumber(splittedData[12]),
|
||||||
powerLimit: safeParseNumber(splittedData[13]),
|
powerLimit: safeParseNumber(splittedData[13]),
|
||||||
clockCore: safeParseNumber(splittedData[14]),
|
clockCore: safeParseNumber(splittedData[14]),
|
||||||
clockMemory: safeParseNumber(splittedData[15]),
|
clockMemory: safeParseNumber(splittedData[15])
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
results = results.filter((item) => {
|
results = results.filter((item) => {
|
||||||
return ('pciBus' in item);
|
return 'pciBus' in item;
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeControllerNvidia(controller, nvidia) {
|
function mergeControllerNvidia(controller, nvidia) {
|
||||||
if (nvidia.driverVersion) { controller.driverVersion = nvidia.driverVersion; }
|
if (nvidia.driverVersion) {
|
||||||
if (nvidia.subDeviceId) { controller.subDeviceId = nvidia.subDeviceId; }
|
controller.driverVersion = nvidia.driverVersion;
|
||||||
if (nvidia.name) { controller.name = nvidia.name; }
|
}
|
||||||
if (nvidia.pciBus) { controller.pciBus = nvidia.pciBus; }
|
if (nvidia.subDeviceId) {
|
||||||
if (nvidia.fanSpeed) { controller.fanSpeed = nvidia.fanSpeed; }
|
controller.subDeviceId = nvidia.subDeviceId;
|
||||||
|
}
|
||||||
|
if (nvidia.name) {
|
||||||
|
controller.name = nvidia.name;
|
||||||
|
}
|
||||||
|
if (nvidia.pciBus) {
|
||||||
|
controller.pciBus = nvidia.pciBus;
|
||||||
|
}
|
||||||
|
if (nvidia.fanSpeed) {
|
||||||
|
controller.fanSpeed = nvidia.fanSpeed;
|
||||||
|
}
|
||||||
if (nvidia.memoryTotal) {
|
if (nvidia.memoryTotal) {
|
||||||
controller.memoryTotal = nvidia.memoryTotal;
|
controller.memoryTotal = nvidia.memoryTotal;
|
||||||
controller.vram = nvidia.memoryTotal;
|
controller.vram = nvidia.memoryTotal;
|
||||||
controller.vramDynamic = false;
|
controller.vramDynamic = false;
|
||||||
}
|
}
|
||||||
if (nvidia.memoryUsed) { controller.memoryUsed = nvidia.memoryUsed; }
|
if (nvidia.memoryUsed) {
|
||||||
if (nvidia.memoryFree) { controller.memoryFree = nvidia.memoryFree; }
|
controller.memoryUsed = nvidia.memoryUsed;
|
||||||
if (nvidia.utilizationGpu) { controller.utilizationGpu = nvidia.utilizationGpu; }
|
}
|
||||||
if (nvidia.utilizationMemory) { controller.utilizationMemory = nvidia.utilizationMemory; }
|
if (nvidia.memoryFree) {
|
||||||
if (nvidia.temperatureGpu) { controller.temperatureGpu = nvidia.temperatureGpu; }
|
controller.memoryFree = nvidia.memoryFree;
|
||||||
if (nvidia.temperatureMemory) { controller.temperatureMemory = nvidia.temperatureMemory; }
|
}
|
||||||
if (nvidia.powerDraw) { controller.powerDraw = nvidia.powerDraw; }
|
if (nvidia.utilizationGpu) {
|
||||||
if (nvidia.powerLimit) { controller.powerLimit = nvidia.powerLimit; }
|
controller.utilizationGpu = nvidia.utilizationGpu;
|
||||||
if (nvidia.clockCore) { controller.clockCore = nvidia.clockCore; }
|
}
|
||||||
if (nvidia.clockMemory) { controller.clockMemory = nvidia.clockMemory; }
|
if (nvidia.utilizationMemory) {
|
||||||
|
controller.utilizationMemory = nvidia.utilizationMemory;
|
||||||
|
}
|
||||||
|
if (nvidia.temperatureGpu) {
|
||||||
|
controller.temperatureGpu = nvidia.temperatureGpu;
|
||||||
|
}
|
||||||
|
if (nvidia.temperatureMemory) {
|
||||||
|
controller.temperatureMemory = nvidia.temperatureMemory;
|
||||||
|
}
|
||||||
|
if (nvidia.powerDraw) {
|
||||||
|
controller.powerDraw = nvidia.powerDraw;
|
||||||
|
}
|
||||||
|
if (nvidia.powerLimit) {
|
||||||
|
controller.powerLimit = nvidia.powerLimit;
|
||||||
|
}
|
||||||
|
if (nvidia.clockCore) {
|
||||||
|
controller.clockCore = nvidia.clockCore;
|
||||||
|
}
|
||||||
|
if (nvidia.clockMemory) {
|
||||||
|
controller.clockMemory = nvidia.clockMemory;
|
||||||
|
}
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,7 +580,7 @@ function graphics(callback) {
|
|||||||
// --> pixeldepth (?)
|
// --> pixeldepth (?)
|
||||||
// --> sizex
|
// --> sizex
|
||||||
// --> sizey
|
// --> sizey
|
||||||
let result = {
|
const result = {
|
||||||
vendor: '',
|
vendor: '',
|
||||||
model: '',
|
model: '',
|
||||||
deviceName: '',
|
deviceName: '',
|
||||||
@ -559,11 +625,12 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (model_raw.length > 2) {
|
if (model_raw.length > 2) {
|
||||||
result.model = model_raw.match(/.{1,2}/g).map(function (v) {
|
result.model = model_raw
|
||||||
return String.fromCharCode(parseInt(v, 16));
|
.match(/.{1,2}/g)
|
||||||
}).join('');
|
.map((v) => String.fromCharCode(parseInt(v, 16)))
|
||||||
|
.join('');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch {
|
||||||
util.noop();
|
util.noop();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -573,7 +640,7 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseLinesLinuxDisplays(lines, depth) {
|
function parseLinesLinuxDisplays(lines, depth) {
|
||||||
let displays = [];
|
const displays = [];
|
||||||
let currentDisplay = {
|
let currentDisplay = {
|
||||||
vendor: '',
|
vendor: '',
|
||||||
model: '',
|
model: '',
|
||||||
@ -596,10 +663,21 @@ function graphics(callback) {
|
|||||||
let is_current = false;
|
let is_current = false;
|
||||||
let edid_raw = '';
|
let edid_raw = '';
|
||||||
let start = 0;
|
let start = 0;
|
||||||
for (let i = 1; i < lines.length; i++) { // start with second line
|
for (let i = 1; i < lines.length; i++) {
|
||||||
|
// start with second line
|
||||||
if ('' !== lines[i].trim()) {
|
if ('' !== lines[i].trim()) {
|
||||||
if (' ' !== lines[i][0] && '\t' !== lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') !== -1) { // first line of new entry
|
if (' ' !== lines[i][0] && '\t' !== lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') !== -1) {
|
||||||
if (currentDisplay.model || currentDisplay.main || currentDisplay.builtin || currentDisplay.connection || currentDisplay.sizeX !== null || currentDisplay.pixelDepth !== null || currentDisplay.resolutionX !== null) { // push last display to array
|
// first line of new entry
|
||||||
|
if (
|
||||||
|
currentDisplay.model ||
|
||||||
|
currentDisplay.main ||
|
||||||
|
currentDisplay.builtin ||
|
||||||
|
currentDisplay.connection ||
|
||||||
|
currentDisplay.sizeX !== null ||
|
||||||
|
currentDisplay.pixelDepth !== null ||
|
||||||
|
currentDisplay.resolutionX !== null
|
||||||
|
) {
|
||||||
|
// push last display to array
|
||||||
displays.push(currentDisplay);
|
displays.push(currentDisplay);
|
||||||
currentDisplay = {
|
currentDisplay = {
|
||||||
vendor: '',
|
vendor: '',
|
||||||
@ -622,7 +700,7 @@ function graphics(callback) {
|
|||||||
let parts = lines[i].split(' ');
|
let parts = lines[i].split(' ');
|
||||||
currentDisplay.connection = parts[0];
|
currentDisplay.connection = parts[0];
|
||||||
currentDisplay.main = lines[i].toLowerCase().indexOf(' primary ') >= 0;
|
currentDisplay.main = lines[i].toLowerCase().indexOf(' primary ') >= 0;
|
||||||
currentDisplay.builtin = (parts[0].toLowerCase().indexOf('edp') >= 0);
|
currentDisplay.builtin = parts[0].toLowerCase().indexOf('edp') >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to read EDID information
|
// try to read EDID information
|
||||||
@ -666,7 +744,16 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pushen displays
|
// pushen displays
|
||||||
if (currentDisplay.model || currentDisplay.main || currentDisplay.builtin || currentDisplay.connection || currentDisplay.sizeX !== null || currentDisplay.pixelDepth !== null || currentDisplay.resolutionX !== null) { // still information there
|
if (
|
||||||
|
currentDisplay.model ||
|
||||||
|
currentDisplay.main ||
|
||||||
|
currentDisplay.builtin ||
|
||||||
|
currentDisplay.connection ||
|
||||||
|
currentDisplay.sizeX !== null ||
|
||||||
|
currentDisplay.pixelDepth !== null ||
|
||||||
|
currentDisplay.resolutionX !== null
|
||||||
|
) {
|
||||||
|
// still information there
|
||||||
displays.push(currentDisplay);
|
displays.push(currentDisplay);
|
||||||
}
|
}
|
||||||
return displays;
|
return displays;
|
||||||
@ -680,8 +767,8 @@ function graphics(callback) {
|
|||||||
displays: []
|
displays: []
|
||||||
};
|
};
|
||||||
if (_darwin) {
|
if (_darwin) {
|
||||||
let cmd = 'system_profiler -xml -detailLevel full SPDisplaysDataType';
|
const cmd = 'system_profiler -xml -detailLevel full SPDisplaysDataType';
|
||||||
exec(cmd, function (error, stdout) {
|
exec(cmd, (error, stdout) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
try {
|
try {
|
||||||
const output = stdout.toString();
|
const output = stdout.toString();
|
||||||
@ -690,7 +777,10 @@ function graphics(callback) {
|
|||||||
util.noop();
|
util.noop();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
stdout = execSync('defaults read /Library/Preferences/com.apple.windowserver.plist 2>/dev/null;defaults read /Library/Preferences/com.apple.windowserver.displays.plist 2>/dev/null; echo ""', { maxBuffer: 1024 * 20000 });
|
stdout = execSync(
|
||||||
|
'defaults read /Library/Preferences/com.apple.windowserver.plist 2>/dev/null;defaults read /Library/Preferences/com.apple.windowserver.displays.plist 2>/dev/null; echo ""',
|
||||||
|
{ maxBuffer: 1024 * 20000 }
|
||||||
|
);
|
||||||
const output = (stdout || '').toString();
|
const output = (stdout || '').toString();
|
||||||
const obj = util.plistReader(output);
|
const obj = util.plistReader(output);
|
||||||
if (obj['DisplayAnyUserSets'] && obj['DisplayAnyUserSets']['Configs'] && obj['DisplayAnyUserSets']['Configs'][0] && obj['DisplayAnyUserSets']['Configs'][0]['DisplayConfig']) {
|
if (obj['DisplayAnyUserSets'] && obj['DisplayAnyUserSets']['Configs'] && obj['DisplayAnyUserSets']['Configs'][0] && obj['DisplayAnyUserSets']['Configs'][0]['DisplayConfig']) {
|
||||||
@ -722,7 +812,7 @@ function graphics(callback) {
|
|||||||
i++;
|
i++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch {
|
||||||
util.noop();
|
util.noop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -735,9 +825,9 @@ function graphics(callback) {
|
|||||||
if (_linux) {
|
if (_linux) {
|
||||||
// Raspberry: https://elinux.org/RPI_vcgencmd_usage
|
// Raspberry: https://elinux.org/RPI_vcgencmd_usage
|
||||||
if (util.isRaspberry()) {
|
if (util.isRaspberry()) {
|
||||||
let cmd = 'fbset -s 2> /dev/null | grep \'mode "\' ; vcgencmd get_mem gpu 2> /dev/null; tvservice -s 2> /dev/null; tvservice -n 2> /dev/null;';
|
const cmd = "fbset -s 2> /dev/null | grep 'mode \"' ; vcgencmd get_mem gpu 2> /dev/null; tvservice -s 2> /dev/null; tvservice -n 2> /dev/null;";
|
||||||
exec(cmd, function (error, stdout) {
|
exec(cmd, (error, stdout) => {
|
||||||
let lines = stdout.toString().split('\n');
|
const lines = stdout.toString().split('\n');
|
||||||
if (lines.length > 3 && lines[0].indexOf('mode "') >= -1 && lines[2].indexOf('0x12000a') > -1) {
|
if (lines.length > 3 && lines[0].indexOf('mode "') >= -1 && lines[2].indexOf('0x12000a') > -1) {
|
||||||
const parts = lines[0].replace('mode', '').replace(/"/g, '').trim().split('x');
|
const parts = lines[0].replace('mode', '').replace(/"/g, '').trim().split('x');
|
||||||
if (parts.length === 2) {
|
if (parts.length === 2) {
|
||||||
@ -769,44 +859,41 @@ function graphics(callback) {
|
|||||||
vramDynamic: true
|
vramDynamic: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// if (callback) {
|
|
||||||
// callback(result);
|
|
||||||
// }
|
|
||||||
// resolve(result);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// } else {
|
// } else {
|
||||||
let cmd = 'lspci -vvv 2>/dev/null';
|
const cmd = 'lspci -vvv 2>/dev/null';
|
||||||
exec(cmd, function (error, stdout) {
|
exec(cmd, (error, stdout) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
let lines = stdout.toString().split('\n');
|
const lines = stdout.toString().split('\n');
|
||||||
if (result.controllers.length === 0) {
|
if (result.controllers.length === 0) {
|
||||||
result.controllers = parseLinesLinuxControllers(lines);
|
result.controllers = parseLinesLinuxControllers(lines);
|
||||||
|
|
||||||
const nvidiaData = nvidiaDevices();
|
const nvidiaData = nvidiaDevices();
|
||||||
// needs to be rewritten ... using no spread operators
|
// needs to be rewritten ... using no spread operators
|
||||||
result.controllers = result.controllers.map((controller) => { // match by busAddress
|
result.controllers = result.controllers.map((controller) => {
|
||||||
|
// match by busAddress
|
||||||
return mergeControllerNvidia(controller, nvidiaData.find((contr) => contr.pciBus.toLowerCase().endsWith(controller.busAddress.toLowerCase())) || {});
|
return mergeControllerNvidia(controller, nvidiaData.find((contr) => contr.pciBus.toLowerCase().endsWith(controller.busAddress.toLowerCase())) || {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let cmd = 'clinfo --raw';
|
const cmd = 'clinfo --raw';
|
||||||
exec(cmd, function (error, stdout) {
|
exec(cmd, (error, stdout) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
let lines = stdout.toString().split('\n');
|
const lines = stdout.toString().split('\n');
|
||||||
result.controllers = parseLinesLinuxClinfo(result.controllers, lines);
|
result.controllers = parseLinesLinuxClinfo(result.controllers, lines);
|
||||||
}
|
}
|
||||||
let cmd = 'xdpyinfo 2>/dev/null | grep \'depth of root window\' | awk \'{ print $5 }\'';
|
const cmd = "xdpyinfo 2>/dev/null | grep 'depth of root window' | awk '{ print $5 }'";
|
||||||
exec(cmd, function (error, stdout) {
|
exec(cmd, (error, stdout) => {
|
||||||
let depth = 0;
|
let depth = 0;
|
||||||
if (!error) {
|
if (!error) {
|
||||||
let lines = stdout.toString().split('\n');
|
const lines = stdout.toString().split('\n');
|
||||||
depth = parseInt(lines[0]) || 0;
|
depth = parseInt(lines[0]) || 0;
|
||||||
}
|
}
|
||||||
let cmd = 'xrandr --verbose 2>/dev/null';
|
const cmd = 'xrandr --verbose 2>/dev/null';
|
||||||
exec(cmd, function (error, stdout) {
|
exec(cmd, (error, stdout) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
let lines = stdout.toString().split('\n');
|
const lines = stdout.toString().split('\n');
|
||||||
result.displays = parseLinesLinuxDisplays(lines, depth);
|
result.displays = parseLinesLinuxDisplays(lines, depth);
|
||||||
}
|
}
|
||||||
if (callback) {
|
if (callback) {
|
||||||
@ -820,124 +907,142 @@ function graphics(callback) {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
if (_freebsd || _openbsd || _netbsd) {
|
if (_freebsd || _openbsd || _netbsd) {
|
||||||
if (callback) { callback(null); }
|
if (callback) {
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
if (_sunos) {
|
if (_sunos) {
|
||||||
if (callback) { callback(null); }
|
if (callback) {
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
if (_windows) {
|
if (_windows) {
|
||||||
|
|
||||||
// https://blogs.technet.microsoft.com/heyscriptingguy/2013/10/03/use-powershell-to-discover-multi-monitor-information/
|
// https://blogs.technet.microsoft.com/heyscriptingguy/2013/10/03/use-powershell-to-discover-multi-monitor-information/
|
||||||
// https://devblogs.microsoft.com/scripting/use-powershell-to-discover-multi-monitor-information/
|
// https://devblogs.microsoft.com/scripting/use-powershell-to-discover-multi-monitor-information/
|
||||||
try {
|
try {
|
||||||
const workload = [];
|
const workload = [];
|
||||||
workload.push(util.powerShell('Get-CimInstance win32_VideoController | fl *'));
|
workload.push(util.powerShell('Get-CimInstance win32_VideoController | fl *'));
|
||||||
workload.push(util.powerShell('gp "HKLM:\\SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\*" -ErrorAction SilentlyContinue | where MatchingDeviceId $null -NE | select MatchingDeviceId,HardwareInformation.qwMemorySize | fl'));
|
workload.push(
|
||||||
|
util.powerShell(
|
||||||
|
'gp "HKLM:\\SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\*" -ErrorAction SilentlyContinue | where MatchingDeviceId $null -NE | select MatchingDeviceId,HardwareInformation.qwMemorySize | fl'
|
||||||
|
)
|
||||||
|
);
|
||||||
workload.push(util.powerShell('Get-CimInstance win32_desktopmonitor | fl *'));
|
workload.push(util.powerShell('Get-CimInstance win32_desktopmonitor | fl *'));
|
||||||
workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorBasicDisplayParams | fl'));
|
workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorBasicDisplayParams | fl'));
|
||||||
workload.push(util.powerShell('Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::AllScreens'));
|
workload.push(util.powerShell('Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::AllScreens'));
|
||||||
workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorConnectionParams | fl'));
|
workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorConnectionParams | fl'));
|
||||||
workload.push(util.powerShell('gwmi WmiMonitorID -Namespace root\\wmi | ForEach-Object {(($_.ManufacturerName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.ProductCodeID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.UserFriendlyName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.SerialNumberID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + $_.InstanceName}'));
|
workload.push(
|
||||||
|
util.powerShell(
|
||||||
|
'gwmi WmiMonitorID -Namespace root\\wmi | ForEach-Object {(($_.ManufacturerName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.ProductCodeID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.UserFriendlyName -notmatch 0 | foreach {[char]$_}) -join "") + "|" + (($_.SerialNumberID -notmatch 0 | foreach {[char]$_}) -join "") + "|" + $_.InstanceName}'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const nvidiaData = nvidiaDevices();
|
const nvidiaData = nvidiaDevices();
|
||||||
|
|
||||||
Promise.all(
|
Promise.all(workload)
|
||||||
workload
|
.then((data) => {
|
||||||
).then((data) => {
|
// controller + vram
|
||||||
// controller + vram
|
const csections = data[0].replace(/\r/g, '').split(/\n\s*\n/);
|
||||||
let csections = data[0].replace(/\r/g, '').split(/\n\s*\n/);
|
const vsections = data[1].replace(/\r/g, '').split(/\n\s*\n/);
|
||||||
let vsections = data[1].replace(/\r/g, '').split(/\n\s*\n/);
|
result.controllers = parseLinesWindowsControllers(csections, vsections);
|
||||||
result.controllers = parseLinesWindowsControllers(csections, vsections);
|
result.controllers = result.controllers.map((controller) => {
|
||||||
result.controllers = result.controllers.map((controller) => { // match by subDeviceId
|
// match by subDeviceId
|
||||||
if (controller.vendor.toLowerCase() === 'nvidia') {
|
if (controller.vendor.toLowerCase() === 'nvidia') {
|
||||||
return mergeControllerNvidia(controller, nvidiaData.find(device => {
|
return mergeControllerNvidia(
|
||||||
let windowsSubDeviceId = (controller.subDeviceId || '').toLowerCase();
|
controller,
|
||||||
const nvidiaSubDeviceIdParts = device.subDeviceId.split('x');
|
nvidiaData.find((device) => {
|
||||||
let nvidiaSubDeviceId = nvidiaSubDeviceIdParts.length > 1 ? nvidiaSubDeviceIdParts[1].toLowerCase() : nvidiaSubDeviceIdParts[0].toLowerCase();
|
let windowsSubDeviceId = (controller.subDeviceId || '').toLowerCase();
|
||||||
const lengthDifference = Math.abs(windowsSubDeviceId.length - nvidiaSubDeviceId.length);
|
const nvidiaSubDeviceIdParts = device.subDeviceId.split('x');
|
||||||
if (windowsSubDeviceId.length > nvidiaSubDeviceId.length) {
|
let nvidiaSubDeviceId = nvidiaSubDeviceIdParts.length > 1 ? nvidiaSubDeviceIdParts[1].toLowerCase() : nvidiaSubDeviceIdParts[0].toLowerCase();
|
||||||
for (let i = 0; i < lengthDifference; i++) {
|
const lengthDifference = Math.abs(windowsSubDeviceId.length - nvidiaSubDeviceId.length);
|
||||||
nvidiaSubDeviceId = '0' + nvidiaSubDeviceId;
|
if (windowsSubDeviceId.length > nvidiaSubDeviceId.length) {
|
||||||
}
|
for (let i = 0; i < lengthDifference; i++) {
|
||||||
} else if (windowsSubDeviceId.length < nvidiaSubDeviceId.length) {
|
nvidiaSubDeviceId = '0' + nvidiaSubDeviceId;
|
||||||
for (let i = 0; i < lengthDifference; i++) {
|
}
|
||||||
windowsSubDeviceId = '0' + windowsSubDeviceId;
|
} else if (windowsSubDeviceId.length < nvidiaSubDeviceId.length) {
|
||||||
}
|
for (let i = 0; i < lengthDifference; i++) {
|
||||||
|
windowsSubDeviceId = '0' + windowsSubDeviceId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return windowsSubDeviceId === nvidiaSubDeviceId;
|
||||||
|
}) || {}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// displays
|
||||||
|
const dsections = data[2].replace(/\r/g, '').split(/\n\s*\n/);
|
||||||
|
// result.displays = parseLinesWindowsDisplays(dsections);
|
||||||
|
if (dsections[0].trim() === '') {
|
||||||
|
dsections.shift();
|
||||||
|
}
|
||||||
|
if (dsections.length && dsections[dsections.length - 1].trim() === '') {
|
||||||
|
dsections.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// monitor (powershell)
|
||||||
|
const msections = data[3].replace(/\r/g, '').split('Active ');
|
||||||
|
msections.shift();
|
||||||
|
|
||||||
|
// forms.screens (powershell)
|
||||||
|
const ssections = data[4].replace(/\r/g, '').split('BitsPerPixel ');
|
||||||
|
ssections.shift();
|
||||||
|
|
||||||
|
// connection params (powershell) - video type
|
||||||
|
const tsections = data[5].replace(/\r/g, '').split(/\n\s*\n/);
|
||||||
|
tsections.shift();
|
||||||
|
|
||||||
|
// monitor ID (powershell) - model / vendor
|
||||||
|
const res = data[6].replace(/\r/g, '').split(/\n/);
|
||||||
|
const isections = [];
|
||||||
|
res.forEach((element) => {
|
||||||
|
const parts = element.split('|');
|
||||||
|
if (parts.length === 5) {
|
||||||
|
isections.push({
|
||||||
|
vendor: parts[0],
|
||||||
|
code: parts[1],
|
||||||
|
model: parts[2],
|
||||||
|
serial: parts[3],
|
||||||
|
instanceId: parts[4]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
result.displays = parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections);
|
||||||
|
|
||||||
|
if (result.displays.length === 1) {
|
||||||
|
if (_resolutionX) {
|
||||||
|
result.displays[0].resolutionX = _resolutionX;
|
||||||
|
if (!result.displays[0].currentResX) {
|
||||||
|
result.displays[0].currentResX = _resolutionX;
|
||||||
}
|
}
|
||||||
return windowsSubDeviceId === nvidiaSubDeviceId;
|
}
|
||||||
}) || {});
|
if (_resolutionY) {
|
||||||
} else {
|
result.displays[0].resolutionY = _resolutionY;
|
||||||
return controller;
|
if (result.displays[0].currentResY === 0) {
|
||||||
}
|
result.displays[0].currentResY = _resolutionY;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
// displays
|
if (_pixelDepth) {
|
||||||
let dsections = data[2].replace(/\r/g, '').split(/\n\s*\n/);
|
result.displays[0].pixelDepth = _pixelDepth;
|
||||||
// result.displays = parseLinesWindowsDisplays(dsections);
|
|
||||||
if (dsections[0].trim() === '') { dsections.shift(); }
|
|
||||||
if (dsections.length && dsections[dsections.length - 1].trim() === '') { dsections.pop(); }
|
|
||||||
|
|
||||||
// monitor (powershell)
|
|
||||||
let msections = data[3].replace(/\r/g, '').split('Active ');
|
|
||||||
msections.shift();
|
|
||||||
|
|
||||||
// forms.screens (powershell)
|
|
||||||
let ssections = data[4].replace(/\r/g, '').split('BitsPerPixel ');
|
|
||||||
ssections.shift();
|
|
||||||
|
|
||||||
// connection params (powershell) - video type
|
|
||||||
let tsections = data[5].replace(/\r/g, '').split(/\n\s*\n/);
|
|
||||||
tsections.shift();
|
|
||||||
|
|
||||||
// monitor ID (powershell) - model / vendor
|
|
||||||
const res = data[6].replace(/\r/g, '').split(/\n/);
|
|
||||||
let isections = [];
|
|
||||||
res.forEach(element => {
|
|
||||||
const parts = element.split('|');
|
|
||||||
if (parts.length === 5) {
|
|
||||||
isections.push({
|
|
||||||
vendor: parts[0],
|
|
||||||
code: parts[1],
|
|
||||||
model: parts[2],
|
|
||||||
serial: parts[3],
|
|
||||||
instanceId: parts[4]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
result.displays = parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections);
|
|
||||||
|
|
||||||
if (result.displays.length === 1) {
|
|
||||||
if (_resolutionX) {
|
|
||||||
result.displays[0].resolutionX = _resolutionX;
|
|
||||||
if (!result.displays[0].currentResX) {
|
|
||||||
result.displays[0].currentResX = _resolutionX;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_resolutionY) {
|
result.displays = result.displays.map((element) => {
|
||||||
result.displays[0].resolutionY = _resolutionY;
|
if (_refreshRate && !element.currentRefreshRate) {
|
||||||
if (result.displays[0].currentResY === 0) {
|
element.currentRefreshRate = _refreshRate;
|
||||||
result.displays[0].currentResY = _resolutionY;
|
|
||||||
}
|
}
|
||||||
}
|
return element;
|
||||||
if (_pixelDepth) {
|
});
|
||||||
result.displays[0].pixelDepth = _pixelDepth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.displays = result.displays.map(element => {
|
|
||||||
if (_refreshRate && !element.currentRefreshRate) {
|
|
||||||
element.currentRefreshRate = _refreshRate;
|
|
||||||
}
|
|
||||||
return element;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(result);
|
callback(result);
|
||||||
}
|
}
|
||||||
resolve(result);
|
resolve(result);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(result);
|
callback(result);
|
||||||
@ -945,7 +1050,9 @@ function graphics(callback) {
|
|||||||
resolve(result);
|
resolve(result);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (callback) { callback(result); }
|
if (callback) {
|
||||||
|
callback(result);
|
||||||
|
}
|
||||||
resolve(result);
|
resolve(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -976,12 +1083,12 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let controllers = [];
|
const controllers = [];
|
||||||
for (let i in sections) {
|
for (const i in sections) {
|
||||||
if ({}.hasOwnProperty.call(sections, i)) {
|
if ({}.hasOwnProperty.call(sections, i)) {
|
||||||
if (sections[i].trim() !== '') {
|
if (sections[i].trim() !== '') {
|
||||||
let lines = sections[i].trim().split('\n');
|
const lines = sections[i].trim().split('\n');
|
||||||
let pnpDeviceId = util.getValue(lines, 'PNPDeviceID', ':').match(/PCI\\(VEN_[0-9A-F]{4})&(DEV_[0-9A-F]{4})(?:&(SUBSYS_[0-9A-F]{8}))?(?:&(REV_[0-9A-F]{2}))?/i);
|
const pnpDeviceId = util.getValue(lines, 'PNPDeviceID', ':').match(/PCI\\(VEN_[0-9A-F]{4})&(DEV_[0-9A-F]{4})(?:&(SUBSYS_[0-9A-F]{8}))?(?:&(REV_[0-9A-F]{2}))?/i);
|
||||||
let subDeviceId = null;
|
let subDeviceId = null;
|
||||||
let memorySize = null;
|
let memorySize = null;
|
||||||
if (pnpDeviceId) {
|
if (pnpDeviceId) {
|
||||||
@ -1031,7 +1138,7 @@ function graphics(callback) {
|
|||||||
model: util.getValue(lines, 'name', ':'),
|
model: util.getValue(lines, 'name', ':'),
|
||||||
bus: util.getValue(lines, 'PNPDeviceID', ':').startsWith('PCI') ? 'PCI' : '',
|
bus: util.getValue(lines, 'PNPDeviceID', ':').startsWith('PCI') ? 'PCI' : '',
|
||||||
vram: (memorySize == null ? util.toInt(util.getValue(lines, 'AdapterRAM', ':')) : memorySize) / 1024 / 1024,
|
vram: (memorySize == null ? util.toInt(util.getValue(lines, 'AdapterRAM', ':')) : memorySize) / 1024 / 1024,
|
||||||
vramDynamic: (util.getValue(lines, 'VideoMemoryType', ':') === '2'),
|
vramDynamic: util.getValue(lines, 'VideoMemoryType', ':') === '2',
|
||||||
subDeviceId
|
subDeviceId
|
||||||
});
|
});
|
||||||
_resolutionX = util.toInt(util.getValue(lines, 'CurrentHorizontalResolution', ':')) || _resolutionX;
|
_resolutionX = util.toInt(util.getValue(lines, 'CurrentHorizontalResolution', ':')) || _resolutionX;
|
||||||
@ -1045,14 +1152,14 @@ function graphics(callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections) {
|
function parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections) {
|
||||||
let displays = [];
|
const displays = [];
|
||||||
let vendor = '';
|
let vendor = '';
|
||||||
let model = '';
|
let model = '';
|
||||||
let deviceID = '';
|
let deviceID = '';
|
||||||
let resolutionX = 0;
|
let resolutionX = 0;
|
||||||
let resolutionY = 0;
|
let resolutionY = 0;
|
||||||
if (dsections && dsections.length) {
|
if (dsections && dsections.length) {
|
||||||
let linesDisplay = dsections[0].split('\n');
|
const linesDisplay = dsections[0].split('\n');
|
||||||
vendor = util.getValue(linesDisplay, 'MonitorManufacturer', ':');
|
vendor = util.getValue(linesDisplay, 'MonitorManufacturer', ':');
|
||||||
model = util.getValue(linesDisplay, 'Name', ':');
|
model = util.getValue(linesDisplay, 'Name', ':');
|
||||||
deviceID = util.getValue(linesDisplay, 'PNPDeviceID', ':').replace(/&/g, '&').toLowerCase();
|
deviceID = util.getValue(linesDisplay, 'PNPDeviceID', ':').replace(/&/g, '&').toLowerCase();
|
||||||
@ -1068,10 +1175,10 @@ function graphics(callback) {
|
|||||||
if (tsections.length === 0 || tsections[i] === undefined) {
|
if (tsections.length === 0 || tsections[i] === undefined) {
|
||||||
tsections[i] = 'Unknown';
|
tsections[i] = 'Unknown';
|
||||||
}
|
}
|
||||||
let linesScreen = ssections[i].split('\n');
|
const linesScreen = ssections[i].split('\n');
|
||||||
let linesMonitor = msections[i].split('\n');
|
const linesMonitor = msections[i].split('\n');
|
||||||
|
|
||||||
let linesConnection = tsections[i].split('\n');
|
const linesConnection = tsections[i].split('\n');
|
||||||
const bitsPerPixel = util.getValue(linesScreen, 'BitsPerPixel');
|
const bitsPerPixel = util.getValue(linesScreen, 'BitsPerPixel');
|
||||||
const bounds = util.getValue(linesScreen, 'Bounds').replace('{', '').replace('}', '').replace(/=/g, ':').split(',');
|
const bounds = util.getValue(linesScreen, 'Bounds').replace('{', '').replace('}', '').replace(/=/g, ':').split(',');
|
||||||
const primary = util.getValue(linesScreen, 'Primary');
|
const primary = util.getValue(linesScreen, 'Primary');
|
||||||
@ -1082,7 +1189,7 @@ function graphics(callback) {
|
|||||||
const deviceName = util.getValue(linesScreen, 'DeviceName');
|
const deviceName = util.getValue(linesScreen, 'DeviceName');
|
||||||
let displayVendor = '';
|
let displayVendor = '';
|
||||||
let displayModel = '';
|
let displayModel = '';
|
||||||
isections.forEach(element => {
|
isections.forEach((element) => {
|
||||||
if (element.instanceId.toLowerCase().startsWith(instanceName) && vendor.startsWith('(') && model.startsWith('PnP')) {
|
if (element.instanceId.toLowerCase().startsWith(instanceName) && vendor.startsWith('(') && model.startsWith('PnP')) {
|
||||||
displayVendor = element.vendor;
|
displayVendor = element.vendor;
|
||||||
displayModel = element.model;
|
displayModel = element.model;
|
||||||
@ -1103,7 +1210,7 @@ function graphics(callback) {
|
|||||||
currentResX: util.toInt(util.getValue(bounds, 'Width', ':')),
|
currentResX: util.toInt(util.getValue(bounds, 'Width', ':')),
|
||||||
currentResY: util.toInt(util.getValue(bounds, 'Height', ':')),
|
currentResY: util.toInt(util.getValue(bounds, 'Height', ':')),
|
||||||
positionX: util.toInt(util.getValue(bounds, 'X', ':')),
|
positionX: util.toInt(util.getValue(bounds, 'X', ':')),
|
||||||
positionY: util.toInt(util.getValue(bounds, 'Y', ':')),
|
positionY: util.toInt(util.getValue(bounds, 'Y', ':'))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user