computer-identifiers.js 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. /*
  2. Copyright 2019-2021 Intel Corporation
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. function trimIdentifiers(val)
  14. {
  15. for(var v in val)
  16. {
  17. if (!val[v] || val[v] == 'None' || val[v] == '' || val[v].trim() == '') { delete val[v]; }
  18. }
  19. }
  20. function trimResults(val)
  21. {
  22. var i, x;
  23. for (i = 0; i < val.length; ++i)
  24. {
  25. for (x in val[i])
  26. {
  27. if (x.startsWith('_'))
  28. {
  29. delete val[i][x];
  30. }
  31. else
  32. {
  33. if (val[i][x] == null || val[i][x] == 0)
  34. {
  35. delete val[i][x];
  36. }
  37. }
  38. }
  39. }
  40. }
  41. function brief(headers, obj)
  42. {
  43. var i, x;
  44. for (x = 0; x < obj.length; ++x)
  45. {
  46. for (i in obj[x])
  47. {
  48. if (!headers.includes(i))
  49. {
  50. delete obj[x][i];
  51. }
  52. }
  53. }
  54. return (obj);
  55. }
  56. function dataHandler(c)
  57. {
  58. this.str += c.toString();
  59. }
  60. function linux_identifiers()
  61. {
  62. var identifiers = {};
  63. var ret = {};
  64. var values = {};
  65. if (!require('fs').existsSync('/sys/class/dmi/id')) {
  66. if (require('fs').existsSync('/sys/firmware/devicetree/base/model')) {
  67. if (require('fs').readFileSync('/sys/firmware/devicetree/base/model').toString().trim().startsWith('Raspberry')) {
  68. identifiers['board_vendor'] = 'Raspberry Pi';
  69. identifiers['board_name'] = require('fs').readFileSync('/sys/firmware/devicetree/base/model').toString().trim();
  70. identifiers['board_serial'] = require('fs').readFileSync('/sys/firmware/devicetree/base/serial-number').toString().trim();
  71. const memorySlots = [];
  72. var child = require('child_process').execFile('/bin/sh', ['sh']);
  73. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  74. child.stdin.write('vcgencmd get_mem arm && vcgencmd get_mem gpu\nexit\n');
  75. child.waitExit();
  76. try {
  77. const lines = child.stdout.str.trim().split('\n');
  78. if (lines.length == 2) {
  79. memorySlots.push({ Locator: "ARM Memory", Size: lines[0].split('=')[1].trim() })
  80. memorySlots.push({ Locator: "GPU Memory", Size: lines[1].split('=')[1].trim() })
  81. ret.memory = { Memory_Device: memorySlots };
  82. }
  83. } catch (xx) { }
  84. } else {
  85. throw('Unknown board');
  86. }
  87. } else {
  88. throw ('this platform does not have DMI statistics');
  89. }
  90. } else {
  91. var entries = require('fs').readdirSync('/sys/class/dmi/id');
  92. for (var i in entries) {
  93. if (require('fs').statSync('/sys/class/dmi/id/' + entries[i]).isFile()) {
  94. try {
  95. ret[entries[i]] = require('fs').readFileSync('/sys/class/dmi/id/' + entries[i]).toString().trim();
  96. } catch(z) { }
  97. if (ret[entries[i]] == 'None') { delete ret[entries[i]]; }
  98. }
  99. }
  100. entries = null;
  101. identifiers['bios_date'] = ret['bios_date'];
  102. identifiers['bios_vendor'] = ret['bios_vendor'];
  103. identifiers['bios_version'] = ret['bios_version'];
  104. identifiers['bios_serial'] = ret['product_serial'];
  105. identifiers['board_name'] = ret['board_name'];
  106. identifiers['board_serial'] = ret['board_serial'];
  107. identifiers['board_vendor'] = ret['board_vendor'];
  108. identifiers['board_version'] = ret['board_version'];
  109. identifiers['product_uuid'] = ret['product_uuid'];
  110. identifiers['product_name'] = ret['product_name'];
  111. }
  112. try {
  113. identifiers['bios_mode'] = (require('fs').statSync('/sys/firmware/efi').isDirectory() ? 'UEFI': 'Legacy');
  114. } catch (ex) { identifiers['bios_mode'] = 'Legacy'; }
  115. var child = require('child_process').execFile('/bin/sh', ['sh']);
  116. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  117. child.stdin.write('cat /proc/cpuinfo | grep -i "model name" | ' + "tr '\\n' ':' | awk -F: '{ print $2 }'\nexit\n");
  118. child.waitExit();
  119. identifiers['cpu_name'] = child.stdout.str.trim();
  120. if (identifiers['cpu_name'] == "") { // CPU BLANK, check lscpu instead
  121. child = require('child_process').execFile('/bin/sh', ['sh']);
  122. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  123. child.stdin.write('lscpu | grep -i "model name" | ' + "tr '\\n' ':' | awk -F: '{ print $2 }'\nexit\n");
  124. child.waitExit();
  125. identifiers['cpu_name'] = child.stdout.str.trim();
  126. }
  127. child = null;
  128. // Fetch GPU info
  129. child = require('child_process').execFile('/bin/sh', ['sh']);
  130. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  131. child.stdin.write("lspci | grep ' VGA ' | tr '\\n' '`' | awk '{ a=split($0,lines" + ',"`"); printf "["; for(i=1;i<a;++i) { split(lines[i],gpu,"r: "); printf "%s\\"%s\\"", (i==1?"":","),gpu[2]; } printf "]"; }\'\nexit\n');
  132. child.waitExit();
  133. try { identifiers['gpu_name'] = JSON.parse(child.stdout.str.trim()); } catch (xx) { }
  134. child = null;
  135. // Fetch Storage Info
  136. child = require('child_process').execFile('/bin/sh', ['sh']);
  137. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  138. child.stdin.write("lshw -class disk -disable network | tr '\\n' '`' | awk '" + '{ len=split($0,lines,"*"); printf "["; for(i=2;i<=len;++i) { model=""; caption=""; size=""; clen=split(lines[i],item,"`"); for(j=2;j<clen;++j) { split(item[j],tokens,":"); split(tokens[1],key," "); if(key[1]=="description") { caption=substr(tokens[2],2); } if(key[1]=="product") { model=substr(tokens[2],2); } if(key[1]=="size") { size=substr(tokens[2],2); } } if(model=="") { model=caption; } if(caption!="" || model!="") { printf "%s{\\"Caption\\":\\"%s\\",\\"Model\\":\\"%s\\",\\"Size\\":\\"%s\\"}",(i==2?"":","),caption,model,size; } } printf "]"; }\'\nexit\n');
  139. child.waitExit();
  140. try { identifiers['storage_devices'] = JSON.parse(child.stdout.str.trim()); } catch (xx) { }
  141. child = null;
  142. // Fetch storage volumes using df
  143. child = require('child_process').execFile('/bin/sh', ['sh']);
  144. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  145. child.stdin.write('df -T -x tmpfs -x devtmpfs -x efivarfs | awk \'NR==1 || $1 ~ ".+"{print $3, $4, $5, $7, $2}\' | awk \'NR>1 {printf "{\\"size\\":\\"%s\\",\\"used\\":\\"%s\\",\\"available\\":\\"%s\\",\\"mount_point\\":\\"%s\\",\\"type\\":\\"%s\\"},", $1, $2, $3, $4, $5}\' | sed \'$ s/,$//\' | awk \'BEGIN {printf "["} {printf "%s", $0} END {printf "]"}\'\nexit\n');
  146. child.waitExit();
  147. try { ret.volumes = JSON.parse(child.stdout.str.trim()); } catch (xx) { }
  148. child = null;
  149. values.identifiers = identifiers;
  150. values.linux = ret;
  151. trimIdentifiers(values.identifiers);
  152. var dmidecode = require('lib-finder').findBinary('dmidecode');
  153. if (dmidecode != null)
  154. {
  155. child = require('child_process').execFile('/bin/sh', ['sh']);
  156. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  157. child.stderr.str = ''; child.stderr.on('data', dataHandler);
  158. child.stdin.write(dmidecode + " -t memory | tr '\\n' '`' | ");
  159. child.stdin.write(" awk '{ ");
  160. child.stdin.write(' printf("[");');
  161. child.stdin.write(' comma="";');
  162. child.stdin.write(' c=split($0, lines, "``");');
  163. child.stdin.write(' for(i=1;i<=c;++i)');
  164. child.stdin.write(' {');
  165. child.stdin.write(' d=split(lines[i], val, "`");');
  166. child.stdin.write(' split(val[1], tokens, ",");');
  167. child.stdin.write(' split(tokens[2], dmitype, " ");');
  168. child.stdin.write(' dmi = dmitype[3]+0; ');
  169. child.stdin.write(' if(dmi == 5 || dmi == 6 || dmi == 16 || dmi == 17)');
  170. child.stdin.write(' {');
  171. child.stdin.write(' ccx="";');
  172. child.stdin.write(' printf("%s{\\"%s\\": {", comma, val[2]);');
  173. child.stdin.write(' for(j=3;j<d;++j)');
  174. child.stdin.write(' {');
  175. child.stdin.write(' sub(/^[ \\t]*/,"",val[j]);');
  176. child.stdin.write(' if(split(val[j],tmp,":")>1)');
  177. child.stdin.write(' {');
  178. child.stdin.write(' sub(/^[ \\t]*/,"",tmp[2]);');
  179. child.stdin.write(' gsub(/ /,"",tmp[1]);');
  180. child.stdin.write(' printf("%s\\"%s\\": \\"%s\\"", ccx, tmp[1], tmp[2]);');
  181. child.stdin.write(' ccx=",";');
  182. child.stdin.write(' }');
  183. child.stdin.write(' }');
  184. child.stdin.write(' printf("}}");');
  185. child.stdin.write(' comma=",";');
  186. child.stdin.write(' }');
  187. child.stdin.write(' }');
  188. child.stdin.write(' printf("]");');
  189. child.stdin.write("}'\nexit\n");
  190. child.waitExit();
  191. try
  192. {
  193. var j = JSON.parse(child.stdout.str);
  194. var i, key, key2;
  195. for (i = 0; i < j.length; ++i)
  196. {
  197. for (key in j[i])
  198. {
  199. delete j[i][key]['ArrayHandle'];
  200. delete j[i][key]['ErrorInformationHandle'];
  201. for (key2 in j[i][key])
  202. {
  203. if (j[i][key][key2] == 'Unknown' || j[i][key][key2] == 'Not Specified' || j[i][key][key2] == '')
  204. {
  205. delete j[i][key][key2];
  206. }
  207. }
  208. }
  209. }
  210. if(j.length > 0){
  211. var mem = {};
  212. for (i = 0; i < j.length; ++i)
  213. {
  214. for (key in j[i])
  215. {
  216. if (mem[key] == null) { mem[key] = []; }
  217. mem[key].push(j[i][key]);
  218. }
  219. }
  220. values.linux.memory = mem;
  221. }
  222. }
  223. catch (e)
  224. { }
  225. child = null;
  226. }
  227. var usbdevices = require('lib-finder').findBinary('usb-devices');
  228. if (usbdevices != null)
  229. {
  230. var child = require('child_process').execFile('/bin/sh', ['sh']);
  231. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  232. child.stderr.str = ''; child.stderr.on('data', dataHandler);
  233. child.stdin.write(usbdevices + " | tr '\\n' '`' | ");
  234. child.stdin.write(" awk '");
  235. child.stdin.write('{');
  236. child.stdin.write(' comma="";');
  237. child.stdin.write(' printf("[");');
  238. child.stdin.write(' len=split($0, group, "``");');
  239. child.stdin.write(' for(i=1;i<=len;++i)');
  240. child.stdin.write(' {');
  241. child.stdin.write(' comma2="";');
  242. child.stdin.write(' xlen=split(group[i], line, "`");');
  243. child.stdin.write(' scount=0;');
  244. child.stdin.write(' for(x=1;x<xlen;++x)');
  245. child.stdin.write(' {');
  246. child.stdin.write(' if(line[x] ~ "^S:")');
  247. child.stdin.write(' {');
  248. child.stdin.write(' ++scount;');
  249. child.stdin.write(' }');
  250. child.stdin.write(' }');
  251. child.stdin.write(' if(scount>0)');
  252. child.stdin.write(' {');
  253. child.stdin.write(' printf("%s{", comma); comma=",";');
  254. child.stdin.write(' for(x=1;x<xlen;++x)');
  255. child.stdin.write(' {');
  256. child.stdin.write(' if(line[x] ~ "^T:")');
  257. child.stdin.write(' {');
  258. child.stdin.write(' comma3="";');
  259. child.stdin.write(' printf("%s\\"hardware\\": {", comma2); comma2=",";');
  260. child.stdin.write(' sub(/^T:[ \\t]*/, "", line[x]);');
  261. child.stdin.write(' gsub(/= */, "=", line[x]);');
  262. child.stdin.write(' blen=split(line[x], tokens, " ");');
  263. child.stdin.write(' for(y=1;y<blen;++y)');
  264. child.stdin.write(' {');
  265. child.stdin.write(' match(tokens[y],/=/);');
  266. child.stdin.write(' h=substr(tokens[y],1,RSTART-1);');
  267. child.stdin.write(' v=substr(tokens[y],RSTART+1);');
  268. child.stdin.write(' sub(/#/, "", h);');
  269. child.stdin.write(' printf("%s\\"%s\\": \\"%s\\"", comma3, h, v); comma3=",";');
  270. child.stdin.write(' }');
  271. child.stdin.write(' printf("}");');
  272. child.stdin.write(' }');
  273. child.stdin.write(' if(line[x] ~ "^S:")');
  274. child.stdin.write(' {');
  275. child.stdin.write(' sub(/^S:[ \\t]*/, "", line[x]);');
  276. child.stdin.write(' match(line[x], /=/);');
  277. child.stdin.write(' h=substr(line[x],1,RSTART-1);');
  278. child.stdin.write(' v=substr(line[x],RSTART+1);');
  279. child.stdin.write(' printf("%s\\"%s\\": \\"%s\\"", comma2, h,v); comma2=",";');
  280. child.stdin.write(' }');
  281. child.stdin.write(' }');
  282. child.stdin.write(' printf("}");');
  283. child.stdin.write(' }');
  284. child.stdin.write(' }');
  285. child.stdin.write(' printf("]");');
  286. child.stdin.write("}'\nexit\n");
  287. child.waitExit();
  288. try
  289. {
  290. values.linux.usb = JSON.parse(child.stdout.str);
  291. }
  292. catch(x)
  293. { }
  294. child = null;
  295. }
  296. var pcidevices = require('lib-finder').findBinary('lspci');
  297. if (pcidevices != null)
  298. {
  299. var child = require('child_process').execFile('/bin/sh', ['sh']);
  300. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  301. child.stderr.str = ''; child.stderr.on('data', dataHandler);
  302. child.stdin.write(pcidevices + " -m | tr '\\n' '`' | ");
  303. child.stdin.write(" awk '");
  304. child.stdin.write('{');
  305. child.stdin.write(' printf("[");');
  306. child.stdin.write(' comma="";');
  307. child.stdin.write(' alen=split($0, lines, "`");');
  308. child.stdin.write(' for(a=1;a<alen;++a)');
  309. child.stdin.write(' {');
  310. child.stdin.write(' match(lines[a], / /);');
  311. child.stdin.write(' blen=split(lines[a], meta, "\\"");');
  312. child.stdin.write(' bus=substr(lines[a], 1, RSTART);');
  313. child.stdin.write(' gsub(/ /, "", bus);');
  314. child.stdin.write(' printf("%s{\\"bus\\": \\"%s\\"", comma, bus); comma=",";');
  315. child.stdin.write(' printf(", \\"device\\": \\"%s\\"", meta[2]);');
  316. child.stdin.write(' printf(", \\"manufacturer\\": \\"%s\\"", meta[4]);');
  317. child.stdin.write(' printf(", \\"description\\": \\"%s\\"", meta[6]);');
  318. child.stdin.write(' if(meta[8] != "")');
  319. child.stdin.write(' {');
  320. child.stdin.write(' printf(", \\"subsystem\\": {");');
  321. child.stdin.write(' printf("\\"manufacturer\\": \\"%s\\"", meta[8]);');
  322. child.stdin.write(' printf(", \\"description\\": \\"%s\\"", meta[10]);');
  323. child.stdin.write(' printf("}");');
  324. child.stdin.write(' }');
  325. child.stdin.write(' printf("}");');
  326. child.stdin.write(' }');
  327. child.stdin.write(' printf("]");');
  328. child.stdin.write("}'\nexit\n");
  329. child.waitExit();
  330. try
  331. {
  332. values.linux.pci = JSON.parse(child.stdout.str);
  333. }
  334. catch (x)
  335. { }
  336. child = null;
  337. }
  338. // Linux Last Boot Up Time
  339. try {
  340. child = require('child_process').execFile('/usr/bin/uptime', ['', '-s']); // must include blank value at begining for some reason?
  341. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  342. child.stderr.on('data', function () { });
  343. child.waitExit();
  344. var regex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
  345. if (regex.test(child.stdout.str.trim())) {
  346. values.linux.LastBootUpTime = child.stdout.str.trim();
  347. } else {
  348. child = require('child_process').execFile('/bin/sh', ['sh']);
  349. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  350. child.stdin.write('date -d "@$(( $(date +%s) - $(awk \'{print int($1)}\' /proc/uptime) ))" "+%Y-%m-%d %H:%M:%S"\nexit\n');
  351. child.waitExit();
  352. if (regex.test(child.stdout.str.trim())) {
  353. values.linux.LastBootUpTime = child.stdout.str.trim();
  354. }
  355. }
  356. child = null;
  357. } catch (ex) { }
  358. // Linux TPM
  359. try {
  360. if (require('fs').statSync('/sys/class/tpm/tpm0').isDirectory()){
  361. values.tpm = {
  362. SpecVersion: require('fs').readFileSync('/sys/class/tpm/tpm0/tpm_version_major').toString().trim()
  363. }
  364. }
  365. } catch (ex) { }
  366. // Linux Batteries
  367. try {
  368. var batteries = require('fs').readdirSync('/sys/class/power_supply/');
  369. if (batteries.length != 0) {
  370. values.battery = [];
  371. for (var i in batteries) {
  372. const filesToRead = [
  373. 'capacity', 'cycle_count', 'energy_full', 'energy_full_design',
  374. 'energy_now', 'manufacturer', 'model_name', 'power_now',
  375. 'serial_number', 'status', 'technology', 'voltage_now'
  376. ];
  377. const thedata = {};
  378. for (var x in filesToRead) {
  379. try {
  380. const content = require('fs').readFileSync('/sys/class/power_supply/' + batteries[i] + '/' + filesToRead[x]).toString().trim();
  381. thedata[filesToRead[x]] = /^\d+$/.test(content) ? parseInt(content, 10) : content;
  382. } catch (err) { }
  383. }
  384. if (Object.keys(thedata).length === 0) continue; // No data read, skip
  385. const status = (thedata.status || '').toLowerCase();
  386. const isCharging = status === 'charging';
  387. const isDischarging = status === 'discharging';
  388. const toMilli = function (val) { return Math.round((val || 0) / 1000) }; // Convert from µ units to m units (divide by 1000)
  389. const batteryJson = {
  390. "InstanceName": batteries[i],
  391. "CycleCount": thedata.cycle_count || 0,
  392. "FullChargedCapacity": toMilli(thedata.energy_full),
  393. "Chemistry": (thedata.technology || ''),
  394. "DesignedCapacity": toMilli(thedata.energy_full_design),
  395. "DeviceName": thedata.model_name || "Battery",
  396. "ManufactureName": thedata.manufacturer || "Unknown",
  397. "SerialNumber": thedata.serial_number || "unknown",
  398. "ChargeRate": isCharging ? toMilli(thedata.power_now) : 0,
  399. "Charging": isCharging,
  400. "DischargeRate": isDischarging ? toMilli(thedata.power_now) : 0,
  401. "Discharging": isDischarging,
  402. "RemainingCapacity": toMilli(thedata.energy_now),
  403. "Voltage": toMilli(thedata.voltage_now),
  404. "Health": (thedata.energy_full && thedata.energy_full_design ? Math.floor((thedata.energy_full / thedata.energy_full_design) * 100) : 0),
  405. "BatteryCharge": (thedata.energy_now && thedata.energy_full ? Math.floor((thedata.energy_now / thedata.energy_full) * 100) : 0)
  406. };
  407. values.battery.push(batteryJson);
  408. }
  409. if (values.battery.length == 0) { delete values.battery; }
  410. }
  411. } catch (ex) { }
  412. return (values);
  413. }
  414. function windows_wmic_results(str)
  415. {
  416. var lines = str.trim().split('\r\n');
  417. var keys = lines[0].split(',');
  418. var i, key, keyval;
  419. var tokens;
  420. var result = [];
  421. console.log('Lines: ' + lines.length, 'Keys: ' + keys.length);
  422. for (i = 1; i < lines.length; ++i)
  423. {
  424. var obj = {};
  425. console.log('i: ' + i);
  426. tokens = lines[i].split(',');
  427. for (key = 0; key < keys.length; ++key)
  428. {
  429. var tmp = Buffer.from(tokens[key], 'binary').toString();
  430. console.log(tokens[key], tmp);
  431. tokens[key] = tmp == null ? '' : tmp;
  432. if (tokens[key].trim())
  433. {
  434. obj[keys[key].trim()] = tokens[key].trim();
  435. }
  436. }
  437. delete obj.Node;
  438. result.push(obj);
  439. }
  440. return (result);
  441. }
  442. function windows_identifiers()
  443. {
  444. var ret = { windows: {} };
  445. var items, item, i;
  446. ret['identifiers'] = {};
  447. var values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_Bios", ['ReleaseDate', 'Manufacturer', 'SMBIOSBIOSVersion', 'SerialNumber']);
  448. if(values[0]){
  449. ret['identifiers']['bios_date'] = values[0]['ReleaseDate'];
  450. ret['identifiers']['bios_vendor'] = values[0]['Manufacturer'];
  451. ret['identifiers']['bios_version'] = values[0]['SMBIOSBIOSVersion'];
  452. ret['identifiers']['bios_serial'] = values[0]['SerialNumber'];
  453. }
  454. ret['identifiers']['bios_mode'] = 'Legacy';
  455. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_BaseBoard", ['Product', 'SerialNumber', 'Manufacturer', 'Version']);
  456. if(values[0]){
  457. ret['identifiers']['board_name'] = values[0]['Product'];
  458. ret['identifiers']['board_serial'] = values[0]['SerialNumber'];
  459. ret['identifiers']['board_vendor'] = values[0]['Manufacturer'];
  460. ret['identifiers']['board_version'] = values[0]['Version'];
  461. }
  462. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_ComputerSystemProduct", ['UUID', 'Name']);
  463. if(values[0]){
  464. ret['identifiers']['product_uuid'] = values[0]['UUID'];
  465. ret['identifiers']['product_name'] = values[0]['Name'];
  466. }
  467. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_SystemEnclosure", ['SerialNumber', 'SMBIOSAssetTag', 'Manufacturer']);
  468. if(values[0]){
  469. ret['identifiers']['chassis_serial'] = values[0]['SerialNumber'];
  470. ret['identifiers']['chassis_assettag'] = values[0]['SMBIOSAssetTag'];
  471. ret['identifiers']['chassis_manufacturer'] = values[0]['Manufacturer'];
  472. }
  473. trimIdentifiers(ret.identifiers);
  474. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_PhysicalMemory");
  475. if(values[0]){
  476. trimResults(values);
  477. ret.windows.memory = values;
  478. }
  479. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_OperatingSystem");
  480. if(values[0]){
  481. trimResults(values);
  482. ret.windows.osinfo = values[0];
  483. }
  484. values = require('win-wmi-fixed').query('ROOT\\CIMV2', "SELECT * FROM Win32_DiskPartition");
  485. if(values[0]){
  486. trimResults(values);
  487. ret.windows.partitions = values;
  488. for (var i in values) {
  489. if (values[i].Type=='GPT: System') {
  490. ret['identifiers']['bios_mode'] = 'UEFI';
  491. }
  492. }
  493. }
  494. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_Processor", ['Caption', 'DeviceID', 'Manufacturer', 'MaxClockSpeed', 'Name', 'SocketDesignation']);
  495. if(values[0]){
  496. ret.windows.cpu = values;
  497. }
  498. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_VideoController", ['Name', 'CurrentHorizontalResolution', 'CurrentVerticalResolution']);
  499. if(values[0]){
  500. ret.windows.gpu = values;
  501. }
  502. values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_DiskDrive", ['Caption', 'DeviceID', 'Model', 'Partitions', 'Size', 'Status']);
  503. if(values[0]){
  504. ret.windows.drives = values;
  505. }
  506. // Insert GPU names
  507. ret.identifiers.gpu_name = [];
  508. for (var gpuinfo in ret.windows.gpu)
  509. {
  510. if (ret.windows.gpu[gpuinfo].Name) { ret.identifiers.gpu_name.push(ret.windows.gpu[gpuinfo].Name); }
  511. }
  512. // Insert Storage Devices
  513. ret.identifiers.storage_devices = [];
  514. for (var dv in ret.windows.drives)
  515. {
  516. ret.identifiers.storage_devices.push({ Caption: ret.windows.drives[dv].Caption, Model: ret.windows.drives[dv].Model, Size: ret.windows.drives[dv].Size });
  517. }
  518. try { ret.identifiers.cpu_name = ret.windows.cpu[0].Name; } catch (x) { }
  519. // Windows TPM
  520. IntToStr = function (v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); };
  521. try {
  522. values = require('win-wmi').query('ROOT\\CIMV2\\Security\\MicrosoftTpm', "SELECT * FROM Win32_Tpm", ['IsActivated_InitialValue','IsEnabled_InitialValue','IsOwned_InitialValue','ManufacturerId','ManufacturerVersion','SpecVersion']);
  523. if(values[0]) {
  524. ret.tpm = {
  525. SpecVersion: values[0].SpecVersion.split(",")[0],
  526. ManufacturerId: IntToStr(values[0].ManufacturerId).replace(/[^\x00-\x7F]/g, ""),
  527. ManufacturerVersion: values[0].ManufacturerVersion,
  528. IsActivated: values[0].IsActivated_InitialValue,
  529. IsEnabled: values[0].IsEnabled_InitialValue,
  530. IsOwned: values[0].IsOwned_InitialValue,
  531. }
  532. }
  533. } catch (ex) { }
  534. // Windows Batteries
  535. IntToStrLE = function (v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF); };
  536. try {
  537. function mergeJSONArrays() {
  538. var resultMap = {};
  539. var result = [];
  540. // Loop through all arguments (arrays)
  541. for (var i = 0; i < arguments.length; i++) {
  542. var currentArray = arguments[i];
  543. // Skip if not an array
  544. if (!currentArray || currentArray.constructor !== Array) {
  545. continue;
  546. }
  547. // Process each object in the array
  548. for (var j = 0; j < currentArray.length; j++) {
  549. var obj = currentArray[j];
  550. // Skip if not an object or missing InstanceName
  551. if (!obj || typeof obj !== 'object' || !obj.InstanceName) {
  552. continue;
  553. }
  554. var name = obj.InstanceName;
  555. // Create new entry if it doesn't exist
  556. if (!resultMap[name]) {
  557. resultMap[name] = { InstanceName: name };
  558. result.push(resultMap[name]);
  559. }
  560. // Copy all properties except InstanceName
  561. for (var key in obj) {
  562. if (obj.hasOwnProperty(key) && key !== 'InstanceName') {
  563. resultMap[name][key] = obj[key];
  564. }
  565. }
  566. }
  567. }
  568. return result;
  569. }
  570. values = require('win-wmi').query('ROOT\\WMI', "SELECT * FROM BatteryCycleCount",['InstanceName','CycleCount']);
  571. var values2 = require('win-wmi').query('ROOT\\WMI', "SELECT * FROM BatteryFullChargedCapacity",['InstanceName','FullChargedCapacity']);
  572. var values3 = require('win-wmi').query('ROOT\\WMI', "SELECT * FROM BatteryRuntime",['InstanceName','EstimatedRuntime']);
  573. var values4 = require('win-wmi').query('ROOT\\WMI', "SELECT * FROM BatteryStaticData",['InstanceName','Chemistry','DesignedCapacity','DeviceName','ManufactureDate','ManufactureName','SerialNumber']);
  574. for (i = 0; i < values4.length; ++i) {
  575. if (values4[i].Chemistry) { values4[i].Chemistry = IntToStrLE(parseInt(values4[i].Chemistry)); }
  576. if (values4[i].ManufactureDate) { if (values4[i].ManufactureDate.indexOf('*****') != -1) delete values4[i].ManufactureDate; }
  577. }
  578. var values5 = require('win-wmi').query('ROOT\\WMI', "SELECT * FROM BatteryStatus",['InstanceName','ChargeRate','Charging','DischargeRate','Discharging','RemainingCapacity','Voltage']);
  579. var values6 = [];
  580. if (values2.length > 0 && values4.length > 0) {
  581. for (i = 0; i < values2.length; ++i) {
  582. for (var j = 0; j < values4.length; ++j) {
  583. if (values2[i].InstanceName == values4[j].InstanceName) {
  584. if ((values4[j].DesignedCapacity && values4[j].DesignedCapacity > 0) && (values2[i].FullChargedCapacity && values2[i].FullChargedCapacity > 0)) {
  585. values6[i] = {
  586. Health: Math.floor((values2[i].FullChargedCapacity / values4[j].DesignedCapacity) * 100),
  587. InstanceName: values2[i].InstanceName
  588. };
  589. if (values6[i].Health > 100) { values6[i].Health = 100; }
  590. } else {
  591. values6[i] = { Health: 0, InstanceName: values2[i].InstanceName };
  592. }
  593. break;
  594. }
  595. }
  596. }
  597. }
  598. var values7 = [];
  599. if (values2.length > 0 && values5.length > 0) {
  600. for (i = 0; i < values2.length; ++i) {
  601. for (var j = 0; j < values5.length; ++j) {
  602. if (values2[i].InstanceName == values5[j].InstanceName) {
  603. if ((values2[i].FullChargedCapacity && values2[i].FullChargedCapacity > 0) && (values5[j].RemainingCapacity && values5[j].RemainingCapacity > 0)) {
  604. values7[i] = {
  605. BatteryCharge: Math.floor((values5[j].RemainingCapacity / values2[i].FullChargedCapacity) * 100),
  606. InstanceName: values2[i].InstanceName
  607. };
  608. } else {
  609. values7[i] = { BatteryCharge: 0, InstanceName: values2[i].InstanceName };
  610. }
  611. break;
  612. }
  613. }
  614. }
  615. }
  616. ret.battery = mergeJSONArrays(values, values2, values3, values4, values5, values6, values7);
  617. } catch (ex) { }
  618. return (ret);
  619. }
  620. function macos_identifiers()
  621. {
  622. var ret = { identifiers: {}, darwin: {} };
  623. var child;
  624. child = require('child_process').execFile('/bin/sh', ['sh']);
  625. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  626. child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep board-id | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
  627. child.waitExit();
  628. ret.identifiers.board_name = child.stdout.str.trim();
  629. child = require('child_process').execFile('/bin/sh', ['sh']);
  630. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  631. child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep IOPlatformSerialNumber | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
  632. child.waitExit();
  633. ret.identifiers.board_serial = child.stdout.str.trim();
  634. child = require('child_process').execFile('/bin/sh', ['sh']);
  635. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  636. child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep manufacturer | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
  637. child.waitExit();
  638. ret.identifiers.board_vendor = child.stdout.str.trim();
  639. child = require('child_process').execFile('/bin/sh', ['sh']);
  640. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  641. child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep version | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
  642. child.waitExit();
  643. ret.identifiers.board_version = child.stdout.str.trim();
  644. child = require('child_process').execFile('/bin/sh', ['sh']);
  645. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  646. child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
  647. child.waitExit();
  648. ret.identifiers.product_uuid = child.stdout.str.trim();
  649. child = require('child_process').execFile('/bin/sh', ['sh']);
  650. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  651. child.stdin.write('sysctl -n machdep.cpu.brand_string\nexit\n');
  652. child.waitExit();
  653. ret.identifiers.cpu_name = child.stdout.str.trim();
  654. child = require('child_process').execFile('/bin/sh', ['sh']);
  655. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  656. child.stdin.write('system_profiler SPMemoryDataType\nexit\n');
  657. child.waitExit();
  658. var lines = child.stdout.str.trim().split('\n');
  659. if(lines.length > 0) {
  660. const memorySlots = [];
  661. if(lines[2].trim().includes('Memory Slots:')) { // OLD MACS WITH SLOTS
  662. var memorySlots1 = child.stdout.str.split(/\n{2,}/).slice(3);
  663. memorySlots1.forEach(function(slot,index) {
  664. var lines = slot.split('\n');
  665. if(lines.length == 1){ // start here
  666. if(lines[0].trim()!=''){
  667. var slotObj = { DeviceLocator: lines[0].trim().replace(/:$/, '') }; // Initialize name as an empty string
  668. var nextline = memorySlots1[index+1].split('\n');
  669. nextline.forEach(function(line) {
  670. if (line.trim() !== '') {
  671. var parts = line.split(':');
  672. var key = parts[0].trim();
  673. var value = parts[1].trim();
  674. value = (key == 'Part Number' || key == 'Manufacturer') ? hexToAscii(parts[1].trim()) : parts[1].trim();
  675. slotObj[key.replace(' ','')] = value; // Store attribute in the slot object
  676. }
  677. });
  678. memorySlots.push(slotObj);
  679. }
  680. }
  681. });
  682. } else { // NEW MACS WITHOUT SLOTS
  683. memorySlots.push({ DeviceLocator: "Onboard Memory", Size: lines[2].split(":")[1].trim(), PartNumber: lines[3].split(":")[1].trim(), Manufacturer: lines[4].split(":")[1].trim() })
  684. }
  685. ret.darwin.memory = memorySlots;
  686. }
  687. child = require('child_process').execFile('/bin/sh', ['sh']);
  688. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  689. child.stdin.write('diskutil info -all\nexit\n');
  690. child.waitExit();
  691. var sections = child.stdout.str.split('**********\n');
  692. if(sections.length > 0){
  693. var devices = [];
  694. for (var i = 0; i < sections.length; i++) {
  695. var lines = sections[i].split('\n');
  696. var deviceInfo = {};
  697. var wholeYes = false;
  698. var physicalYes = false;
  699. var oldmac = false;
  700. for (var j = 0; j < lines.length; j++) {
  701. var keyValue = lines[j].split(':');
  702. var key = keyValue[0].trim();
  703. var value = keyValue[1] ? keyValue[1].trim() : '';
  704. if (key === 'Virtual') oldmac = true;
  705. if (key === 'Whole' && value === 'Yes') wholeYes = true;
  706. if (key === 'Virtual' && value === 'No') physicalYes = true;
  707. if(value && key === 'Device / Media Name'){
  708. deviceInfo['Caption'] = value;
  709. }
  710. if(value && key === 'Disk Size'){
  711. deviceInfo['Size'] = value.split(' ')[0] + ' ' + value.split(' ')[1];
  712. }
  713. }
  714. if (wholeYes) {
  715. if (oldmac) {
  716. if (physicalYes) devices.push(deviceInfo);
  717. } else {
  718. devices.push(deviceInfo);
  719. }
  720. }
  721. }
  722. ret.identifiers.storage_devices = devices;
  723. }
  724. // Fetch storage volumes using df
  725. child = require('child_process').execFile('/bin/sh', ['sh']);
  726. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  727. child.stdin.write('df -aHY | awk \'NR>1 {printf "{\\"size\\":\\"%s\\",\\"used\\":\\"%s\\",\\"available\\":\\"%s\\",\\"mount_point\\":\\"%s\\",\\"type\\":\\"%s\\"},", $3, $4, $5, $10, $2}\' | sed \'$ s/,$//\' | awk \'BEGIN {printf "["} {printf "%s", $0} END {printf "]"}\'\nexit\n');
  728. child.waitExit();
  729. try {
  730. ret.darwin.volumes = JSON.parse(child.stdout.str.trim());
  731. for (var index = 0; index < ret.darwin.volumes.length; index++) {
  732. if (ret.darwin.volumes[index].type == 'auto_home'){
  733. ret.darwin.volumes.splice(index,1);
  734. }
  735. }
  736. if (ret.darwin.volumes.length == 0) { // not sonima OS so dont show type for now
  737. child = require('child_process').execFile('/bin/sh', ['sh']);
  738. child.stdout.str = ''; child.stdout.on('data', dataHandler);
  739. child.stdin.write('df -aH | awk \'NR>1 {printf "{\\"size\\":\\"%s\\",\\"used\\":\\"%s\\",\\"available\\":\\"%s\\",\\"mount_point\\":\\"%s\\"},", $2, $3, $4, $9}\' | sed \'$ s/,$//\' | awk \'BEGIN {printf "["} {printf "%s", $0} END {printf "]"}\'\nexit\n');
  740. child.waitExit();
  741. try {
  742. ret.darwin.volumes = JSON.parse(child.stdout.str.trim());
  743. for (var index = 0; index < ret.darwin.volumes.length; index++) {
  744. if (ret.darwin.volumes[index].size == 'auto_home'){
  745. ret.darwin.volumes.splice(index,1);
  746. }
  747. }
  748. } catch (xx) { }
  749. }
  750. } catch (xx) { }
  751. child = null;
  752. // MacOS Last Boot Up Time
  753. try {
  754. child = require('child_process').execFile('/usr/sbin/sysctl', ['', 'kern.boottime']); // must include blank value at begining for some reason?
  755. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  756. child.stderr.on('data', function () { });
  757. child.waitExit();
  758. const timestampMatch = /\{ sec = (\d+), usec = \d+ \}/.exec(child.stdout.str.trim());
  759. if (!ret.darwin) {
  760. ret.darwin = { LastBootUpTime: parseInt(timestampMatch[1]) };
  761. } else {
  762. ret.darwin.LastBootUpTime = parseInt(timestampMatch[1]);
  763. }
  764. child = null;
  765. } catch (ex) { }
  766. trimIdentifiers(ret.identifiers);
  767. child = null;
  768. return (ret);
  769. }
  770. function hexToAscii(hexString) {
  771. if(!hexString.startsWith('0x')) return hexString.trim();
  772. hexString = hexString.startsWith('0x') ? hexString.slice(2) : hexString;
  773. var str = '';
  774. for (var i = 0; i < hexString.length; i += 2) {
  775. var hexPair = hexString.substr(i, 2);
  776. str += String.fromCharCode(parseInt(hexPair, 16));
  777. }
  778. str = str.replace(/[\u007F-\uFFFF]/g, ''); // Remove characters from 0x0080 to 0xFFFF
  779. return str.trim();
  780. }
  781. function win_chassisType()
  782. {
  783. // use new win-wmi-fixed module to get arrays correctly for time being
  784. try {
  785. var tokens = require('win-wmi-fixed').query('ROOT\\CIMV2', 'SELECT ChassisTypes FROM Win32_SystemEnclosure', ['ChassisTypes']);
  786. if (tokens[0]) {
  787. return (parseInt(tokens[0]['ChassisTypes'][0]));
  788. }
  789. } catch (e) {
  790. return (2); // unknown
  791. }
  792. }
  793. function win_systemType()
  794. {
  795. try {
  796. var tokens = require('win-wmi').query('ROOT\\CIMV2', 'SELECT PCSystemType FROM Win32_ComputerSystem', ['PCSystemType']);
  797. if (tokens[0]) {
  798. return (parseInt(tokens[0]['PCSystemType']));
  799. } else {
  800. return (parseInt(1)); // default is desktop
  801. }
  802. } catch (ex) {
  803. return (parseInt(1)); // default is desktop
  804. }
  805. }
  806. function win_formFactor(chassistype)
  807. {
  808. var ret = 'DESKTOP';
  809. switch (chassistype)
  810. {
  811. case 11: // Handheld
  812. case 30: // Tablet
  813. case 31: // Convertible
  814. case 32: // Detachable
  815. ret = 'TABLET';
  816. break;
  817. case 9: // Laptop
  818. case 10: // Notebook
  819. case 14: // Sub Notebook
  820. ret = 'LAPTOP';
  821. break;
  822. default:
  823. ret = win_systemType() == 2 ? 'MOBILE' : 'DESKTOP';
  824. break;
  825. }
  826. return (ret);
  827. }
  828. switch(process.platform)
  829. {
  830. case 'linux':
  831. module.exports = { _ObjectID: 'identifiers', get: linux_identifiers };
  832. break;
  833. case 'win32':
  834. module.exports = { _ObjectID: 'identifiers', get: windows_identifiers, chassisType: win_chassisType, formFactor: win_formFactor, systemType: win_systemType };
  835. break;
  836. case 'darwin':
  837. module.exports = { _ObjectID: 'identifiers', get: macos_identifiers };
  838. break;
  839. default:
  840. module.exports = { get: function () { throw ('Unsupported Platform'); } };
  841. break;
  842. }
  843. module.exports.isDocker = function isDocker()
  844. {
  845. if (process.platform != 'linux') { return (false); }
  846. var child = require('child_process').execFile('/bin/sh', ['sh']);
  847. child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
  848. child.stdin.write("cat /proc/self/cgroup | tr '\n' '`' | awk -F'`' '{ split($1, res, " + '"/"); if(res[2]=="docker"){print "1";} }\'\nexit\n');
  849. child.waitExit();
  850. return (child.stdout.str != '');
  851. };
  852. module.exports.isBatteryPowered = function isBatteryOperated()
  853. {
  854. var ret = false;
  855. switch(process.platform)
  856. {
  857. default:
  858. break;
  859. case 'linux':
  860. var devices = require('fs').readdirSync('/sys/class/power_supply');
  861. for (var i in devices)
  862. {
  863. if (require('fs').readFileSync('/sys/class/power_supply/' + devices[i] + '/type').toString().trim() == 'Battery')
  864. {
  865. ret = true;
  866. break;
  867. }
  868. }
  869. break;
  870. case 'win32':
  871. var GM = require('_GenericMarshal');
  872. var stats = GM.CreateVariable(12);
  873. var kernel32 = GM.CreateNativeProxy('Kernel32.dll');
  874. kernel32.CreateMethod('GetSystemPowerStatus');
  875. if (kernel32.GetSystemPowerStatus(stats).Val != 0)
  876. {
  877. if(stats.toBuffer()[1] != 128 && stats.toBuffer()[1] != 255)
  878. {
  879. ret = true;
  880. }
  881. else
  882. {
  883. // No Battery detected, so lets check if there is supposed to be one
  884. var formFactor = win_formFactor(win_chassisType());
  885. return (formFactor == 'LAPTOP' || formFactor == 'TABLET' || formFactor == 'MOBILE');
  886. }
  887. }
  888. break;
  889. case 'darwin':
  890. var child = require('child_process').execFile('/bin/sh', ['sh']);
  891. child.stdout.str = ''; child.stdout.on('data', function(c){ this.str += c.toString(); });
  892. child.stderr.str = ''; child.stderr.on('data', function(c){ this.str += c.toString(); });
  893. child.stdin.write("pmset -g batt | tr '\\n' '`' | awk -F'`' '{ if(NF>2) { print \"true\"; }}'\nexit\n");
  894. child.waitExit();
  895. if(child.stdout.str.trim() != '') { ret = true; }
  896. break;
  897. }
  898. return (ret);
  899. };
  900. module.exports.isVM = function isVM()
  901. {
  902. var ret = false;
  903. var id = this.get();
  904. if (id.linux && id.linux.sys_vendor)
  905. {
  906. switch (id.linux.sys_vendor)
  907. {
  908. case 'VMware, Inc.':
  909. case 'QEMU':
  910. case 'Xen':
  911. ret = true;
  912. break;
  913. default:
  914. break;
  915. }
  916. }
  917. if (id.identifiers.bios_vendor)
  918. {
  919. switch(id.identifiers.bios_vendor)
  920. {
  921. case 'VMware, Inc.':
  922. case 'Xen':
  923. case 'SeaBIOS':
  924. case 'EFI Development Kit II / OVMF':
  925. case 'Proxmox distribution of EDK II':
  926. ret = true;
  927. break;
  928. default:
  929. break;
  930. }
  931. }
  932. if (id.identifiers.board_vendor && id.identifiers.board_vendor == 'VMware, Inc.') { ret = true; }
  933. if (id.identifiers.board_name)
  934. {
  935. switch (id.identifiers.board_name)
  936. {
  937. case 'VirtualBox':
  938. case 'Virtual Machine':
  939. ret = true;
  940. break;
  941. default:
  942. break;
  943. }
  944. }
  945. if (process.platform == 'win32' && !ret)
  946. {
  947. for(var i in id.identifiers.gpu_name)
  948. {
  949. if(id.identifiers.gpu_name[i].startsWith('VMware '))
  950. {
  951. ret = true;
  952. break;
  953. }
  954. }
  955. }
  956. if (!ret) { ret = this.isDocker(); }
  957. return (ret);
  958. };
  959. // bios_date = BIOS->ReleaseDate
  960. // bios_vendor = BIOS->Manufacturer
  961. // bios_version = BIOS->SMBIOSBIOSVersion
  962. // board_name = BASEBOARD->Product = ioreg/board-id
  963. // board_serial = BASEBOARD->SerialNumber = ioreg/serial-number | ioreg/IOPlatformSerialNumber
  964. // board_vendor = BASEBOARD->Manufacturer = ioreg/manufacturer
  965. // board_version = BASEBOARD->Version