@@ -2,8 +2,7 @@ const { app, BrowserWindow, globalShortcut, screen, ipcMain } = require('electro
22const path = require ( 'path' ) ;
33const fs = require ( 'fs' ) ;
44const os = require ( 'os' ) ;
5- const util = require ( 'util' ) ;
6- const execAsync = util . promisify ( require ( 'child_process' ) . exec ) ;
5+ const si = require ( 'systeminformation' ) ;
76
87let mainWindow ;
98let config = { autoLaunch : false , shortcut : 'CommandOrControl+G' } ;
@@ -12,136 +11,71 @@ let updateInterval;
1211async function collectStats ( ) {
1312 const stats = { } ;
1413
15- // CPU Temperature
16- try {
17- let { stdout } = await execAsync ( 'sensors | grep -A 0 "Tctl:" | cut -c15-22' ) ;
18- stats . cpuTemp = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
19- } catch {
20- try {
21- const raw = fs . readFileSync ( '/sys/class/thermal/thermal_zone0/temp' , 'utf8' ) ;
22- stats . cpuTemp = ( parseInt ( raw ) / 1000 ) . toFixed ( 1 ) ;
23- } catch {
24- stats . cpuTemp = 'N/A' ;
25- }
26- }
27-
28- // CPU Usage
29- try {
30- let { stdout } = await execAsync ( 'top -bn1 | grep "Cpu(s)" | sed "s/.*, *\\([0-9.]*\\)%* id.*/\\1/" | awk \'{print 100 - $1}\'' ) ;
31- stats . cpuUsage = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
32- } catch {
33- stats . cpuUsage = 'N/A' ;
34- }
35-
36- // CPU Frequency
37- try {
38- let { stdout } = await execAsync ( 'cat /proc/cpuinfo | grep "cpu MHz" | head -1 | awk \'{print $4}\'' ) ;
39- stats . cpuFreq = parseFloat ( stdout . trim ( ) ) . toFixed ( 0 ) ;
40- } catch {
41- stats . cpuFreq = 'N/A' ;
42- }
43-
44- // CPU Fan
45- try {
46- let { stdout } = await execAsync ( 'sensors | grep "fan1:" | awk \'{print $2}\'' ) ;
47- stats . cpuFan = stdout . trim ( ) ;
48- } catch {
49- stats . cpuFan = 'N/A' ;
50- }
51-
52- // GPU Temperature
53- try {
54- let { stdout } = await execAsync ( 'nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader' ) ;
55- stats . gpuTemp = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
56- } catch {
57- try {
58- let { stdout } = await execAsync ( 'rocm-smi --showtemp | grep "GPU Temp" | awk \'{print $4}\'' ) ;
59- stats . gpuTemp = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
60- } catch {
61- stats . gpuTemp = 'N/A' ;
62- }
63- }
64-
65- // GPU Usage
66- try {
67- let { stdout } = await execAsync ( 'nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader' ) ;
68- stats . gpuUsage = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
69- } catch {
70- try {
71- let { stdout } = await execAsync ( 'rocm-smi --showutil | grep "GPU use" | awk \'{print $4}\'' ) ;
72- stats . gpuUsage = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
73- } catch {
74- stats . gpuUsage = 'N/A' ;
75- }
76- }
77-
78- // GPU Fan
79- try {
80- let { stdout } = await execAsync ( 'nvidia-smi --query-gpu=fan.speed --format=csv,noheader' ) ;
81- stats . gpuFan = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
82- } catch {
83- try {
84- let { stdout } = await execAsync ( 'rocm-smi --showfan | grep "Fan Level" | awk \'{print $4}\'' ) ;
85- stats . gpuFan = parseFloat ( stdout . trim ( ) ) . toFixed ( 1 ) ;
86- } catch {
87- stats . gpuFan = 'N/A' ;
88- }
89- }
90-
91- // GPU Memory
92- try {
93- let { stdout } = await execAsync ( 'nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader' ) ;
94- const [ used , total ] = stdout . trim ( ) . split ( ',' ) . map ( s => s . trim ( ) . replace ( ' MiB' , '' ) ) ;
95- stats . gpuMem = `${ used } /${ total } ` ;
96- } catch {
97- try {
98- let { stdout } = await execAsync ( 'rocm-smi --showmeminfo vram | grep "Used" | awk \'{print $4 "/" $5}\'' ) ;
99- stats . gpuMem = stdout . trim ( ) ;
100- } catch {
101- stats . gpuMem = 'N/A' ;
102- }
14+ // CPU Stats
15+ const cpuTemp = await si . cpuTemperature ( ) ;
16+ stats . cpuTemp = cpuTemp . main !== null ? cpuTemp . main . toFixed ( 1 ) : 'N/A' ;
17+
18+ const currentLoad = await si . currentLoad ( ) ;
19+ stats . cpuUsage = currentLoad . currentLoad . toFixed ( 1 ) ;
20+
21+ const cpu = await si . cpu ( ) ;
22+ stats . cpuFreq = cpu . speed ? ( cpu . speed * 1000 ) . toFixed ( 0 ) : 'N/A' ;
23+
24+ stats . cpuVoltage = 'N/A' ; // systeminformation doesn't provide voltage directly
25+
26+ // For fans, systeminformation has si.chassis() but limited, fallback to sensors if needed
27+ stats . cpuFan = 'N/A' ;
28+
29+ // GPU Stats
30+ const graphics = await si . graphics ( ) ;
31+ if ( graphics . controllers && graphics . controllers . length > 0 ) {
32+ const gpu = graphics . controllers [ 0 ] ;
33+ stats . gpuTemp = gpu . temperatureGpu ? gpu . temperatureGpu . toFixed ( 1 ) : 'N/A' ;
34+ stats . gpuUsage = gpu . utilizationGpu ? gpu . utilizationGpu . toFixed ( 1 ) : 'N/A' ;
35+ stats . gpuFan = gpu . fanPercent ? gpu . fanPercent . toFixed ( 1 ) : 'N/A' ;
36+ stats . gpuMem = gpu . memoryUsed ? `${ gpu . memoryUsed } /${ gpu . memoryTotal } ` : 'N/A' ;
37+ stats . gpuPower = gpu . powerDraw ? gpu . powerDraw . toFixed ( 1 ) : 'N/A' ;
38+ } else {
39+ stats . gpuTemp = 'N/A' ;
40+ stats . gpuUsage = 'N/A' ;
41+ stats . gpuFan = 'N/A' ;
42+ stats . gpuMem = 'N/A' ;
43+ stats . gpuPower = 'N/A' ;
10344 }
10445
10546 // RAM Usage
106- const totalMem = os . totalmem ( ) ;
107- const freeMem = os . freemem ( ) ;
108- const usedMem = totalMem - freeMem ;
109- stats . ramUsage = ( ( usedMem / totalMem ) * 100 ) . toFixed ( 1 ) ;
47+ const mem = await si . mem ( ) ;
48+ stats . ramUsage = `${ ( mem . used / 1024 / 1024 / 1024 ) . toFixed ( 1 ) } / ${ ( mem . total / 1024 / 1024 / 1024 ) . toFixed ( 1 ) } GB` ;
11049
11150 // Disk Usage
112- try {
113- let { stdout } = await execAsync ( 'df -h / | tail -1 | awk \'{print $5}\' | sed \'s/%//\'' ) ;
114- stats . diskUsage = stdout . trim ( ) ;
115- } catch {
116- stats . diskUsage = 'N/A' ;
117- }
51+ const fsSize = await si . fsSize ( ) ;
52+ const root = fsSize . find ( d => d . mount === '/' ) ;
53+ stats . diskUsage = root ? `${ ( root . used / 1024 / 1024 / 1024 ) . toFixed ( 1 ) } / ${ ( root . size / 1024 / 1024 / 1024 ) . toFixed ( 1 ) } GB` : 'N/A' ;
11854
119- // Battery Level
120- try {
121- const batteryPath = '/sys/class/power_supply/BAT0/capacity' ;
122- if ( fs . existsSync ( batteryPath ) ) {
123- stats . batteryLevel = fs . readFileSync ( batteryPath , 'utf8' ) . trim ( ) ;
124- } else {
125- stats . batteryLevel = 'N/A' ;
126- }
127- } catch {
128- stats . batteryLevel = 'N/A' ;
129- }
55+ // Battery
56+ const battery = await si . battery ( ) ;
57+ stats . batteryLevel = battery . hasBattery ? battery . percent : 'N/A' ;
13058
13159 // Uptime
132- const uptimeSeconds = os . uptime ( ) ;
133- const days = Math . floor ( uptimeSeconds / ( 3600 * 24 ) ) ;
134- const hours = Math . floor ( ( uptimeSeconds % ( 3600 * 24 ) ) / 3600 ) ;
135- const minutes = Math . floor ( ( uptimeSeconds % 3600 ) / 60 ) ;
136- const seconds = Math . floor ( uptimeSeconds % 60 ) ;
137- stats . uptime = `${ days } d ${ hours } h ${ minutes } m ${ seconds } s` ;
138-
139- // Network (placeholder)
140- stats . netDownload = ( Math . random ( ) * 100 ) . toFixed ( 1 ) ;
141- stats . netUpload = ( Math . random ( ) * 20 ) . toFixed ( 1 ) ;
142-
143- // FPS (placeholder)
144- stats . fps = Math . floor ( Math . random ( ) * 60 + 30 ) ;
60+ const time = si . time ( ) ;
61+ stats . uptime = time . uptimeFormatted || `${ Math . floor ( os . uptime ( ) / 3600 ) } h ${ Math . floor ( ( os . uptime ( ) % 3600 ) / 60 ) } m` ;
62+
63+ // Network
64+ const netStats = await si . networkStats ( ) ;
65+ if ( netStats . length > 0 ) {
66+ const net = netStats [ 0 ] ;
67+ stats . netDownload = ( net . rx_sec / 1024 / 1024 * 8 ) . toFixed ( 2 ) + ' Mbps' ;
68+ stats . netUpload = ( net . tx_sec / 1024 / 1024 * 8 ) . toFixed ( 2 ) + ' Mbps' ;
69+ } else {
70+ stats . netDownload = 'N/A' ;
71+ stats . netUpload = 'N/A' ;
72+ }
73+
74+ // FPS placeholder
75+ stats . fps = 'N/A' ;
76+
77+ // Load Avg
78+ stats . loadAvg = os . loadavg ( ) . map ( l => l . toFixed ( 2 ) ) . join ( ' ' ) ;
14579
14680 return stats ;
14781}
0 commit comments