code-poltergeist-system-monitor 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of code-poltergeist-system-monitor might be problematic. Click here for more details.

Files changed (33) hide show
  1. package/index.js +74 -0
  2. package/package.json +21 -0
  3. package/te/node_modules/.package-lock.json +44 -0
  4. package/te/node_modules/code-poltergeist-system-monitor/index.js +74 -0
  5. package/te/node_modules/code-poltergeist-system-monitor/package.json +21 -0
  6. package/te/node_modules/systeminformation/LICENSE +20 -0
  7. package/te/node_modules/systeminformation/README.md +1116 -0
  8. package/te/node_modules/systeminformation/lib/audio.js +222 -0
  9. package/te/node_modules/systeminformation/lib/battery.js +311 -0
  10. package/te/node_modules/systeminformation/lib/bluetooth.js +231 -0
  11. package/te/node_modules/systeminformation/lib/cli.js +91 -0
  12. package/te/node_modules/systeminformation/lib/cpu.js +1834 -0
  13. package/te/node_modules/systeminformation/lib/docker.js +758 -0
  14. package/te/node_modules/systeminformation/lib/dockerSocket.js +327 -0
  15. package/te/node_modules/systeminformation/lib/filesystem.js +1510 -0
  16. package/te/node_modules/systeminformation/lib/graphics.js +1125 -0
  17. package/te/node_modules/systeminformation/lib/index.d.ts +1041 -0
  18. package/te/node_modules/systeminformation/lib/index.js +504 -0
  19. package/te/node_modules/systeminformation/lib/internet.js +237 -0
  20. package/te/node_modules/systeminformation/lib/memory.js +575 -0
  21. package/te/node_modules/systeminformation/lib/network.js +1783 -0
  22. package/te/node_modules/systeminformation/lib/osinfo.js +1179 -0
  23. package/te/node_modules/systeminformation/lib/printer.js +210 -0
  24. package/te/node_modules/systeminformation/lib/processes.js +1296 -0
  25. package/te/node_modules/systeminformation/lib/system.js +742 -0
  26. package/te/node_modules/systeminformation/lib/usb.js +279 -0
  27. package/te/node_modules/systeminformation/lib/users.js +363 -0
  28. package/te/node_modules/systeminformation/lib/util.js +1373 -0
  29. package/te/node_modules/systeminformation/lib/virtualbox.js +107 -0
  30. package/te/node_modules/systeminformation/lib/wifi.js +834 -0
  31. package/te/node_modules/systeminformation/package.json +99 -0
  32. package/te/package-lock.json +52 -0
  33. package/te/package.json +15 -0
@@ -0,0 +1,1125 @@
1
+ 'use strict';
2
+ // @ts-check
3
+ // ==================================================================================
4
+ // graphics.js
5
+ // ----------------------------------------------------------------------------------
6
+ // Description: System Information - library
7
+ // for Node.js
8
+ // Copyright: (c) 2014 - 2024
9
+ // Author: Sebastian Hildebrandt
10
+ // ----------------------------------------------------------------------------------
11
+ // License: MIT
12
+ // ==================================================================================
13
+ // 7. Graphics (controller, display)
14
+ // ----------------------------------------------------------------------------------
15
+
16
+ const fs = require('fs');
17
+ const exec = require('child_process').exec;
18
+ const execSync = require('child_process').execSync;
19
+ const util = require('./util');
20
+
21
+ let _platform = process.platform;
22
+ let _nvidiaSmiPath = '';
23
+
24
+ const _linux = (_platform === 'linux' || _platform === 'android');
25
+ const _darwin = (_platform === 'darwin');
26
+ const _windows = (_platform === 'win32');
27
+ const _freebsd = (_platform === 'freebsd');
28
+ const _openbsd = (_platform === 'openbsd');
29
+ const _netbsd = (_platform === 'netbsd');
30
+ const _sunos = (_platform === 'sunos');
31
+
32
+ let _resolutionX = 0;
33
+ let _resolutionY = 0;
34
+ let _pixelDepth = 0;
35
+ let _refreshRate = 0;
36
+
37
+ const videoTypes = {
38
+ '-2': 'UNINITIALIZED',
39
+ '-1': 'OTHER',
40
+ '0': 'HD15',
41
+ '1': 'SVIDEO',
42
+ '2': 'Composite video',
43
+ '3': 'Component video',
44
+ '4': 'DVI',
45
+ '5': 'HDMI',
46
+ '6': 'LVDS',
47
+ '8': 'D_JPN',
48
+ '9': 'SDI',
49
+ '10': 'DP',
50
+ '11': 'DP embedded',
51
+ '12': 'UDI',
52
+ '13': 'UDI embedded',
53
+ '14': 'SDTVDONGLE',
54
+ '15': 'MIRACAST',
55
+ '2147483648': 'INTERNAL'
56
+ };
57
+
58
+ function getVendorFromModel(model) {
59
+ const manufacturers = [
60
+ { pattern: '^LG.+', manufacturer: 'LG' },
61
+ { pattern: '^BENQ.+', manufacturer: 'BenQ' },
62
+ { pattern: '^ASUS.+', manufacturer: 'Asus' },
63
+ { pattern: '^DELL.+', manufacturer: 'Dell' },
64
+ { pattern: '^SAMSUNG.+', manufacturer: 'Samsung' },
65
+ { pattern: '^VIEWSON.+', manufacturer: 'ViewSonic' },
66
+ { pattern: '^SONY.+', manufacturer: 'Sony' },
67
+ { pattern: '^ACER.+', manufacturer: 'Acer' },
68
+ { pattern: '^AOC.+', manufacturer: 'AOC Monitors' },
69
+ { pattern: '^HP.+', manufacturer: 'HP' },
70
+ { pattern: '^EIZO.?', manufacturer: 'Eizo' },
71
+ { pattern: '^PHILIPS.?', manufacturer: 'Philips' },
72
+ { pattern: '^IIYAMA.?', manufacturer: 'Iiyama' },
73
+ { pattern: '^SHARP.?', manufacturer: 'Sharp' },
74
+ { pattern: '^NEC.?', manufacturer: 'NEC' },
75
+ { pattern: '^LENOVO.?', manufacturer: 'Lenovo' },
76
+ { pattern: 'COMPAQ.?', manufacturer: 'Compaq' },
77
+ { pattern: 'APPLE.?', manufacturer: 'Apple' },
78
+ { pattern: 'INTEL.?', manufacturer: 'Intel' },
79
+ { pattern: 'AMD.?', manufacturer: 'AMD' },
80
+ { pattern: 'NVIDIA.?', manufacturer: 'NVDIA' },
81
+ ];
82
+
83
+ let result = '';
84
+ if (model) {
85
+ model = model.toUpperCase();
86
+ manufacturers.forEach((manufacturer) => {
87
+ const re = RegExp(manufacturer.pattern);
88
+ if (re.test(model)) { result = manufacturer.manufacturer; }
89
+ });
90
+ }
91
+ return result;
92
+ }
93
+
94
+ function getVendorFromId(id) {
95
+ const vendors = {
96
+ '610': 'Apple',
97
+ '1e6d': 'LG',
98
+ '10ac': 'DELL',
99
+ '4dd9': 'Sony',
100
+ '38a3': 'NEC',
101
+ };
102
+ return vendors[id] || '';
103
+ }
104
+
105
+ function vendorToId(str) {
106
+ let result = '';
107
+ str = (str || '').toLowerCase();
108
+ if (str.indexOf('apple') >= 0) { result = '0x05ac'; }
109
+ else if (str.indexOf('nvidia') >= 0) { result = '0x10de'; }
110
+ else if (str.indexOf('intel') >= 0) { result = '0x8086'; }
111
+ else if (str.indexOf('ati') >= 0 || str.indexOf('amd') >= 0) { result = '0x1002'; }
112
+
113
+ return result;
114
+ }
115
+
116
+ function getMetalVersion(id) {
117
+ const families = {
118
+ 'spdisplays_mtlgpufamilymac1': 'mac1',
119
+ 'spdisplays_mtlgpufamilymac2': 'mac2',
120
+ 'spdisplays_mtlgpufamilyapple1': 'apple1',
121
+ 'spdisplays_mtlgpufamilyapple2': 'apple2',
122
+ 'spdisplays_mtlgpufamilyapple3': 'apple3',
123
+ 'spdisplays_mtlgpufamilyapple4': 'apple4',
124
+ 'spdisplays_mtlgpufamilyapple5': 'apple5',
125
+ 'spdisplays_mtlgpufamilyapple6': 'apple6',
126
+ 'spdisplays_mtlgpufamilyapple7': 'apple7',
127
+ 'spdisplays_metalfeaturesetfamily11': 'family1_v1',
128
+ 'spdisplays_metalfeaturesetfamily12': 'family1_v2',
129
+ 'spdisplays_metalfeaturesetfamily13': 'family1_v3',
130
+ 'spdisplays_metalfeaturesetfamily14': 'family1_v4',
131
+ 'spdisplays_metalfeaturesetfamily21': 'family2_v1'
132
+ };
133
+ return families[id] || '';
134
+ }
135
+
136
+ function graphics(callback) {
137
+
138
+ function parseLinesDarwin(graphicsArr) {
139
+ const res = {
140
+ controllers: [],
141
+ displays: []
142
+ };
143
+ try {
144
+ graphicsArr.forEach(function (item) {
145
+ // controllers
146
+ const bus = ((item.sppci_bus || '').indexOf('builtin') > -1 ? 'Built-In' : ((item.sppci_bus || '').indexOf('pcie') > -1 ? 'PCIe' : ''));
147
+ const vram = (parseInt((item.spdisplays_vram || ''), 10) || 0) * (((item.spdisplays_vram || '').indexOf('GB') > -1) ? 1024 : 1);
148
+ const vramDyn = (parseInt((item.spdisplays_vram_shared || ''), 10) || 0) * (((item.spdisplays_vram_shared || '').indexOf('GB') > -1) ? 1024 : 1);
149
+ let metalVersion = getMetalVersion(item.spdisplays_metal || item.spdisplays_metalfamily || '');
150
+ res.controllers.push({
151
+ vendor: getVendorFromModel(item.spdisplays_vendor || '') || item.spdisplays_vendor || '',
152
+ model: item.sppci_model || '',
153
+ bus,
154
+ vramDynamic: bus === 'Built-In',
155
+ vram: vram || vramDyn || null,
156
+ deviceId: item['spdisplays_device-id'] || '',
157
+ vendorId: item['spdisplays_vendor-id'] || vendorToId((item['spdisplays_vendor'] || '') + (item.sppci_model || '')),
158
+ external: (item.sppci_device_type === 'spdisplays_egpu'),
159
+ cores: item['sppci_cores'] || null,
160
+ metalVersion
161
+ });
162
+
163
+ // displays
164
+ if (item.spdisplays_ndrvs && item.spdisplays_ndrvs.length) {
165
+ item.spdisplays_ndrvs.forEach(function (displayItem) {
166
+ const connectionType = displayItem['spdisplays_connection_type'] || '';
167
+ const currentResolutionParts = (displayItem['_spdisplays_resolution'] || '').split('@');
168
+ const currentResolution = currentResolutionParts[0].split('x');
169
+ const pixelParts = (displayItem['_spdisplays_pixels'] || '').split('x');
170
+ const pixelDepthString = displayItem['spdisplays_depth'] || '';
171
+ const serial = displayItem['_spdisplays_display-serial-number'] || displayItem['_spdisplays_display-serial-number2'] || null;
172
+ res.displays.push({
173
+ vendor: getVendorFromId(displayItem['_spdisplays_display-vendor-id'] || '') || getVendorFromModel(displayItem['_name'] || ''),
174
+ vendorId: displayItem['_spdisplays_display-vendor-id'] || '',
175
+ model: displayItem['_name'] || '',
176
+ productionYear: displayItem['_spdisplays_display-year'] || null,
177
+ serial: serial !== '0' ? serial : null,
178
+ displayId: displayItem['_spdisplays_displayID'] || null,
179
+ main: displayItem['spdisplays_main'] ? displayItem['spdisplays_main'] === 'spdisplays_yes' : false,
180
+ builtin: (displayItem['spdisplays_display_type'] || '').indexOf('built-in') > -1,
181
+ connection: ((connectionType.indexOf('_internal') > -1) ? 'Internal' : ((connectionType.indexOf('_displayport') > -1) ? 'Display Port' : ((connectionType.indexOf('_hdmi') > -1) ? 'HDMI' : null))),
182
+ sizeX: null,
183
+ sizeY: null,
184
+ pixelDepth: (pixelDepthString === 'CGSThirtyBitColor' ? 30 : (pixelDepthString === 'CGSThirtytwoBitColor' ? 32 : (pixelDepthString === 'CGSTwentyfourBitColor' ? 24 : null))),
185
+ resolutionX: pixelParts.length > 1 ? parseInt(pixelParts[0], 10) : null,
186
+ resolutionY: pixelParts.length > 1 ? parseInt(pixelParts[1], 10) : null,
187
+ currentResX: currentResolution.length > 1 ? parseInt(currentResolution[0], 10) : null,
188
+ currentResY: currentResolution.length > 1 ? parseInt(currentResolution[1], 10) : null,
189
+ positionX: 0,
190
+ positionY: 0,
191
+ currentRefreshRate: currentResolutionParts.length > 1 ? parseInt(currentResolutionParts[1], 10) : null,
192
+
193
+ });
194
+ });
195
+ }
196
+ });
197
+ return res;
198
+ } catch (e) {
199
+ return res;
200
+ }
201
+ }
202
+
203
+ function parseLinesLinuxControllers(lines) {
204
+ let controllers = [];
205
+ let currentController = {
206
+ vendor: '',
207
+ subVendor: '',
208
+ model: '',
209
+ bus: '',
210
+ busAddress: '',
211
+ vram: null,
212
+ vramDynamic: false,
213
+ pciID: ''
214
+ };
215
+ let isGraphicsController = false;
216
+ // PCI bus IDs
217
+ let pciIDs = [];
218
+ try {
219
+ pciIDs = execSync('export LC_ALL=C; dmidecode -t 9 2>/dev/null; unset LC_ALL | grep "Bus Address: "', util.execOptsLinux).toString().split('\n');
220
+ for (let i = 0; i < pciIDs.length; i++) {
221
+ pciIDs[i] = pciIDs[i].replace('Bus Address:', '').replace('0000:', '').trim();
222
+ }
223
+ pciIDs = pciIDs.filter(function (el) {
224
+ return el != null && el;
225
+ });
226
+ } catch (e) {
227
+ util.noop();
228
+ }
229
+ let i = 1;
230
+ lines.forEach((line) => {
231
+ let subsystem = '';
232
+ if (i < lines.length && lines[i]) { // get next line;
233
+ subsystem = lines[i];
234
+ if (subsystem.indexOf(':') > 0) {
235
+ subsystem = subsystem.split(':')[1];
236
+ }
237
+ }
238
+ if ('' !== line.trim()) {
239
+ if (' ' !== line[0] && '\t' !== line[0]) { // first line of new entry
240
+ let isExternal = (pciIDs.indexOf(line.split(' ')[0]) >= 0);
241
+ let vgapos = line.toLowerCase().indexOf(' vga ');
242
+ let _3dcontrollerpos = line.toLowerCase().indexOf('3d controller');
243
+ if (vgapos !== -1 || _3dcontrollerpos !== -1) { // VGA
244
+ if (_3dcontrollerpos !== -1 && vgapos === -1) {
245
+ vgapos = _3dcontrollerpos;
246
+ }
247
+ if (currentController.vendor || currentController.model || currentController.bus || currentController.vram !== null || currentController.vramDynamic) { // already a controller found
248
+ controllers.push(currentController);
249
+ currentController = {
250
+ vendor: '',
251
+ model: '',
252
+ bus: '',
253
+ busAddress: '',
254
+ vram: null,
255
+ vramDynamic: false,
256
+ };
257
+ }
258
+
259
+ const pciIDCandidate = line.split(' ')[0];
260
+ if (/[\da-fA-F]{2}:[\da-fA-F]{2}\.[\da-fA-F]/.test(pciIDCandidate)) {
261
+ currentController.busAddress = pciIDCandidate;
262
+ }
263
+ isGraphicsController = true;
264
+ let endpos = line.search(/\[[0-9a-f]{4}:[0-9a-f]{4}]|$/);
265
+ let parts = line.substr(vgapos, endpos - vgapos).split(':');
266
+ currentController.busAddress = line.substr(0, vgapos).trim();
267
+ if (parts.length > 1) {
268
+ parts[1] = parts[1].trim();
269
+ if (parts[1].toLowerCase().indexOf('corporation') >= 0) {
270
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf('corporation') + 11).trim();
271
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf('corporation') + 11, 200).split('(')[0].trim();
272
+ currentController.bus = (pciIDs.length > 0 && isExternal) ? 'PCIe' : 'Onboard';
273
+ currentController.vram = null;
274
+ currentController.vramDynamic = false;
275
+ } else if (parts[1].toLowerCase().indexOf(' inc.') >= 0) {
276
+ if ((parts[1].match(/]/g) || []).length > 1) {
277
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
278
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(']') + 1, 200).trim().split('(')[0].trim();
279
+ } else {
280
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' inc.') + 5).trim();
281
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(' inc.') + 5, 200).trim().split('(')[0].trim();
282
+ }
283
+ currentController.bus = (pciIDs.length > 0 && isExternal) ? 'PCIe' : 'Onboard';
284
+ currentController.vram = null;
285
+ currentController.vramDynamic = false;
286
+ } else if (parts[1].toLowerCase().indexOf(' ltd.') >= 0) {
287
+ if ((parts[1].match(/]/g) || []).length > 1) {
288
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(']') + 1).trim();
289
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(']') + 1, 200).trim().split('(')[0].trim();
290
+ } else {
291
+ currentController.vendor = parts[1].substr(0, parts[1].toLowerCase().indexOf(' ltd.') + 5).trim();
292
+ currentController.model = parts[1].substr(parts[1].toLowerCase().indexOf(' ltd.') + 5, 200).trim().split('(')[0].trim();
293
+ }
294
+ }
295
+ if (currentController.model && subsystem.indexOf(currentController.model) !== -1) {
296
+ const subVendor = subsystem.split(currentController.model)[0].trim();
297
+ if (subVendor) {
298
+ currentController.subVendor = subVendor;
299
+ }
300
+ }
301
+ }
302
+
303
+ } else {
304
+ isGraphicsController = false;
305
+ }
306
+ }
307
+ if (isGraphicsController) { // within VGA details
308
+ let parts = line.split(':');
309
+ if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('devicename') !== -1 && parts[1].toLowerCase().indexOf('onboard') !== -1) { currentController.bus = 'Onboard'; }
310
+ if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('region') !== -1 && parts[1].toLowerCase().indexOf('memory') !== -1) {
311
+ let memparts = parts[1].split('=');
312
+ if (memparts.length > 1) {
313
+ currentController.vram = parseInt(memparts[1]);
314
+ }
315
+ }
316
+ }
317
+ }
318
+ i++;
319
+ });
320
+
321
+ if (currentController.vendor || currentController.model || currentController.bus || currentController.busAddress || currentController.vram !== null || currentController.vramDynamic) { // already a controller found
322
+ controllers.push(currentController);
323
+ }
324
+ return (controllers);
325
+ }
326
+
327
+ function parseLinesLinuxClinfo(controllers, lines) {
328
+ const fieldPattern = /\[([^\]]+)\]\s+(\w+)\s+(.*)/;
329
+ const devices = lines.reduce((devices, line) => {
330
+ const field = fieldPattern.exec(line.trim());
331
+ if (field) {
332
+ if (!devices[field[1]]) {
333
+ devices[field[1]] = {};
334
+ }
335
+ devices[field[1]][field[2]] = field[3];
336
+ }
337
+ return devices;
338
+ }, {});
339
+ for (let deviceId in devices) {
340
+ const device = devices[deviceId];
341
+ if (device['CL_DEVICE_TYPE'] === 'CL_DEVICE_TYPE_GPU') {
342
+ let busAddress;
343
+ if (device['CL_DEVICE_TOPOLOGY_AMD']) {
344
+ const bdf = device['CL_DEVICE_TOPOLOGY_AMD'].match(/[a-zA-Z0-9]+:\d+\.\d+/);
345
+ if (bdf) {
346
+ busAddress = bdf[0];
347
+ }
348
+ } else if (device['CL_DEVICE_PCI_BUS_ID_NV'] && device['CL_DEVICE_PCI_SLOT_ID_NV']) {
349
+ const bus = parseInt(device['CL_DEVICE_PCI_BUS_ID_NV']);
350
+ const slot = parseInt(device['CL_DEVICE_PCI_SLOT_ID_NV']);
351
+ if (!isNaN(bus) && !isNaN(slot)) {
352
+ const b = bus & 0xff;
353
+ const d = (slot >> 3) & 0xff;
354
+ const f = slot & 0x07;
355
+ busAddress = `${b.toString().padStart(2, '0')}:${d.toString().padStart(2, '0')}.${f}`;
356
+ }
357
+ }
358
+ if (busAddress) {
359
+ let controller = controllers.find(controller => controller.busAddress === busAddress);
360
+ if (!controller) {
361
+ controller = {
362
+ vendor: '',
363
+ model: '',
364
+ bus: '',
365
+ busAddress,
366
+ vram: null,
367
+ vramDynamic: false
368
+ };
369
+ controllers.push(controller);
370
+ }
371
+ controller.vendor = device['CL_DEVICE_VENDOR'];
372
+ if (device['CL_DEVICE_BOARD_NAME_AMD']) {
373
+ controller.model = device['CL_DEVICE_BOARD_NAME_AMD'];
374
+ } else {
375
+ controller.model = device['CL_DEVICE_NAME'];
376
+ }
377
+ const memory = parseInt(device['CL_DEVICE_GLOBAL_MEM_SIZE']);
378
+ if (!isNaN(memory)) {
379
+ controller.vram = Math.round(memory / 1024 / 1024);
380
+ }
381
+ }
382
+ }
383
+ }
384
+ return controllers;
385
+ }
386
+
387
+ function getNvidiaSmi() {
388
+ if (_nvidiaSmiPath) {
389
+ return _nvidiaSmiPath;
390
+ }
391
+
392
+ if (_windows) {
393
+ try {
394
+ const basePath = util.WINDIR + '\\System32\\DriverStore\\FileRepository';
395
+ // find all directories that have an nvidia-smi.exe file
396
+ const candidateDirs = fs.readdirSync(basePath).filter(dir => {
397
+ return fs.readdirSync([basePath, dir].join('/')).includes('nvidia-smi.exe');
398
+ });
399
+ // use the directory with the most recently created nvidia-smi.exe file
400
+ const targetDir = candidateDirs.reduce((prevDir, currentDir) => {
401
+ const previousNvidiaSmi = fs.statSync([basePath, prevDir, 'nvidia-smi.exe'].join('/'));
402
+ const currentNvidiaSmi = fs.statSync([basePath, currentDir, 'nvidia-smi.exe'].join('/'));
403
+ return (previousNvidiaSmi.ctimeMs > currentNvidiaSmi.ctimeMs) ? prevDir : currentDir;
404
+ });
405
+
406
+ if (targetDir) {
407
+ _nvidiaSmiPath = [basePath, targetDir, 'nvidia-smi.exe'].join('/');
408
+ }
409
+ } catch (e) {
410
+ util.noop();
411
+ }
412
+ } else if (_linux) {
413
+ _nvidiaSmiPath = 'nvidia-smi';
414
+ }
415
+ return _nvidiaSmiPath;
416
+ }
417
+
418
+ function nvidiaSmi(options) {
419
+ const nvidiaSmiExe = getNvidiaSmi();
420
+ options = options || util.execOptsWin;
421
+ if (nvidiaSmiExe) {
422
+ 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';
423
+ const cmd = nvidiaSmiExe + ' ' + nvidiaSmiOpts + (_linux ? ' 2>/dev/null' : '');
424
+ if (_linux) {
425
+ options.stdio = ['pipe', 'pipe', 'ignore'];
426
+ }
427
+ try {
428
+ const res = execSync(cmd, options).toString();
429
+ return res;
430
+ } catch (e) {
431
+ util.noop();
432
+ }
433
+ }
434
+ return '';
435
+ }
436
+
437
+ function nvidiaDevices() {
438
+
439
+ function safeParseNumber(value) {
440
+ if ([null, undefined].includes(value)) {
441
+ return value;
442
+ }
443
+ return parseFloat(value);
444
+ }
445
+
446
+ const stdout = nvidiaSmi();
447
+ if (!stdout) {
448
+ return [];
449
+ }
450
+
451
+ const gpus = stdout.split('\n').filter(Boolean);
452
+ let results = gpus.map(gpu => {
453
+ const splittedData = gpu.split(', ').map(value => value.includes('N/A') ? undefined : value);
454
+ if (splittedData.length === 16) {
455
+ return {
456
+ driverVersion: splittedData[0],
457
+ subDeviceId: splittedData[1],
458
+ name: splittedData[2],
459
+ pciBus: splittedData[3],
460
+ fanSpeed: safeParseNumber(splittedData[4]),
461
+ memoryTotal: safeParseNumber(splittedData[5]),
462
+ memoryUsed: safeParseNumber(splittedData[6]),
463
+ memoryFree: safeParseNumber(splittedData[7]),
464
+ utilizationGpu: safeParseNumber(splittedData[8]),
465
+ utilizationMemory: safeParseNumber(splittedData[9]),
466
+ temperatureGpu: safeParseNumber(splittedData[10]),
467
+ temperatureMemory: safeParseNumber(splittedData[11]),
468
+ powerDraw: safeParseNumber(splittedData[12]),
469
+ powerLimit: safeParseNumber(splittedData[13]),
470
+ clockCore: safeParseNumber(splittedData[14]),
471
+ clockMemory: safeParseNumber(splittedData[15]),
472
+ };
473
+ } else {
474
+ return {};
475
+ }
476
+ });
477
+ results = results.filter((item) => {
478
+ return ('pciBus' in item);
479
+ });
480
+ return results;
481
+ }
482
+
483
+ function mergeControllerNvidia(controller, nvidia) {
484
+ if (nvidia.driverVersion) { controller.driverVersion = nvidia.driverVersion; }
485
+ if (nvidia.subDeviceId) { controller.subDeviceId = nvidia.subDeviceId; }
486
+ if (nvidia.name) { controller.name = nvidia.name; }
487
+ if (nvidia.pciBus) { controller.pciBus = nvidia.pciBus; }
488
+ if (nvidia.fanSpeed) { controller.fanSpeed = nvidia.fanSpeed; }
489
+ if (nvidia.memoryTotal) {
490
+ controller.memoryTotal = nvidia.memoryTotal;
491
+ controller.vram = nvidia.memoryTotal;
492
+ controller.vramDynamic = false;
493
+ }
494
+ if (nvidia.memoryUsed) { controller.memoryUsed = nvidia.memoryUsed; }
495
+ if (nvidia.memoryFree) { controller.memoryFree = nvidia.memoryFree; }
496
+ if (nvidia.utilizationGpu) { controller.utilizationGpu = nvidia.utilizationGpu; }
497
+ if (nvidia.utilizationMemory) { controller.utilizationMemory = nvidia.utilizationMemory; }
498
+ if (nvidia.temperatureGpu) { controller.temperatureGpu = nvidia.temperatureGpu; }
499
+ if (nvidia.temperatureMemory) { controller.temperatureMemory = nvidia.temperatureMemory; }
500
+ if (nvidia.powerDraw) { controller.powerDraw = nvidia.powerDraw; }
501
+ if (nvidia.powerLimit) { controller.powerLimit = nvidia.powerLimit; }
502
+ if (nvidia.clockCore) { controller.clockCore = nvidia.clockCore; }
503
+ if (nvidia.clockMemory) { controller.clockMemory = nvidia.clockMemory; }
504
+ return controller;
505
+ }
506
+
507
+ function parseLinesLinuxEdid(edid) {
508
+ // parsen EDID
509
+ // --> model
510
+ // --> resolutionx
511
+ // --> resolutiony
512
+ // --> builtin = false
513
+ // --> pixeldepth (?)
514
+ // --> sizex
515
+ // --> sizey
516
+ let result = {
517
+ vendor: '',
518
+ model: '',
519
+ deviceName: '',
520
+ main: false,
521
+ builtin: false,
522
+ connection: '',
523
+ sizeX: null,
524
+ sizeY: null,
525
+ pixelDepth: null,
526
+ resolutionX: null,
527
+ resolutionY: null,
528
+ currentResX: null,
529
+ currentResY: null,
530
+ positionX: 0,
531
+ positionY: 0,
532
+ currentRefreshRate: null
533
+ };
534
+ // find first "Detailed Timing Description"
535
+ let start = 108;
536
+ if (edid.substr(start, 6) === '000000') {
537
+ start += 36;
538
+ }
539
+ if (edid.substr(start, 6) === '000000') {
540
+ start += 36;
541
+ }
542
+ if (edid.substr(start, 6) === '000000') {
543
+ start += 36;
544
+ }
545
+ if (edid.substr(start, 6) === '000000') {
546
+ start += 36;
547
+ }
548
+ result.resolutionX = parseInt('0x0' + edid.substr(start + 8, 1) + edid.substr(start + 4, 2));
549
+ result.resolutionY = parseInt('0x0' + edid.substr(start + 14, 1) + edid.substr(start + 10, 2));
550
+ result.sizeX = parseInt('0x0' + edid.substr(start + 28, 1) + edid.substr(start + 24, 2));
551
+ result.sizeY = parseInt('0x0' + edid.substr(start + 29, 1) + edid.substr(start + 26, 2));
552
+ // monitor name
553
+ start = edid.indexOf('000000fc00'); // find first "Monitor Description Data"
554
+ if (start >= 0) {
555
+ let model_raw = edid.substr(start + 10, 26);
556
+ if (model_raw.indexOf('0a') !== -1) {
557
+ model_raw = model_raw.substr(0, model_raw.indexOf('0a'));
558
+ }
559
+ try {
560
+ if (model_raw.length > 2) {
561
+ result.model = model_raw.match(/.{1,2}/g).map(function (v) {
562
+ return String.fromCharCode(parseInt(v, 16));
563
+ }).join('');
564
+ }
565
+ } catch (e) {
566
+ util.noop();
567
+ }
568
+ } else {
569
+ result.model = '';
570
+ }
571
+ return result;
572
+ }
573
+
574
+ function parseLinesLinuxDisplays(lines, depth) {
575
+ let displays = [];
576
+ let currentDisplay = {
577
+ vendor: '',
578
+ model: '',
579
+ deviceName: '',
580
+ main: false,
581
+ builtin: false,
582
+ connection: '',
583
+ sizeX: null,
584
+ sizeY: null,
585
+ pixelDepth: null,
586
+ resolutionX: null,
587
+ resolutionY: null,
588
+ currentResX: null,
589
+ currentResY: null,
590
+ positionX: 0,
591
+ positionY: 0,
592
+ currentRefreshRate: null
593
+ };
594
+ let is_edid = false;
595
+ let is_current = false;
596
+ let edid_raw = '';
597
+ let start = 0;
598
+ for (let i = 1; i < lines.length; i++) { // start with second line
599
+ if ('' !== lines[i].trim()) {
600
+ if (' ' !== lines[i][0] && '\t' !== lines[i][0] && lines[i].toLowerCase().indexOf(' connected ') !== -1) { // first line of new entry
601
+ if (currentDisplay.model || currentDisplay.main || currentDisplay.builtin || currentDisplay.connection || currentDisplay.sizeX !== null || currentDisplay.pixelDepth !== null || currentDisplay.resolutionX !== null) { // push last display to array
602
+ displays.push(currentDisplay);
603
+ currentDisplay = {
604
+ vendor: '',
605
+ model: '',
606
+ main: false,
607
+ builtin: false,
608
+ connection: '',
609
+ sizeX: null,
610
+ sizeY: null,
611
+ pixelDepth: null,
612
+ resolutionX: null,
613
+ resolutionY: null,
614
+ currentResX: null,
615
+ currentResY: null,
616
+ positionX: 0,
617
+ positionY: 0,
618
+ currentRefreshRate: null
619
+ };
620
+ }
621
+ let parts = lines[i].split(' ');
622
+ currentDisplay.connection = parts[0];
623
+ currentDisplay.main = lines[i].toLowerCase().indexOf(' primary ') >= 0;
624
+ currentDisplay.builtin = (parts[0].toLowerCase().indexOf('edp') >= 0);
625
+ }
626
+
627
+ // try to read EDID information
628
+ if (is_edid) {
629
+ if (lines[i].search(/\S|$/) > start) {
630
+ edid_raw += lines[i].toLowerCase().trim();
631
+ } else {
632
+ // parsen EDID
633
+ let edid_decoded = parseLinesLinuxEdid(edid_raw);
634
+ currentDisplay.vendor = edid_decoded.vendor;
635
+ currentDisplay.model = edid_decoded.model;
636
+ currentDisplay.resolutionX = edid_decoded.resolutionX;
637
+ currentDisplay.resolutionY = edid_decoded.resolutionY;
638
+ currentDisplay.sizeX = edid_decoded.sizeX;
639
+ currentDisplay.sizeY = edid_decoded.sizeY;
640
+ currentDisplay.pixelDepth = depth;
641
+ is_edid = false;
642
+ }
643
+ }
644
+ if (lines[i].toLowerCase().indexOf('edid:') >= 0) {
645
+ is_edid = true;
646
+ start = lines[i].search(/\S|$/);
647
+ }
648
+ if (lines[i].toLowerCase().indexOf('*current') >= 0) {
649
+ const parts1 = lines[i].split('(');
650
+ if (parts1 && parts1.length > 1 && parts1[0].indexOf('x') >= 0) {
651
+ const resParts = parts1[0].trim().split('x');
652
+ currentDisplay.currentResX = util.toInt(resParts[0]);
653
+ currentDisplay.currentResY = util.toInt(resParts[1]);
654
+ }
655
+ is_current = true;
656
+ }
657
+ if (is_current && lines[i].toLowerCase().indexOf('clock') >= 0 && lines[i].toLowerCase().indexOf('hz') >= 0 && lines[i].toLowerCase().indexOf('v: height') >= 0) {
658
+ const parts1 = lines[i].split('clock');
659
+ if (parts1 && parts1.length > 1 && parts1[1].toLowerCase().indexOf('hz') >= 0) {
660
+ currentDisplay.currentRefreshRate = util.toInt(parts1[1]);
661
+ }
662
+ is_current = false;
663
+ }
664
+ }
665
+ }
666
+
667
+ // pushen displays
668
+ if (currentDisplay.model || currentDisplay.main || currentDisplay.builtin || currentDisplay.connection || currentDisplay.sizeX !== null || currentDisplay.pixelDepth !== null || currentDisplay.resolutionX !== null) { // still information there
669
+ displays.push(currentDisplay);
670
+ }
671
+ return displays;
672
+ }
673
+
674
+ // function starts here
675
+ return new Promise((resolve) => {
676
+ process.nextTick(() => {
677
+ let result = {
678
+ controllers: [],
679
+ displays: []
680
+ };
681
+ if (_darwin) {
682
+ let cmd = 'system_profiler -xml -detailLevel full SPDisplaysDataType';
683
+ exec(cmd, function (error, stdout) {
684
+ if (!error) {
685
+ try {
686
+ const output = stdout.toString();
687
+ result = parseLinesDarwin(util.plistParser(output)[0]._items);
688
+ } catch (e) {
689
+ util.noop();
690
+ }
691
+ try {
692
+ 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 });
693
+ const output = (stdout || '').toString();
694
+ const obj = util.plistReader(output);
695
+ if (obj['DisplayAnyUserSets'] && obj['DisplayAnyUserSets']['Configs'] && obj['DisplayAnyUserSets']['Configs'][0] && obj['DisplayAnyUserSets']['Configs'][0]['DisplayConfig']) {
696
+ const current = obj['DisplayAnyUserSets']['Configs'][0]['DisplayConfig'];
697
+ let i = 0;
698
+ current.forEach((o) => {
699
+ if (o['CurrentInfo'] && o['CurrentInfo']['OriginX'] !== undefined && result.displays && result.displays[i]) {
700
+ result.displays[i].positionX = o['CurrentInfo']['OriginX'];
701
+ }
702
+ if (o['CurrentInfo'] && o['CurrentInfo']['OriginY'] !== undefined && result.displays && result.displays[i]) {
703
+ result.displays[i].positionY = o['CurrentInfo']['OriginY'];
704
+ }
705
+ i++;
706
+ });
707
+ }
708
+ if (obj['DisplayAnyUserSets'] && obj['DisplayAnyUserSets'].length > 0 && obj['DisplayAnyUserSets'][0].length > 0 && obj['DisplayAnyUserSets'][0][0]['DisplayID']) {
709
+ const current = obj['DisplayAnyUserSets'][0];
710
+ let i = 0;
711
+ current.forEach((o) => {
712
+ if ('OriginX' in o && result.displays && result.displays[i]) {
713
+ result.displays[i].positionX = o['OriginX'];
714
+ }
715
+ if ('OriginY' in o && result.displays && result.displays[i]) {
716
+ result.displays[i].positionY = o['OriginY'];
717
+ }
718
+ if (o['Mode'] && o['Mode']['BitsPerPixel'] !== undefined && result.displays && result.displays[i]) {
719
+ result.displays[i].pixelDepth = o['Mode']['BitsPerPixel'];
720
+ }
721
+ i++;
722
+ });
723
+ }
724
+ } catch (e) {
725
+ util.noop();
726
+ }
727
+ }
728
+ if (callback) {
729
+ callback(result);
730
+ }
731
+ resolve(result);
732
+ });
733
+ }
734
+ if (_linux) {
735
+ // Raspberry: https://elinux.org/RPI_vcgencmd_usage
736
+ if (util.isRaspberry() && util.isRaspbian()) {
737
+ let cmd = 'fbset -s | grep \'mode "\'; vcgencmd get_mem gpu; tvservice -s; tvservice -n;';
738
+ exec(cmd, function (error, stdout) {
739
+ let lines = stdout.toString().split('\n');
740
+ if (lines.length > 3 && lines[0].indexOf('mode "') >= -1 && lines[2].indexOf('0x12000a') > -1) {
741
+ const parts = lines[0].replace('mode', '').replace(/"/g, '').trim().split('x');
742
+ if (parts.length === 2) {
743
+ result.displays.push({
744
+ vendor: '',
745
+ model: util.getValue(lines, 'device_name', '='),
746
+ main: true,
747
+ builtin: false,
748
+ connection: 'HDMI',
749
+ sizeX: null,
750
+ sizeY: null,
751
+ pixelDepth: null,
752
+ resolutionX: parseInt(parts[0], 10),
753
+ resolutionY: parseInt(parts[1], 10),
754
+ currentResX: null,
755
+ currentResY: null,
756
+ positionX: 0,
757
+ positionY: 0,
758
+ currentRefreshRate: null
759
+ });
760
+ }
761
+ }
762
+ if (lines.length > 1 && stdout.toString().indexOf('gpu=') >= -1) {
763
+ result.controllers.push({
764
+ vendor: 'Broadcom',
765
+ model: util.getRpiGpu(),
766
+ bus: '',
767
+ vram: util.getValue(lines, 'gpu', '=').replace('M', ''),
768
+ vramDynamic: true
769
+ });
770
+ }
771
+ if (callback) {
772
+ callback(result);
773
+ }
774
+ resolve(result);
775
+ });
776
+ } else {
777
+ let cmd = 'lspci -vvv 2>/dev/null';
778
+ exec(cmd, function (error, stdout) {
779
+ if (!error) {
780
+ let lines = stdout.toString().split('\n');
781
+ result.controllers = parseLinesLinuxControllers(lines);
782
+ const nvidiaData = nvidiaDevices();
783
+ // needs to be rewritten ... using no spread operators
784
+ result.controllers = result.controllers.map((controller) => { // match by busAddress
785
+ return mergeControllerNvidia(controller, nvidiaData.find((contr) => contr.pciBus.toLowerCase().endsWith(controller.busAddress.toLowerCase())) || {});
786
+ });
787
+ }
788
+ let cmd = 'clinfo --raw';
789
+ exec(cmd, function (error, stdout) {
790
+ if (!error) {
791
+ let lines = stdout.toString().split('\n');
792
+ result.controllers = parseLinesLinuxClinfo(result.controllers, lines);
793
+ }
794
+ let cmd = 'xdpyinfo 2>/dev/null | grep \'depth of root window\' | awk \'{ print $5 }\'';
795
+ exec(cmd, function (error, stdout) {
796
+ let depth = 0;
797
+ if (!error) {
798
+ let lines = stdout.toString().split('\n');
799
+ depth = parseInt(lines[0]) || 0;
800
+ }
801
+ let cmd = 'xrandr --verbose 2>/dev/null';
802
+ exec(cmd, function (error, stdout) {
803
+ if (!error) {
804
+ let lines = stdout.toString().split('\n');
805
+ result.displays = parseLinesLinuxDisplays(lines, depth);
806
+ }
807
+ if (callback) {
808
+ callback(result);
809
+ }
810
+ resolve(result);
811
+ });
812
+ });
813
+ });
814
+ });
815
+ }
816
+ }
817
+ if (_freebsd || _openbsd || _netbsd) {
818
+ if (callback) { callback(null); }
819
+ resolve(null);
820
+ }
821
+ if (_sunos) {
822
+ if (callback) { callback(null); }
823
+ resolve(null);
824
+ }
825
+ if (_windows) {
826
+
827
+ // https://blogs.technet.microsoft.com/heyscriptingguy/2013/10/03/use-powershell-to-discover-multi-monitor-information/
828
+ // https://devblogs.microsoft.com/scripting/use-powershell-to-discover-multi-monitor-information/
829
+ try {
830
+ const workload = [];
831
+ workload.push(util.powerShell('Get-CimInstance win32_VideoController | fl *'));
832
+ 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'));
833
+ workload.push(util.powerShell('Get-CimInstance win32_desktopmonitor | fl *'));
834
+ workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorBasicDisplayParams | fl'));
835
+ workload.push(util.powerShell('Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::AllScreens'));
836
+ workload.push(util.powerShell('Get-CimInstance -Namespace root\\wmi -ClassName WmiMonitorConnectionParams | fl'));
837
+ 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}'));
838
+
839
+ const nvidiaData = nvidiaDevices();
840
+
841
+ Promise.all(
842
+ workload
843
+ ).then((data) => {
844
+ // controller + vram
845
+ let csections = data[0].replace(/\r/g, '').split(/\n\s*\n/);
846
+ let vsections = data[1].replace(/\r/g, '').split(/\n\s*\n/);
847
+ result.controllers = parseLinesWindowsControllers(csections, vsections);
848
+ result.controllers = result.controllers.map((controller) => { // match by subDeviceId
849
+ if (controller.vendor.toLowerCase() === 'nvidia') {
850
+ return mergeControllerNvidia(controller, nvidiaData.find(device => {
851
+ let windowsSubDeviceId = (controller.subDeviceId || '').toLowerCase();
852
+ const nvidiaSubDeviceIdParts = device.subDeviceId.split('x');
853
+ let nvidiaSubDeviceId = nvidiaSubDeviceIdParts.length > 1 ? nvidiaSubDeviceIdParts[1].toLowerCase() : nvidiaSubDeviceIdParts[0].toLowerCase();
854
+ const lengthDifference = Math.abs(windowsSubDeviceId.length - nvidiaSubDeviceId.length);
855
+ if (windowsSubDeviceId.length > nvidiaSubDeviceId.length) {
856
+ for (let i = 0; i < lengthDifference; i++) {
857
+ nvidiaSubDeviceId = '0' + nvidiaSubDeviceId;
858
+ }
859
+ } else if (windowsSubDeviceId.length < nvidiaSubDeviceId.length) {
860
+ for (let i = 0; i < lengthDifference; i++) {
861
+ windowsSubDeviceId = '0' + windowsSubDeviceId;
862
+ }
863
+ }
864
+ return windowsSubDeviceId === nvidiaSubDeviceId;
865
+ }) || {});
866
+ } else {
867
+ return controller;
868
+ }
869
+ });
870
+
871
+ // displays
872
+ let dsections = data[2].replace(/\r/g, '').split(/\n\s*\n/);
873
+ // result.displays = parseLinesWindowsDisplays(dsections);
874
+ if (dsections[0].trim() === '') { dsections.shift(); }
875
+ if (dsections.length && dsections[dsections.length - 1].trim() === '') { dsections.pop(); }
876
+
877
+ // monitor (powershell)
878
+ let msections = data[3].replace(/\r/g, '').split('Active ');
879
+ msections.shift();
880
+
881
+ // forms.screens (powershell)
882
+ let ssections = data[4].replace(/\r/g, '').split('BitsPerPixel ');
883
+ ssections.shift();
884
+
885
+ // connection params (powershell) - video type
886
+ let tsections = data[5].replace(/\r/g, '').split(/\n\s*\n/);
887
+ tsections.shift();
888
+
889
+ // monitor ID (powershell) - model / vendor
890
+ const res = data[6].replace(/\r/g, '').split(/\n/);
891
+ let isections = [];
892
+ res.forEach(element => {
893
+ const parts = element.split('|');
894
+ if (parts.length === 5) {
895
+ isections.push({
896
+ vendor: parts[0],
897
+ code: parts[1],
898
+ model: parts[2],
899
+ serial: parts[3],
900
+ instanceId: parts[4]
901
+ });
902
+ }
903
+ });
904
+
905
+ result.displays = parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections);
906
+
907
+ if (result.displays.length === 1) {
908
+ if (_resolutionX) {
909
+ result.displays[0].resolutionX = _resolutionX;
910
+ if (!result.displays[0].currentResX) {
911
+ result.displays[0].currentResX = _resolutionX;
912
+ }
913
+ }
914
+ if (_resolutionY) {
915
+ result.displays[0].resolutionY = _resolutionY;
916
+ if (result.displays[0].currentResY === 0) {
917
+ result.displays[0].currentResY = _resolutionY;
918
+ }
919
+ }
920
+ if (_pixelDepth) {
921
+ result.displays[0].pixelDepth = _pixelDepth;
922
+ }
923
+ }
924
+ result.displays = result.displays.map(element => {
925
+ if (_refreshRate && !element.currentRefreshRate) {
926
+ element.currentRefreshRate = _refreshRate;
927
+ }
928
+ return element;
929
+ });
930
+
931
+ if (callback) {
932
+ callback(result);
933
+ }
934
+ resolve(result);
935
+ })
936
+ .catch(() => {
937
+ if (callback) {
938
+ callback(result);
939
+ }
940
+ resolve(result);
941
+ });
942
+ } catch (e) {
943
+ if (callback) { callback(result); }
944
+ resolve(result);
945
+ }
946
+ }
947
+ });
948
+ });
949
+
950
+ function parseLinesWindowsControllers(sections, vections) {
951
+ const memorySizes = {};
952
+ for (const i in vections) {
953
+ if ({}.hasOwnProperty.call(vections, i)) {
954
+ if (vections[i].trim() !== '') {
955
+ const lines = vections[i].trim().split('\n');
956
+ const matchingDeviceId = util.getValue(lines, 'MatchingDeviceId').match(/PCI\\(VEN_[0-9A-F]{4})&(DEV_[0-9A-F]{4})(?:&(SUBSYS_[0-9A-F]{8}))?(?:&(REV_[0-9A-F]{2}))?/i);
957
+ if (matchingDeviceId) {
958
+ const quadWordmemorySize = parseInt(util.getValue(lines, 'HardwareInformation.qwMemorySize'));
959
+ if (!isNaN(quadWordmemorySize)) {
960
+ let deviceId = matchingDeviceId[1].toUpperCase() + '&' + matchingDeviceId[2].toUpperCase();
961
+ if (matchingDeviceId[3]) {
962
+ deviceId += '&' + matchingDeviceId[3].toUpperCase();
963
+ }
964
+ if (matchingDeviceId[4]) {
965
+ deviceId += '&' + matchingDeviceId[4].toUpperCase();
966
+ }
967
+ memorySizes[deviceId] = quadWordmemorySize;
968
+ }
969
+ }
970
+ }
971
+ }
972
+ }
973
+
974
+ let controllers = [];
975
+ for (let i in sections) {
976
+ if ({}.hasOwnProperty.call(sections, i)) {
977
+ if (sections[i].trim() !== '') {
978
+ let lines = sections[i].trim().split('\n');
979
+ 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);
980
+ let subDeviceId = null;
981
+ let memorySize = null;
982
+ if (pnpDeviceId) {
983
+ subDeviceId = pnpDeviceId[3] || '';
984
+ if (subDeviceId) {
985
+ subDeviceId = subDeviceId.split('_')[1];
986
+ }
987
+
988
+ // Match PCI device identifier (there's an order of increasing generality):
989
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-pci-devices
990
+
991
+ // PCI\VEN_v(4)&DEV_d(4)&SUBSYS_s(4)n(4)&REV_r(2)
992
+ if (memorySize == null && pnpDeviceId[3] && pnpDeviceId[4]) {
993
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[3].toUpperCase() + '&' + pnpDeviceId[4].toUpperCase();
994
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
995
+ memorySize = memorySizes[deviceId];
996
+ }
997
+ }
998
+
999
+ // PCI\VEN_v(4)&DEV_d(4)&SUBSYS_s(4)n(4)
1000
+ if (memorySize == null && pnpDeviceId[3]) {
1001
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[3].toUpperCase();
1002
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
1003
+ memorySize = memorySizes[deviceId];
1004
+ }
1005
+ }
1006
+
1007
+ // PCI\VEN_v(4)&DEV_d(4)&REV_r(2)
1008
+ if (memorySize == null && pnpDeviceId[4]) {
1009
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase() + '&' + pnpDeviceId[4].toUpperCase();
1010
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
1011
+ memorySize = memorySizes[deviceId];
1012
+ }
1013
+ }
1014
+
1015
+ // PCI\VEN_v(4)&DEV_d(4)
1016
+ if (memorySize == null) {
1017
+ const deviceId = pnpDeviceId[1].toUpperCase() + '&' + pnpDeviceId[2].toUpperCase();
1018
+ if ({}.hasOwnProperty.call(memorySizes, deviceId)) {
1019
+ memorySize = memorySizes[deviceId];
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ controllers.push({
1025
+ vendor: util.getValue(lines, 'AdapterCompatibility', ':'),
1026
+ model: util.getValue(lines, 'name', ':'),
1027
+ bus: util.getValue(lines, 'PNPDeviceID', ':').startsWith('PCI') ? 'PCI' : '',
1028
+ vram: (memorySize == null ? util.toInt(util.getValue(lines, 'AdapterRAM', ':')) : memorySize) / 1024 / 1024,
1029
+ vramDynamic: (util.getValue(lines, 'VideoMemoryType', ':') === '2'),
1030
+ subDeviceId
1031
+ });
1032
+ _resolutionX = util.toInt(util.getValue(lines, 'CurrentHorizontalResolution', ':')) || _resolutionX;
1033
+ _resolutionY = util.toInt(util.getValue(lines, 'CurrentVerticalResolution', ':')) || _resolutionY;
1034
+ _refreshRate = util.toInt(util.getValue(lines, 'CurrentRefreshRate', ':')) || _refreshRate;
1035
+ _pixelDepth = util.toInt(util.getValue(lines, 'CurrentBitsPerPixel', ':')) || _pixelDepth;
1036
+ }
1037
+ }
1038
+ }
1039
+ return controllers;
1040
+ }
1041
+
1042
+ function parseLinesWindowsDisplaysPowershell(ssections, msections, dsections, tsections, isections) {
1043
+ let displays = [];
1044
+ let vendor = '';
1045
+ let model = '';
1046
+ let deviceID = '';
1047
+ let resolutionX = 0;
1048
+ let resolutionY = 0;
1049
+ if (dsections && dsections.length) {
1050
+ let linesDisplay = dsections[0].split('\n');
1051
+ vendor = util.getValue(linesDisplay, 'MonitorManufacturer', ':');
1052
+ model = util.getValue(linesDisplay, 'Name', ':');
1053
+ deviceID = util.getValue(linesDisplay, 'PNPDeviceID', ':').replace(/&amp;/g, '&').toLowerCase();
1054
+ resolutionX = util.toInt(util.getValue(linesDisplay, 'ScreenWidth', ':'));
1055
+ resolutionY = util.toInt(util.getValue(linesDisplay, 'ScreenHeight', ':'));
1056
+ }
1057
+ for (let i = 0; i < ssections.length; i++) {
1058
+ if (ssections[i].trim() !== '') {
1059
+ ssections[i] = 'BitsPerPixel ' + ssections[i];
1060
+ msections[i] = 'Active ' + msections[i];
1061
+ // tsections can be empty OR undefined on earlier versions of powershell (<=2.0)
1062
+ // Tag connection type as UNKNOWN by default if this information is missing
1063
+ if (tsections.length === 0 || tsections[i] === undefined) {
1064
+ tsections[i] = 'Unknown';
1065
+ }
1066
+ let linesScreen = ssections[i].split('\n');
1067
+ let linesMonitor = msections[i].split('\n');
1068
+
1069
+ let linesConnection = tsections[i].split('\n');
1070
+ const bitsPerPixel = util.getValue(linesScreen, 'BitsPerPixel');
1071
+ const bounds = util.getValue(linesScreen, 'Bounds').replace('{', '').replace('}', '').replace(/=/g, ':').split(',');
1072
+ const primary = util.getValue(linesScreen, 'Primary');
1073
+ const sizeX = util.getValue(linesMonitor, 'MaxHorizontalImageSize');
1074
+ const sizeY = util.getValue(linesMonitor, 'MaxVerticalImageSize');
1075
+ const instanceName = util.getValue(linesMonitor, 'InstanceName').toLowerCase();
1076
+ const videoOutputTechnology = util.getValue(linesConnection, 'VideoOutputTechnology');
1077
+ const deviceName = util.getValue(linesScreen, 'DeviceName');
1078
+ let displayVendor = '';
1079
+ let displayModel = '';
1080
+ isections.forEach(element => {
1081
+ if (element.instanceId.toLowerCase().startsWith(instanceName) && vendor.startsWith('(') && model.startsWith('PnP')) {
1082
+ displayVendor = element.vendor;
1083
+ displayModel = element.model;
1084
+ }
1085
+ });
1086
+ displays.push({
1087
+ vendor: instanceName.startsWith(deviceID) && displayVendor === '' ? vendor : displayVendor,
1088
+ model: instanceName.startsWith(deviceID) && displayModel === '' ? model : displayModel,
1089
+ deviceName,
1090
+ main: primary.toLowerCase() === 'true',
1091
+ builtin: videoOutputTechnology === '2147483648',
1092
+ connection: videoOutputTechnology && videoTypes[videoOutputTechnology] ? videoTypes[videoOutputTechnology] : '',
1093
+ resolutionX: util.toInt(util.getValue(bounds, 'Width', ':')),
1094
+ resolutionY: util.toInt(util.getValue(bounds, 'Height', ':')),
1095
+ sizeX: sizeX ? parseInt(sizeX, 10) : null,
1096
+ sizeY: sizeY ? parseInt(sizeY, 10) : null,
1097
+ pixelDepth: bitsPerPixel,
1098
+ currentResX: util.toInt(util.getValue(bounds, 'Width', ':')),
1099
+ currentResY: util.toInt(util.getValue(bounds, 'Height', ':')),
1100
+ positionX: util.toInt(util.getValue(bounds, 'X', ':')),
1101
+ positionY: util.toInt(util.getValue(bounds, 'Y', ':')),
1102
+ });
1103
+ }
1104
+ }
1105
+ if (ssections.length === 0) {
1106
+ displays.push({
1107
+ vendor,
1108
+ model,
1109
+ main: true,
1110
+ sizeX: null,
1111
+ sizeY: null,
1112
+ resolutionX,
1113
+ resolutionY,
1114
+ pixelDepth: null,
1115
+ currentResX: resolutionX,
1116
+ currentResY: resolutionY,
1117
+ positionX: 0,
1118
+ positionY: 0
1119
+ });
1120
+ }
1121
+ return displays;
1122
+ }
1123
+ }
1124
+
1125
+ exports.graphics = graphics;