mirror of https://github.com/aristocratos/bpytop
Added: Options for choosing temperature scale and readded support for negative celsius temps
parent
57778eee03
commit
2318f506d4
73
bpytop.py
73
bpytop.py
|
@ -161,6 +161,9 @@ cpu_sensor=$cpu_sensor
|
|||
#* Show temperatures for cpu cores also if check_temp is True and sensors has been found
|
||||
show_coretemp=$show_coretemp
|
||||
|
||||
#* Which temperature scale to use, available values: "celsius", "fahrenheit", "kelvin" and "rankine"
|
||||
temp_scale="$temp_scale"
|
||||
|
||||
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
|
||||
draw_clock="$draw_clock"
|
||||
|
||||
|
@ -405,7 +408,7 @@ class Config:
|
|||
"swap_disk", "show_disks", "use_fstab", "net_download", "net_upload", "net_auto", "net_color_fixed", "show_init", "theme_background",
|
||||
"net_sync", "show_battery", "tree_depth", "cpu_sensor", "show_coretemp", "proc_update_mult", "shown_boxes", "net_iface", "only_physical",
|
||||
"truecolor", "io_mode", "io_graph_combined", "io_graph_speeds", "show_io_stat", "cpu_graph_upper", "cpu_graph_lower", "cpu_invert_lower",
|
||||
"cpu_single_graph", "show_uptime"]
|
||||
"cpu_single_graph", "show_uptime", "temp_scale"]
|
||||
conf_dict: Dict[str, Union[str, int, bool]] = {}
|
||||
color_theme: str = "Default"
|
||||
theme_background: bool = True
|
||||
|
@ -429,6 +432,7 @@ class Config:
|
|||
check_temp: bool = True
|
||||
cpu_sensor: str = "Auto"
|
||||
show_coretemp: bool = True
|
||||
temp_scale: str = "celsius"
|
||||
draw_clock: str = "%X"
|
||||
background_update: bool = True
|
||||
custom_cpu_name: str = ""
|
||||
|
@ -461,6 +465,7 @@ class Config:
|
|||
log_levels: List[str] = ["ERROR", "WARNING", "INFO", "DEBUG"]
|
||||
cpu_percent_fields: List = ["total"]
|
||||
cpu_percent_fields.extend(getattr(psutil.cpu_times_percent(), "_fields", []))
|
||||
temp_scales: List[str] = ["celsius", "fahrenheit", "kelvin", "rankine"]
|
||||
|
||||
cpu_sensors: List[str] = [ "Auto" ]
|
||||
|
||||
|
@ -567,6 +572,9 @@ class Config:
|
|||
if cpu_graph in new_config and not new_config[cpu_graph] in self.cpu_percent_fields:
|
||||
new_config[cpu_graph] = "_error_"
|
||||
self.warnings.append(f'Config key "{cpu_graph}" does not contain an available cpu stat attribute!')
|
||||
if "temp_scale" in new_config and not new_config["temp_scale"] in self.temp_scales:
|
||||
new_config["temp_scale"] = "_error_"
|
||||
self.warnings.append(f'Config key "temp_scale" does not contain a recognized temperature scale!')
|
||||
return new_config
|
||||
|
||||
def save_config(self):
|
||||
|
@ -1449,7 +1457,7 @@ class Graph:
|
|||
if max_value:
|
||||
self.lowest = 1 if self.round_up_low else 0
|
||||
self.max_value = max_value
|
||||
data = [ min_max((v + offset) * 100 // (max_value + offset), self.lowest, 100) for v in data ] #* Convert values to percentage values of max_value with max_value as ceiling
|
||||
data = [ min_max((v + offset) * 100 // (max_value + offset), min_max(v + offset, 0, self.lowest), 100) for v in data ] #* Convert values to percentage values of max_value with max_value as ceiling
|
||||
else:
|
||||
self.max_value = 0
|
||||
if color_max_value:
|
||||
|
@ -1533,7 +1541,7 @@ class Graph:
|
|||
else:
|
||||
for n in range(self.height):
|
||||
self.graphs[self.current][n] = self.graphs[self.current][n][1:]
|
||||
if self.max_value: value = min_max((value + self.offset) * 100 // (self.max_value + self.offset), self.lowest, 100)
|
||||
if self.max_value: value = min_max((value + self.offset) * 100 // (self.max_value + self.offset), min_max(value + self.offset, 0, self.lowest), 100)
|
||||
self._create([value])
|
||||
return self.out
|
||||
|
||||
|
@ -1865,6 +1873,8 @@ class CpuBox(Box, SubBox):
|
|||
hh: int = ceil(h / 2)
|
||||
hh2: int = h - hh
|
||||
mid_line: bool = False
|
||||
temp: int = 0
|
||||
unit: str = ""
|
||||
if not CONFIG.cpu_single_graph and CONFIG.cpu_graph_upper != CONFIG.cpu_graph_lower:
|
||||
mid_line = True
|
||||
if h % 2: hh = floor(h / 2)
|
||||
|
@ -1937,8 +1947,9 @@ class CpuBox(Box, SubBox):
|
|||
f'{THEME.gradient["cpu"][cpu.cpu_usage[0][-1]]}{cpu.cpu_usage[0][-1]:>4}{THEME.main_fg}%')
|
||||
if cpu.got_sensors:
|
||||
try:
|
||||
temp, unit = temperature(cpu.cpu_temp[0][-1], CONFIG.temp_scale)
|
||||
out += (f'{THEME.inactive_fg} ⡀⡀⡀⡀⡀{Mv.l(5)}{THEME.gradient["temp"][min_max(cpu.cpu_temp[0][-1], 0, cpu.cpu_temp_crit) * 100 // cpu.cpu_temp_crit]}{Graphs.temps[0](None if cls.resized else cpu.cpu_temp[0][-1])}'
|
||||
f'{cpu.cpu_temp[0][-1]:>4}{THEME.main_fg}°C')
|
||||
f'{temp:>4}{THEME.main_fg}{unit}')
|
||||
except:
|
||||
cpu.got_sensors = False
|
||||
|
||||
|
@ -1952,11 +1963,12 @@ class CpuBox(Box, SubBox):
|
|||
out += f'{cpu.cpu_usage[n][-1]:>{3 if cls.column_size < 2 else 4}}{THEME.main_fg}%'
|
||||
if cpu.got_sensors and cpu.cpu_temp[n] and not hide_cores:
|
||||
try:
|
||||
temp, unit = temperature(cpu.cpu_temp[n][-1], CONFIG.temp_scale)
|
||||
if cls.column_size > 1:
|
||||
out += f'{THEME.inactive_fg} ⡀⡀⡀⡀⡀{Mv.l(5)}{THEME.gradient["temp"][100 if cpu.cpu_temp[n][-1] >= cpu.cpu_temp_crit else (cpu.cpu_temp[n][-1] * 100 // cpu.cpu_temp_crit)]}{Graphs.temps[n](None if cls.resized else cpu.cpu_temp[n][-1])}'
|
||||
out += f'{THEME.inactive_fg} ⡀⡀⡀⡀⡀{Mv.l(5)}{THEME.gradient["temp"][min_max(cpu.cpu_temp[n][-1], 0, cpu.cpu_temp_crit) * 100 // cpu.cpu_temp_crit]}{Graphs.temps[n](None if cls.resized else cpu.cpu_temp[n][-1])}'
|
||||
else:
|
||||
out += f'{THEME.gradient["temp"][100 if cpu.cpu_temp[n][-1] >= cpu.cpu_temp_crit else (cpu.cpu_temp[n][-1] * 100 // cpu.cpu_temp_crit)]}'
|
||||
out += f'{cpu.cpu_temp[n][-1]:>4}{THEME.main_fg}°C'
|
||||
out += f'{THEME.gradient["temp"][min_max(temp, 0, cpu.cpu_temp_crit) * 100 // cpu.cpu_temp_crit]}'
|
||||
out += f'{temp:>4}{THEME.main_fg}{unit}'
|
||||
except:
|
||||
cpu.got_sensors = False
|
||||
elif cpu.got_sensors and not hide_cores:
|
||||
|
@ -3062,7 +3074,7 @@ class CpuCollector(Collector):
|
|||
s_name, s_label = CONFIG.cpu_sensor.split(":", 1)
|
||||
for name, entries in psutil.sensors_temperatures().items():
|
||||
for num, entry in enumerate(entries, 1):
|
||||
if name == s_name and (entry.label == s_label or str(num) == s_label) and round(entry.current) > 0:
|
||||
if name == s_name and (entry.label == s_label or str(num) == s_label):
|
||||
if entry.label.startswith("Package"):
|
||||
cpu_type = "intel"
|
||||
elif entry.label.startswith("Tdie"):
|
||||
|
@ -3074,7 +3086,7 @@ class CpuCollector(Collector):
|
|||
if getattr(entry, "critical", None) != None and entry.critical > 1: cls.cpu_temp_crit = round(entry.critical)
|
||||
else: cls.cpu_temp_crit = 95
|
||||
temp = round(entry.current)
|
||||
elif entry.label.startswith(("Package", "Tdie")) and cpu_type in ["", "other"] and s_name == "_-_" and hasattr(entry, "current") and round(entry.current) > 0:
|
||||
elif entry.label.startswith(("Package", "Tdie")) and cpu_type in ["", "other"] and s_name == "_-_" and hasattr(entry, "current"):
|
||||
if not cls.cpu_temp_high or cls.sensor_swap or cpu_type == "other":
|
||||
cls.sensor_swap = False
|
||||
if getattr(entry, "high", None) != None and entry.high > 1: cls.cpu_temp_high = round(entry.high)
|
||||
|
@ -3083,7 +3095,7 @@ class CpuCollector(Collector):
|
|||
else: cls.cpu_temp_crit = 95
|
||||
cpu_type = "intel" if entry.label.startswith("Package") else "ryzen"
|
||||
temp = round(entry.current)
|
||||
elif (entry.label.startswith(("Core", "Tccd", "CPU")) or (name.lower().startswith("cpu") and not entry.label)) and hasattr(entry, "current") and round(entry.current) > 0:
|
||||
elif (entry.label.startswith(("Core", "Tccd", "CPU")) or (name.lower().startswith("cpu") and not entry.label)) and hasattr(entry, "current"):
|
||||
if entry.label.startswith(("Core", "Tccd")):
|
||||
entry_int = int(entry.label.replace("Core", "").replace("Tccd", ""))
|
||||
if entry_int in core_dict and cpu_type != "ryzen":
|
||||
|
@ -4368,7 +4380,18 @@ class Menu:
|
|||
'',
|
||||
'Only works if check_temp is True and',
|
||||
'the system is reporting core temps.'],
|
||||
|
||||
"temp_scale" : [
|
||||
'Which temperature scale to use.',
|
||||
'',
|
||||
'Celsius, default scale.',
|
||||
'',
|
||||
'Fahrenheit, the american one.',
|
||||
'',
|
||||
'Kelvin, 0 = absolute zero, 1 degree change',
|
||||
'equals 1 degree change in Celsius.',
|
||||
'',
|
||||
'Rankine, 0 = abosulte zero, 1 degree change',
|
||||
'equals 1 degree change in Fahrenheit.'],
|
||||
"custom_cpu_name" : [
|
||||
'Custom cpu model name in cpu percentage box.',
|
||||
'',
|
||||
|
@ -4572,6 +4595,7 @@ class Menu:
|
|||
cpu_sensor_i: int = CONFIG.cpu_sensors.index(CONFIG.cpu_sensor)
|
||||
cpu_graph_i: Dict[str, int] = { "cpu_graph_upper" : CONFIG.cpu_percent_fields.index(CONFIG.cpu_graph_upper),
|
||||
"cpu_graph_lower" : CONFIG.cpu_percent_fields.index(CONFIG.cpu_graph_lower)}
|
||||
temp_scale_i: int = CONFIG.temp_scales.index(CONFIG.temp_scale)
|
||||
color_i: int
|
||||
max_opt_len: int = max([len(categories[x]) for x in categories]) * 2
|
||||
cat_list = list(categories)
|
||||
|
@ -4635,11 +4659,13 @@ class Menu:
|
|||
counter = f' {cpu_sensor_i + 1}/{len(CONFIG.cpu_sensors)}'
|
||||
elif opt in ["cpu_graph_upper", "cpu_graph_lower"]:
|
||||
counter = f' {cpu_graph_i[opt] + 1}/{len(CONFIG.cpu_percent_fields)}'
|
||||
elif opt == "temp_scale":
|
||||
counter = f' {temp_scale_i + 1}/{len(CONFIG.temp_scales)}'
|
||||
else:
|
||||
counter = ""
|
||||
out += f'{Mv.to(y+1+cy, x+1)}{t_color}{Fx.b}{opt.replace("_", " ").capitalize() + counter:^24.24}{Fx.ub}{Mv.to(y+2+cy, x+1)}{v_color}'
|
||||
if opt == selected:
|
||||
if isinstance(value, bool) or opt in ["color_theme", "proc_sorting", "log_level", "cpu_sensor", "cpu_graph_upper", "cpu_graph_lower"]:
|
||||
if isinstance(value, bool) or opt in ["color_theme", "proc_sorting", "log_level", "cpu_sensor", "cpu_graph_upper", "cpu_graph_lower", "temp_scale"]:
|
||||
out += f'{t_color} {Symbol.left}{v_color}{d_quote + str(value) + d_quote:^20.20}{t_color}{Symbol.right} '
|
||||
elif inputting:
|
||||
out += f'{str(input_val)[-17:] + Fx.bl + "█" + Fx.ubl + "" + Symbol.enter:^33.33}'
|
||||
|
@ -4849,6 +4875,16 @@ class Menu:
|
|||
setattr(CpuCollector, selected.replace("_graph", ""), [])
|
||||
Term.refresh(force=True)
|
||||
cls.resized = False
|
||||
elif key in ["left", "right"] and selected == "temp_scale":
|
||||
if key == "left":
|
||||
temp_scale_i -= 1
|
||||
if temp_scale_i < 0: temp_scale_i = len(CONFIG.temp_scales) - 1
|
||||
if key == "right":
|
||||
temp_scale_i += 1
|
||||
if temp_scale_i > len(CONFIG.temp_scales) - 1: temp_scale_i = 0
|
||||
CONFIG.temp_scale = CONFIG.temp_scales[temp_scale_i]
|
||||
Term.refresh(force=True)
|
||||
cls.resized = False
|
||||
elif key in ["left", "right"] and selected == "cpu_sensor" and len(CONFIG.cpu_sensors) > 1:
|
||||
if key == "left":
|
||||
cpu_sensor_i -= 1
|
||||
|
@ -5277,6 +5313,19 @@ def readfile(file: str, default: str = "") -> str:
|
|||
pass
|
||||
return default if out is None else out
|
||||
|
||||
def temperature(value: int, scale: str = "celsius") -> Tuple[int, str]:
|
||||
"""Returns a tuple with integer value and string unit converted from an integer in celsius to: celsius, fahrenheit, kelvin or rankine."""
|
||||
if scale == "celsius":
|
||||
return (value, "°C")
|
||||
elif scale == "fahrenheit":
|
||||
return (round(value * 1.8 + 32), "°F")
|
||||
elif scale == "kelvin":
|
||||
return (round(value + 273.15), "°K")
|
||||
elif scale == "rankine":
|
||||
return (round(value * 1.8 + 491.67), "°R")
|
||||
else:
|
||||
return (0, "")
|
||||
|
||||
def process_keys():
|
||||
mouse_pos: Tuple[int, int] = (0, 0)
|
||||
filtered: bool = False
|
||||
|
|
Loading…
Reference in New Issue