code-poltergeist-system-monitor 1.0.6

Sign up to get free protection for your applications and to get access to all the features.

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;