@@ -41,6 +41,28 @@ String colorPercentage(int percentage) {
41
41
return pen (percentage.toString ()) + '%' ;
42
42
}
43
43
44
+ String ? findHwmonPathByNamePart (String namePart) {
45
+ const hwmonBasePath = "/sys/class/hwmon/hwmon" ;
46
+ int index = 0 ;
47
+ while (true ) {
48
+ var path = hwmonBasePath + index.toString ();
49
+ if (! Directory (path).existsSync ()) {
50
+ break ;
51
+ }
52
+ var namePath = path + "/name" ;
53
+ if (! File (namePath).existsSync ()) {
54
+ index++ ;
55
+ continue ;
56
+ }
57
+ var name = File (namePath).readAsStringSync ();
58
+ if (name.contains (namePart)) {
59
+ return path;
60
+ }
61
+ index++ ;
62
+ }
63
+ return null ;
64
+ }
65
+
44
66
class CpuNormalizedDataSource extends PerfmonDataSource {
45
67
static const path = '/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq' ;
46
68
static const header_cpu_freq = 'cpu_freq_mhz' ;
@@ -81,42 +103,51 @@ class GpuDataSource extends PerfmonDataSource {
81
103
static RegExp regex = RegExp (r'(\d+)@(\d+)Hz' );
82
104
static const header_gpu_load = 'gpu_load' ;
83
105
static const header_gpu_freq = 'gpu_freq_mhz' ;
106
+ static const header_gpu_temp = 'gpu_temp_mc' ;
107
+ late String gpu_temp_path;
84
108
85
109
List <int > _getData () {
86
110
var str = File (path).readAsStringSync ();
87
111
var matches = regex.firstMatch (str);
88
112
if (matches? .groupCount != 2 ) {
89
113
throw Exception ('Cannot parse GPU data source: $str ' );
90
114
}
115
+ var gpu_temp = File (gpu_temp_path).readAsStringSync ();
91
116
return [
92
117
int .parse (matches! .group (1 )! ),
93
- int .parse (matches.group (2 )! ) ~ / 1000000
118
+ int .parse (matches.group (2 )! ) ~ / 1000000 ,
119
+ int .parse (gpu_temp)
94
120
];
95
121
}
96
122
97
123
@override
98
124
void init () {
99
125
if (! File (path).existsSync ()) {
100
- throw Exception ('GPU data source not found' );
126
+ throw Exception ('GPU load data source not found' );
127
+ }
128
+ var hwmon_path = findHwmonPathByNamePart ("gpu_thermal" );
129
+ if (hwmon_path == null ) {
130
+ throw Exception ('GPU temp data source not found' );
101
131
}
132
+ gpu_temp_path = hwmon_path + "/temp1_input" ;
102
133
_getData ();
103
134
}
104
135
105
136
@override
106
137
String getCsvHeader () {
107
- return '$header_gpu_load ,$header_gpu_freq ' ;
138
+ return '$header_gpu_load ,$header_gpu_freq ,$ header_gpu_temp ' ;
108
139
}
109
140
110
141
@override
111
142
String getCsvLine () {
112
143
var data = _getData ();
113
- return '${data [0 ]},${data [1 ]}' ;
144
+ return '${data [0 ]},${data [1 ]},${ data [ 2 ]} ' ;
114
145
}
115
146
116
147
@override
117
148
String getUserFriendlyLine () {
118
149
var data = _getData ();
119
- return 'GPU load: ${colorPercentage (data [0 ])}, freq: ${(data [1 ] / 1000 ).toStringAsFixed (1 )}GHz' ;
150
+ return 'GPU load: ${colorPercentage (data [0 ])}, freq: ${(data [1 ] / 1000 ).toStringAsFixed (1 )}GHz, temp: ${( data [ 2 ] / 1000 ). toStringAsFixed ( 1 )}°C ' ;
120
151
}
121
152
}
122
153
@@ -170,17 +201,21 @@ class NpuDataSource extends PerfmonDataSource {
170
201
static RegExp regex =
171
202
RegExp (r'Core0:\s+(\d+)%, Core1:\s+(\d+)%, Core2:\s+(\d+)%' );
172
203
static const header_npu_load = 'npu_load' ;
204
+ static const header_npu_temp = 'npu_temp_mc' ;
205
+ late String npu_temp_path;
173
206
174
207
List <int > _getData () {
175
208
var str = File (path).readAsStringSync ();
176
209
var matches = regex.firstMatch (str);
177
210
if (matches? .groupCount != 3 ) {
178
211
throw Exception ('Cannot parse NPU data source: $str ' );
179
212
}
213
+ var npu_temp = File (npu_temp_path).readAsStringSync ();
180
214
return [
181
215
int .parse (matches! .group (1 )! ),
182
216
int .parse (matches.group (2 )! ),
183
- int .parse (matches.group (3 )! )
217
+ int .parse (matches.group (3 )! ),
218
+ int .parse (npu_temp)
184
219
];
185
220
}
186
221
@@ -189,24 +224,29 @@ class NpuDataSource extends PerfmonDataSource {
189
224
if (! File (path).existsSync ()) {
190
225
throw Exception ('NPU data source not found' );
191
226
}
227
+ var hwmon_path = findHwmonPathByNamePart ("npu_thermal" );
228
+ if (hwmon_path == null ) {
229
+ throw Exception ('NPU temp data source not found' );
230
+ }
231
+ npu_temp_path = hwmon_path + "/temp1_input" ;
192
232
_getData ();
193
233
}
194
234
195
235
@override
196
236
String getCsvHeader () {
197
- return '${header_npu_load }_0,${header_npu_load }_1,${header_npu_load }_2' ;
237
+ return '${header_npu_load }_0,${header_npu_load }_1,${header_npu_load }_2,${ header_npu_temp } ' ;
198
238
}
199
239
200
240
@override
201
241
String getCsvLine () {
202
242
var data = _getData ();
203
- return '${data [0 ]},${data [1 ]},${data [2 ]}' ;
243
+ return '${data [0 ]},${data [1 ]},${data [2 ]},${ data [ 3 ]} ' ;
204
244
}
205
245
206
246
@override
207
247
String getUserFriendlyLine () {
208
248
var data = _getData ();
209
- return 'NPU load: ${colorPercentage (data [0 ])}, ${colorPercentage (data [1 ])}, ${colorPercentage (data [2 ])}' ;
249
+ return 'NPU load: ${colorPercentage (data [0 ])}, ${colorPercentage (data [1 ])}, ${colorPercentage (data [2 ])}, temp: ${( data [ 3 ] / 1000 ). toStringAsFixed ( 1 )}°C ' ;
210
250
}
211
251
}
212
252
0 commit comments