EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
sysinfo.js
Go to the documentation of this file.
1/*
2Copyright 2019-2021 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17var PDH_FMT_LONG = 0x00000100;
18var PDH_FMT_DOUBLE = 0x00000200;
19
20var promise = require('promise');
21if (process.platform == 'win32')
22{
23 var GM = require('_GenericMarshal');
24 GM.kernel32 = GM.CreateNativeProxy('kernel32.dll');
25 GM.kernel32.CreateMethod('GlobalMemoryStatusEx');
26
27 GM.pdh = GM.CreateNativeProxy('pdh.dll');
28 GM.pdh.CreateMethod('PdhAddEnglishCounterA');
29 GM.pdh.CreateMethod('PdhCloseQuery');
30 GM.pdh.CreateMethod('PdhCollectQueryData');
31 GM.pdh.CreateMethod('PdhGetFormattedCounterValue');
32 GM.pdh.CreateMethod('PdhGetFormattedCounterArrayA');
33 GM.pdh.CreateMethod('PdhOpenQueryA');
34 GM.pdh.CreateMethod('PdhRemoveCounter');
35}
36
37function windows_cpuUtilization()
38{
39 var p = new promise(function (res, rej) { this._res = res; this._rej = rej; });
40 p.counter = GM.CreateVariable(16);
41 p.cpu = GM.CreatePointer();
42 p.cpuTotal = GM.CreatePointer();
43 var err = 0;
44 if ((err = GM.pdh.PdhOpenQueryA(0, 0, p.cpu).Val) != 0) { p._rej(err); return; }
45
46 // This gets the CPU Utilization for each proc
47 if ((err = GM.pdh.PdhAddEnglishCounterA(p.cpu.Deref(), GM.CreateVariable('\\Processor(*)\\% Processor Time'), 0, p.cpuTotal).Val) != 0) { p._rej(err); return; }
48
49 if ((err = GM.pdh.PdhCollectQueryData(p.cpu.Deref()).Val != 0)) { p._rej(err); return; }
50 p._timeout = setTimeout(function (po)
51 {
52 var u = { cpus: [] };
53 var bufSize = GM.CreateVariable(4);
54 var itemCount = GM.CreateVariable(4);
55 var buffer, szName, item;
56 var e;
57 if ((e = GM.pdh.PdhCollectQueryData(po.cpu.Deref()).Val != 0)) { po._rej(e); return; }
58
59 if ((e = GM.pdh.PdhGetFormattedCounterArrayA(po.cpuTotal.Deref(), PDH_FMT_DOUBLE, bufSize, itemCount, 0).Val) == -2147481646)
60 {
61 buffer = GM.CreateVariable(bufSize.toBuffer().readUInt32LE());
62 }
63 else
64 {
65 po._rej(e);
66 return;
67 }
68 if ((e = GM.pdh.PdhGetFormattedCounterArrayA(po.cpuTotal.Deref(), PDH_FMT_DOUBLE, bufSize, itemCount, buffer).Val) != 0) { po._rej(e); return; }
69 for(var i=0;i<itemCount.toBuffer().readUInt32LE();++i)
70 {
71 item = buffer.Deref(i * 24, 24);
72 szName = item.Deref(0, GM.PointerSize).Deref();
73 if (szName.String == '_Total')
74 {
75 u.total = item.Deref(16, 8).toBuffer().readDoubleLE();
76 }
77 else
78 {
79 u.cpus[parseInt(szName.String)] = item.Deref(16, 8).toBuffer().readDoubleLE();
80 }
81 }
82
83 GM.pdh.PdhRemoveCounter(po.cpuTotal.Deref());
84 GM.pdh.PdhCloseQuery(po.cpu.Deref());
85 p._res(u);
86 }, 100, p);
87
88 return (p);
89}
90function windows_memUtilization()
91{
92 var info = GM.CreateVariable(64);
93 info.Deref(0, 4).toBuffer().writeUInt32LE(64);
94 GM.kernel32.GlobalMemoryStatusEx(info);
95
96 var ret =
97 {
98 MemTotal: require('bignum').fromBuffer(info.Deref(8, 8).toBuffer(), { endian: 'little' }),
99 MemFree: require('bignum').fromBuffer(info.Deref(16, 8).toBuffer(), { endian: 'little' })
100 };
101
102 ret.percentFree = ((ret.MemFree.div(require('bignum')('1048576')).toNumber() / ret.MemTotal.div(require('bignum')('1048576')).toNumber()) * 100);//.toFixed(2);
103 ret.percentConsumed = ((ret.MemTotal.sub(ret.MemFree).div(require('bignum')('1048576')).toNumber() / ret.MemTotal.div(require('bignum')('1048576')).toNumber()) * 100);//.toFixed(2);
104 ret.MemTotal = ret.MemTotal.toString();
105 ret.MemFree = ret.MemFree.toString();
106 return (ret);
107}
108
109var cpuLastIdle = [];
110var cpuLastSum = [];
111function linux_cpuUtilization() {
112 var ret = { cpus: [] };
113 var info = require('fs').readFileSync('/proc/stat');
114 var lines = info.toString().split('\n');
115 var columns;
116 var x, y;
117 var cpuNo = 0;
118 var currSum, currIdle, utilization;
119 for (var i in lines) {
120 columns = lines[i].split(' ');
121 if (!columns[0].startsWith('cpu')) { break; }
122
123 x = 0, currSum = 0;
124 while (columns[++x] == '');
125 for (y = x; y < columns.length; ++y) { currSum += parseInt(columns[y]); }
126 currIdle = parseInt(columns[3 + x]);
127
128 var diffIdle = currIdle - cpuLastIdle[cpuNo];
129 var diffSum = currSum - cpuLastSum[cpuNo];
130
131 utilization = (100 - ((diffIdle / diffSum) * 100));
132
133 cpuLastSum[cpuNo] = currSum;
134 cpuLastIdle[cpuNo] = currIdle;
135
136 if (!ret.total) {
137 ret.total = utilization;
138 } else {
139 ret.cpus.push(utilization);
140 }
141 ++cpuNo;
142 }
143
144 var p = new promise(function (res, rej) { this._res = res; this._rej = rej; });
145 p._res(ret);
146 return (p);
147}
148function linux_memUtilization()
149{
150 var ret = {};
151
152 var info = require('fs').readFileSync('/proc/meminfo').toString().split('\n');
153 var tokens;
154 for(var i in info)
155 {
156 tokens = info[i].split(' ');
157 switch(tokens[0])
158 {
159 case 'MemTotal:':
160 ret.total = parseInt(tokens[tokens.length - 2]);
161 break;
162 case 'MemFree:':
163 ret.free = parseInt(tokens[tokens.length - 2]);
164 break;
165 }
166 }
167 ret.percentFree = ((ret.free / ret.total) * 100);//.toFixed(2);
168 ret.percentConsumed = (((ret.total - ret.free) / ret.total) * 100);//.toFixed(2);
169 return (ret);
170}
171
172function macos_cpuUtilization()
173{
174 var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
175 var child = require('child_process').execFile('/bin/sh', ['sh']);
176 child.stdout.str = '';
177 child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
178 child.stdin.write('top -l 1 | grep -E "^CPU"\nexit\n');
179 child.waitExit();
180
181 var lines = child.stdout.str.split('\n');
182 if (lines[0].length > 0)
183 {
184 var usage = lines[0].split(':')[1];
185 var bdown = usage.split(',');
186
187 var tot = parseFloat(bdown[0].split('%')[0].trim()) + parseFloat(bdown[1].split('%')[0].trim());
188 ret._res({total: tot, cpus: []});
189 }
190 else
191 {
192 ret._rej('parse error');
193 }
194
195 return (ret);
196}
197function macos_memUtilization()
198{
199 var mem = { };
200 var ret = new promise(function (res, rej) { this._res = res; this._rej = rej; });
201 var child = require('child_process').execFile('/bin/sh', ['sh']);
202 child.stdout.str = '';
203 child.stdout.on('data', function (chunk) { this.str += chunk.toString(); });
204 child.stdin.write('top -l 1 | grep -E "^Phys"\nexit\n');
205 child.waitExit();
206
207 var lines = child.stdout.str.split('\n');
208 if (lines[0].length > 0)
209 {
210 var usage = lines[0].split(':')[1];
211 var bdown = usage.split(',');
212
213 mem.MemTotal = parseInt(bdown[0].trim().split(' ')[0]);
214 mem.MemFree = parseInt(bdown[1].trim().split(' ')[0]);
215 mem.percentFree = ((mem.MemFree / mem.MemTotal) * 100);//.toFixed(2);
216 mem.percentConsumed = (((mem.MemTotal - mem.MemFree) / mem.MemTotal) * 100);//.toFixed(2);
217 return (mem);
218 }
219 else
220 {
221 throw ('Parse Error');
222 }
223}
224
225function windows_thermals()
226{
227 var ret = [];
228 try {
229 ret = require('win-wmi').query('ROOT\\WMI', 'SELECT CurrentTemperature,InstanceName FROM MSAcpi_ThermalZoneTemperature',['CurrentTemperature','InstanceName']);
230 if (ret[0]) {
231 for (var i = 0; i < ret.length; ++i) {
232 ret[i]['CurrentTemperature'] = ((parseFloat(ret[i]['CurrentTemperature']) / 10) - 273.15).toFixed(2);
233 }
234 }
235 } catch (ex) { }
236 return (ret);
237}
238
239function linux_thermals()
240{
241 child = require('child_process').execFile('/bin/sh', ['sh']);
242 child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
243 child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
244 child.stdin.write("cat /sys/class/thermal/thermal_zone*/temp | awk '{ print $0 / 1000 }'\nexit\n");
245 child.waitExit();
246 var ret = child.stdout.str.trim().split('\n');
247 if (ret.length == 1 && ret[0] == '') { ret = []; }
248 return (ret);
249}
250
251function macos_thermals()
252{
253 var ret = [];
254 var child = require('child_process').execFile('/bin/sh', ['sh']);
255 child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
256 child.stderr.on('data', function () { });
257 child.stdin.write('powermetrics --help | grep SMC\nexit\n');
258 child.waitExit();
259
260 if (child.stdout.str.trim() != '')
261 {
262 child = require('child_process').execFile('/bin/sh', ['sh']);
263 child.stdout.str = ''; child.stdout.on('data', function (c)
264 {
265 this.str += c.toString();
266 var tokens = this.str.trim().split('\n');
267 for (var i in tokens)
268 {
269 if (tokens[i].split(' die temperature: ').length > 1)
270 {
271 ret.push(tokens[i].split(' ')[3]);
272 this.parent.kill();
273 }
274 }
275 });
276 child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
277 child.stdin.write('powermetrics -s smc\n');
278 child.waitExit(5000);
279 }
280 return (ret);
281}
282
283const platformConfig = {
284 linux: { cpuUtilization: linux_cpuUtilization, memUtilization: linux_memUtilization, thermals: linux_thermals },
285 win32: { cpuUtilization: windows_cpuUtilization, memUtilization: windows_memUtilization, thermals: windows_thermals },
286 darwin: { cpuUtilization: macos_cpuUtilization, memUtilization: macos_memUtilization, thermals: macos_thermals }
287};
288
289module.exports = platformConfig[process.platform];