From b132530fd8901e0b503855f8429c2c02b563b598 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 12 Jun 2014 22:18:12 +0200 Subject: add cpuinfo with example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- TODO | 1 + examples/plugins/cpuinfo | 44 +++++++++++++++ src/plugins/cpuinfo.py | 142 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 examples/plugins/cpuinfo create mode 100644 src/plugins/cpuinfo.py diff --git a/TODO b/TODO index ab6d1e2..8a8e191 100644 --- a/TODO +++ b/TODO @@ -17,6 +17,7 @@ List of plugins to implement: Backlight control hdparm Thermal monitoring + kernel console output ESSID and link quality for wireless interfaces News feed syndication Keyboard layout diff --git a/examples/plugins/cpuinfo b/examples/plugins/cpuinfo new file mode 100644 index 0000000..9bb7d79 --- /dev/null +++ b/examples/plugins/cpuinfo @@ -0,0 +1,44 @@ +# -*- python -*- + +# A xpybar configuration example testing the features of plugins.cpuinfo + +import time +import threading + +from plugins.cpuinfo import CPUInfo +from plugins.clock import Clock + + +OUTPUT, HEIGHT, YPOS, TOP = 0, 12, 24, True + + +clock = Clock(sync_to = 2.5 * Clock.SECONDS) + +start_ = start +def start(): + start_() + async(lambda : clock.continuous_sync(lambda : bar.invalidate())) + + +def redraw(): + cpuinfo_ = CPUInfo() + count = len(cpuinfo_.cpus) + def read(cpu): + cur = float(cpuinfo_.get(cpu, CPUInfo.CURRENT_FREQUENCY)) + min = 0 + max = float(cpuinfo_.get(cpu, CPUInfo.MAXIMUM_FREQUENCY)) + p = (cur - min) / (max - min) + if p < 0.50: + c = '32' + elif p < 0.85: + c = '39' + elif p < 0.95: + c = '33' + else: + c = '31' + return '\033[%sm%2i\033[39m%%' % (c, int(p * 100)) + text = 'Freq: %s' % ', '.join(read(cpu) for cpu in range(count)) + + bar.clear() + bar.draw_coloured_text(0, 10, 0, 2, text) + diff --git a/src/plugins/cpuinfo.py b/src/plugins/cpuinfo.py new file mode 100644 index 0000000..d6cfc7d --- /dev/null +++ b/src/plugins/cpuinfo.py @@ -0,0 +1,142 @@ +# -*- python -*- +''' +xpybar – xmobar replacement written in python +Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + + +class CPUInfo: # TODO enable setting scaling + ''' + Data from /proc/cpuinfo and /sys/devices/system/cpu + + @variable cpus:list> Information about each CPU + ''' + + + BIOS_FREQUENCY_LIMIT = 'cpufreq/bios_limit' + ''' + CPU frequency limit per BIOS, in kHz + + @mapping int + ''' + + SCALING_GOVERNOR = 'cpufreq/scaling_governor' + ''' + CPU frequency scaling governor + + @mapping str + ''' + + CPU_TRANSITION_LATENCY = 'cpufreq/cpuinfo_transition_latency' + ''' + CPU transition latency, in ns + + @mapping int + ''' + + AVAILABLE_FREQUENCIES = 'cpufreq/scaling_available_frequencies' + ''' + Available CPU scaling frequencies, in kHz + + @mapping itr + ''' + + SCALING_DRIVER = 'cpufreq/scaling_driver' + ''' + CPU frequency scaling driver + + @mapping str + ''' + + AVAILABLE_SCALING_GOVERNORS = 'cpufreq/scaling_available_governors' + ''' + Available CPU frequency scaling governor + + @mapping itr + ''' + + CURRENT_FREQUENCY = 'cpufreq/cpuinfo_cur_freq' + MINIMUM_FREQUENCY = 'cpufreq/cpuinfo_min_freq' + MAXIMUM_FREQUENCY = 'cpufreq/cpuinfo_max_freq' + CURRENT_SCALING_FREQUENCY = 'cpufreq/scaling_cur_freq' + MINIMUM_SCALING_FREQUENCY = 'cpufreq/scaling_min_freq' + MAXIMUM_SCALING_FREQUENCY = 'cpufreq/scaling_max_freq' + # TODO more CPU info + #'cpufreq/affected_cpus' + #'cpufreq/related_cpus' + #'cpufreq/scaling_setspeed' + #cache/ + #power/ + #topology/ + #thermal_throttle + #/sys/devices/system/cpu/cpufreq/ + #/sys/devices/system/cpu/cpuidle/ + #/sys/devices/system/cpu/power/ + + + + def __init__(self): + ''' + Constructor + ''' + cpuinfo = None + with open('/proc/cpuinfo', 'rb') as file: + cpuinfo = file.read() + cpuinfo = cpuinfo.decode('utf-8', 'replace').replace('\t', '') + cpuinfo = filter(lambda cpu : not cpu == '', cpuinfo.split('\n\n')) + + def f(line): + cols = line.split(': ') + key, value = cols[0].replace('_', ' '), ': '.join(cols[1:]) + return (key, value) + self.cpus = [dict(f(line) for line in cpu.split('\n') if ': ' in line) for cpu in cpuinfo] + + + def __contains__(self, key): + ''' + Get whether or not a key is available for any CPU + + @param key:str The key + @return :bool The availability + ''' + return any(map(key in self.cpus, self.cpus)) + + + def __getitem__(self, key): + ''' + Look up a field from '/proc/cpuinfo' for each CPU + + @param key:str The key + @return :list The value associated with the key for each CPU, `None` where missing + ''' + return [cpu[key] if key in cpu else None for cpu in self.cpus] + + + def get(self, cpu, data): + ''' + Read a information from sysfs for a CPU + + @param cpu:int The index of the CPU + @param data:str The file inside the CPU's directory + @return :str The content of the file + ''' + if data == CPUInfo.CURRENT_FREQUENCY: + return str(int(float(self['cpu MHz'][cpu]) * 1000)) + path = '/sys/devices/system/cpu/cpu%i/%s' % (cpu, data) + with open(path, 'rb') as file: + cont = file.read().decode('utf-8', 'replace').rstrip('\n') + return cont + -- cgit v1.2.3-70-g09d2