Skip to content

Commit a38614b

Browse files
committed
Move all sensors specifications to a dictionnary. Sort bny natural order (for ease to use & it fixes core order in coretemp)
1 parent 37f2334 commit a38614b

1 file changed

Lines changed: 124 additions & 38 deletions

File tree

usr/lib/linuxmint/mintreport/sensors.py

Lines changed: 124 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import os
22
import gi
33
import xapp.util
4+
import re
5+
from enum import IntEnum
46

57
gi.require_version("Gtk", "3.0")
68
from gi.repository import Gtk, GLib, Pango
@@ -11,34 +13,99 @@
1113

1214
COL_NAME, COL_VALUE, COL_UNIT, COL_SENSITIVE, COL_ICON_NAME = range(5)
1315

14-
def format_sensor(filename, raw):
15-
raw = raw.strip()
16-
17-
if filename.startswith("temp"):
18-
return f"{int(raw)/1000:.1f}", "°C", "xsi-temperature-symbolic"
19-
20-
if filename.startswith("fan"):
21-
return raw, _("RPM"), "xsi-cog-symbolic"
22-
23-
if filename.startswith("pwm"):
24-
return f"{int(raw)*100/255:.0f}", "%", "xsi-cog-symbolic"
25-
26-
if filename.startswith("in"):
27-
return f"{int(raw)/1000:.3f}", "V", "xsi-cog-symbolic"
28-
29-
if filename.startswith("curr"):
30-
return f"{int(raw)/1000:.3f}", "A", "xsi-cog-symbolic"
31-
32-
if filename.startswith("power"):
33-
return f"{int(raw)/1_000_000:.1f}", "W", "xsi-cog-symbolic"
34-
35-
if filename.startswith("freq"):
36-
return f"{int(raw)/1_000_000_000:.3f}", "GHz", "xsi-cog-symbolic"
37-
38-
if filename.startswith("energy"):
39-
return f"{int(raw)/1_000_000:.3f}", "J", "xsi-cog-symbolic"
40-
41-
return raw, "", "xsi-cpu-symbolic"
16+
class SensorType(IntEnum):
17+
TEMP = 0
18+
FAN = 1
19+
PWM = 2
20+
FREQ = 3
21+
VOLTAGE = 4
22+
CURRENT = 5
23+
POWER = 6
24+
ENERGY = 7
25+
OTHER = 99
26+
27+
28+
SENSOR_SPECS = {
29+
SensorType.TEMP: {
30+
"prefix":"temp",
31+
"format":lambda raw: f"{int(raw)/1000:.1f}",
32+
"unit":"°C",
33+
"icon":"xsi-temperature-symbolic"
34+
},
35+
SensorType.FAN: {
36+
"prefix":"fan",
37+
"format":lambda raw: raw.strip(),
38+
"unit":_("RPM"),
39+
"icon":"xsi-cog-symbolic"
40+
},
41+
SensorType.PWM: {
42+
"prefix":"pwm",
43+
"format":lambda raw: f"{int(raw)*100/255:.0f}",
44+
"unit":"%",
45+
"icon":"xsi-cog-symbolic"
46+
},
47+
SensorType.FREQ: {
48+
"prefix":"freq",
49+
"format":lambda raw: f"{int(raw)/1_000_000_000:.3f}",
50+
"unit":"GHz",
51+
"icon":"xsi-cog-symbolic"
52+
},
53+
SensorType.VOLTAGE: {
54+
"prefix":"in",
55+
"format":lambda raw: f"{int(raw)/1000:.3f}",
56+
"unit":"V",
57+
"icon":"xsi-cog-symbolic"
58+
},
59+
SensorType.CURRENT: {
60+
"prefix":"curr",
61+
"format":lambda raw: f"{int(raw)/1000:.3f}",
62+
"unit":"A",
63+
"icon":"xsi-cog-symbolic"
64+
},
65+
SensorType.POWER: {
66+
"prefix":"power",
67+
"format":lambda raw: f"{int(raw)/1_000_000:.1f}",
68+
"unit":"W",
69+
"icon":"xsi-cog-symbolic"
70+
},
71+
SensorType.ENERGY: {
72+
"prefix":"energy",
73+
"format":lambda raw: f"{int(raw)/1_000_000:.3f}",
74+
"unit":"J",
75+
"icon":"xsi-cog-symbolic"
76+
},
77+
SensorType.OTHER: {
78+
"prefix":"",
79+
"format":lambda raw: raw.strip(),
80+
"unit":"",
81+
"icon":"xsi-cog-symbolic"
82+
},
83+
}
84+
85+
def sensor_spec_from_filename(filename):
86+
for stype, spec in SENSOR_SPECS.items():
87+
prefix = spec["prefix"]
88+
if prefix and filename.startswith(prefix):
89+
return stype, spec
90+
return SensorType.OTHER, SENSOR_SPECS[SensorType.OTHER]
91+
92+
# Helper funcs to sort sensors in correct numerical order (ex in10 after in9)
93+
def natural_key(label):
94+
# Split around any digit sequence
95+
parts = re.split(r'(\d+)', label)
96+
key = []
97+
for part in parts:
98+
if part.isdigit():
99+
key.append(int(part))
100+
else:
101+
key.append(part.lower())
102+
return key
103+
104+
def sort_sensors(sensors):
105+
# Natural sort within each sensor type
106+
sensors.sort(key=lambda s: natural_key(s["label"]))
107+
# Group by sensor type
108+
sensors.sort(key=lambda s: s["type"])
42109

43110
class SensorsListWidget(Gtk.ScrolledWindow):
44111

@@ -122,7 +189,7 @@ def build_tree(self):
122189
if not os.path.isdir(SYS_HWMON):
123190
return
124191

125-
for hwmon in sorted(os.listdir(SYS_HWMON)):
192+
for hwmon in os.listdir(SYS_HWMON):
126193
hwmon_path = os.path.join(SYS_HWMON, hwmon)
127194
device_path = os.path.join(hwmon_path, "device")
128195

@@ -146,10 +213,11 @@ def build_tree(self):
146213
None, [name, "", "", True, "xsi-cpu-symbolic"]
147214
)
148215

149-
device_without_sensors = True;
216+
device_without_sensors = True
150217

151218
# Process all *_input files in base_path
152-
for fname in sorted(os.listdir(base_path)):
219+
sensors = []
220+
for fname in os.listdir(base_path):
153221
if not fname.endswith("_input"):
154222
continue
155223

@@ -158,20 +226,35 @@ def build_tree(self):
158226
if raw is None:
159227
continue
160228

161-
value, unit, icon_name = format_sensor(fname, raw)
229+
stype, spec = sensor_spec_from_filename(fname)
230+
value = spec["format"](raw)
162231

163232
# Label
164233
label_file = fpath.replace("_input", "_label")
165234
label = self._read_file(label_file)
166235
label = label.strip() if label else fname.replace("_input", "")
167236

237+
sensors.append({
238+
"label": label,
239+
"path": fpath,
240+
"value": value,
241+
"unit": spec["unit"],
242+
"icon": spec["icon"],
243+
"type": stype,
244+
})
245+
246+
sort_sensors(sensors)
247+
248+
# Add sorted sensors to treestore
249+
for s in sensors:
168250
itr = self.treestore.append(
169251
parent,
170-
[label, value, unit, True, icon_name],
252+
[s["label"], s["value"], s["unit"], True, s["icon"]],
171253
)
172-
self.sensor_rows[fpath] = itr
173254

174-
device_without_sensors = False;
255+
# Store TreeStore itr and sensor type by path for refresh
256+
self.sensor_rows[s["path"]] = (itr, s["type"])
257+
device_without_sensors = False
175258

176259
if device_without_sensors:
177260
self.treestore.set_value(parent, COL_SENSITIVE, False)
@@ -180,15 +263,18 @@ def build_tree(self):
180263

181264
def refresh_values(self):
182265
self.treestore.freeze_notify()
183-
for fpath, itr in self.sensor_rows.items():
266+
267+
for fpath, (itr, stype) in self.sensor_rows.items():
184268
raw = self._read_file(fpath)
185269
if raw is None:
186270
continue
187271

188-
fname = os.path.basename(fpath)
189-
value, _, _ = format_sensor(fname, raw)
272+
spec = SENSOR_SPECS[stype]
273+
value = spec["format"](raw)
274+
190275
if value != self.treestore.get_value(itr, COL_VALUE):
191276
self.treestore.set_value(itr, COL_VALUE, value)
277+
192278
self.treestore.thaw_notify()
193279
return True
194280

0 commit comments

Comments
 (0)