Improved support for AMD CPU sensors

* K8, K10, and K11? should be treated the same as CoreTemp
  * These are included in osTicket posts
* Cleaned up code for pylint
* Removed unused join_columns() function
This commit is contained in:
2Shirt 2019-05-26 17:40:47 -06:00
parent 9c80c357d6
commit 4912b17bf3
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C
2 changed files with 45 additions and 44 deletions

View file

@ -1557,7 +1557,7 @@ def run_mprime_test(state, test):
# Add temps to report # Add temps to report
test.report.append('{BLUE}Temps{CLEAR}'.format(**COLORS)) test.report.append('{BLUE}Temps{CLEAR}'.format(**COLORS))
for line in generate_sensor_report( for line in generate_sensor_report(
test.sensor_data, 'Idle', 'Max', 'Cooldown', core_only=True): test.sensor_data, 'Idle', 'Max', 'Cooldown', cpu_only=True):
test.report.append(' {}'.format(line)) test.report.append(' {}'.format(line))
# Add abort message(s) # Add abort message(s)

View file

@ -1,4 +1,6 @@
# Wizard Kit: Functions - Sensors '''Wizard Kit: Functions - Sensors'''
# pylint: disable=no-name-in-module,wildcard-import
# vim: sts=2 sw=2 ts=2
import json import json
import re import re
@ -9,7 +11,7 @@ from settings.sensors import *
# Error Classes # Error Classes
class ThermalLimitReachedError(Exception): class ThermalLimitReachedError(Exception):
pass '''Thermal limit reached error.'''
def clear_temps(sensor_data): def clear_temps(sensor_data):
@ -20,28 +22,30 @@ def clear_temps(sensor_data):
_data['Temps'] = [] _data['Temps'] = []
def fix_sensor_str(s): def fix_sensor_str(_s):
"""Cleanup string and return str.""" """Cleanup string and return str."""
s = re.sub(r'^(\w+)-(\w+)-(\w+)', r'\1 (\2 \3)', s, re.IGNORECASE) _s = re.sub(r'^(\w+)-(\w+)-(\w+)', r'\1 (\2 \3)', _s, re.IGNORECASE)
s = s.title() _s = _s.title()
s = s.replace('Coretemp', 'CoreTemp') _s = _s.replace('Coretemp', 'CPUTemp')
s = s.replace('Acpi', 'ACPI') _s = _s.replace('Acpi', 'ACPI')
s = s.replace('ACPItz', 'ACPI TZ') _s = _s.replace('ACPItz', 'ACPI TZ')
s = s.replace('Isa ', 'ISA ') _s = _s.replace('Isa ', 'ISA ')
s = s.replace('Id ', 'ID ') _s = _s.replace('Pci ', 'PCI ')
s = re.sub(r'(\D+)(\d+)', r'\1 \2', s, re.IGNORECASE) _s = _s.replace('Id ', 'ID ')
s = s.replace(' ', ' ') _s = re.sub(r'(\D+)(\d+)', r'\1 \2', _s, re.IGNORECASE)
return s _s = re.sub(r'^K (\d+)Temp', r'AMD K\1 Temps', _s, re.IGNORECASE)
_s = re.sub(r'T(ctl|die)', r'CPU (T\1)', _s, re.IGNORECASE)
return _s
def generate_sensor_report( def generate_sensor_report(
sensor_data, *temp_labels, sensor_data, *temp_labels,
colors=True, core_only=False): colors=True, cpu_only=False):
"""Generate report based on temp_labels, returns list if str.""" """Generate report based on temp_labels, returns list if str."""
report = [] report = []
for _section, _adapters in sorted(sensor_data.items()): for _section, _adapters in sorted(sensor_data.items()):
# CoreTemps then Other temps # CPU temps then Other temps
if core_only and 'Core' not in _section: if cpu_only and 'CPU' not in _section:
continue continue
for _adapter, _sources in sorted(_adapters.items()): for _adapter, _sources in sorted(_adapters.items()):
# Adapter # Adapter
@ -56,7 +60,7 @@ def generate_sensor_report(
': ' if _label != 'Current' else '', ': ' if _label != 'Current' else '',
get_temp_str(_data.get(_label, '???'), colors=colors)) get_temp_str(_data.get(_label, '???'), colors=colors))
report.append(_line) report.append(_line)
if not core_only: if not cpu_only:
report.append(' ') report.append(' ')
# Handle empty reports (i.e. no sensors detected) # Handle empty reports (i.e. no sensors detected)
@ -91,15 +95,15 @@ def get_colored_temp_str(temp):
else: else:
color = COLORS['CLEAR'] color = COLORS['CLEAR']
return '{color}{prefix}{temp:2.0f}°C{CLEAR}'.format( return '{color}{prefix}{temp:2.0f}°C{CLEAR}'.format(
color = color, color=color,
prefix = '-' if temp < 0 else '', prefix='-' if temp < 0 else '',
temp = temp, temp=temp,
**COLORS) **COLORS)
def get_raw_sensor_data(): def get_raw_sensor_data():
"""Read sensor data and return dict.""" """Read sensor data and return dict."""
data = {} json_data = {}
cmd = ['sensors', '-j'] cmd = ['sensors', '-j']
# Get raw data # Get raw data
@ -122,8 +126,8 @@ def get_raw_sensor_data():
try: try:
json_data = json.loads('\n'.join(raw_data)) json_data = json.loads('\n'.join(raw_data))
except json.JSONDecodeError: except json.JSONDecodeError:
# Still broken, just set to empty dict # Still broken, just return the empty dict
json_data = {} pass
# Done # Done
return json_data return json_data
@ -132,10 +136,10 @@ def get_raw_sensor_data():
def get_sensor_data(): def get_sensor_data():
"""Parse raw sensor data and return new dict.""" """Parse raw sensor data and return new dict."""
json_data = get_raw_sensor_data() json_data = get_raw_sensor_data()
sensor_data = {'CoreTemps': {}, 'Other': {}} sensor_data = {'CPUTemps': {}, 'Other': {}}
for _adapter, _sources in json_data.items(): for _adapter, _sources in json_data.items():
if 'coretemp' in _adapter: if is_cpu_adapter(_adapter):
_section = 'CoreTemps' _section = 'CPUTemps'
else: else:
_section = 'Other' _section = 'Other'
sensor_data[_section][_adapter] = {} sensor_data[_section][_adapter] = {}
@ -157,8 +161,8 @@ def get_sensor_data():
} }
# Remove empty sections # Remove empty sections
for k, v in sensor_data.items(): for _k, _v in sensor_data.items():
v = {k2: v2 for k2, v2 in v.items() if v2} _v = {_k2: _v2 for _k2, _v2 in _v.items() if _v2}
# Done # Done
return sensor_data return sensor_data
@ -178,14 +182,20 @@ def get_temp_str(temp, colors=True):
temp) temp)
def is_cpu_adapter(adapter):
"""Checks if adapter is a known CPU adapter, returns bool."""
is_cpu = re.search(r'(core|k\d+)temp', adapter, re.IGNORECASE)
return bool(is_cpu)
def monitor_sensors(monitor_pane, monitor_file): def monitor_sensors(monitor_pane, monitor_file):
"""Continually update sensor data and report to screen.""" """Continually update sensor data and report to screen."""
sensor_data = get_sensor_data() sensor_data = get_sensor_data()
while True: while True:
update_sensor_data(sensor_data) update_sensor_data(sensor_data)
with open(monitor_file, 'w') as f: with open(monitor_file, 'w') as _f:
report = generate_sensor_report(sensor_data, 'Current', 'Max') report = generate_sensor_report(sensor_data, 'Current', 'Max')
f.write('\n'.join(report)) _f.write('\n'.join(report))
sleep(1) sleep(1)
if monitor_pane and not tmux_poll_pane(monitor_pane): if monitor_pane and not tmux_poll_pane(monitor_pane):
break break
@ -196,7 +206,7 @@ def save_average_temp(sensor_data, temp_label, seconds=10):
clear_temps(sensor_data) clear_temps(sensor_data)
# Get temps # Get temps
for i in range(seconds): for _i in range(seconds): # pylint: disable=unused-variable
update_sensor_data(sensor_data) update_sensor_data(sensor_data)
sleep(1) sleep(1)
@ -219,24 +229,15 @@ def update_sensor_data(sensor_data, thermal_limit=None):
_data['Current'] = _temp _data['Current'] = _temp
_data['Max'] = max(_temp, _data['Max']) _data['Max'] = max(_temp, _data['Max'])
_data['Temps'].append(_temp) _data['Temps'].append(_temp)
except Exception: except Exception: # pylint: disable=broad-except
# Dumb workound for Dell sensors with changing source names # Dumb workound for Dell sensors with changing source names
pass pass
# Check if thermal limit reached # Check if thermal limit reached
if thermal_limit and _section == 'CoreTemps': if thermal_limit and _section == 'CPUTemps':
if max(_data['Current'], _data['Max']) >= thermal_limit: if max(_data['Current'], _data['Max']) >= thermal_limit:
raise ThermalLimitReachedError('CoreTemps reached limit') raise ThermalLimitReachedError('CPU temps reached limit')
def join_columns(column1, column2, width=55):
return '{:<{}}{}'.format(
column1,
55+len(column1)-len(REGEX_COLORS.sub('', column1)),
column2)
if __name__ == '__main__': if __name__ == '__main__':
print("This file is not meant to be called directly.") print("This file is not meant to be called directly.")
# vim: sts=2 sw=2 ts=2