#!/usr/bin/env python import json import os import subprocess import sys _BITS = [] def _bit(idx): def wrapper(func): _BITS.append([idx, func.__name__.replace('_', ''), func]) return func return wrapper @_bit(6) def _mem(): with open('/proc/meminfo') as meminfo_fp: attrs = {} for line in meminfo_fp.readlines(): parts = line.split(':', 2) attrs[parts[0].strip()] = parts[1].strip() avail = int(attrs['MemAvailable'].split()[0]) total = int(attrs['MemTotal'].split()[0]) used = int(((total - avail) / total) * 100) color = None if used > 75: color = '#ff0000' if used < 25: color = '#00ff00' return 'M:{}%'.format(used), color @_bit(0) def _backlight(dev_dir='/sys/class/backlight/intel_backlight'): with open('{}/brightness'.format(dev_dir)) as br_fp: with open('{}/max_brightness'.format(dev_dir)) as mb_fp: value = int(br_fp.read().strip()) max_value = int(mb_fp.read().strip()) pct = int(float(float(value) / float(max_value)) * 100) color = None if pct >= 75: color = '#ffaa00' if pct <= 25: color = '#5599ff' return '☼:{}%'.format(pct), color THINKFAN_CONF = '/etc/thinkfan.conf' ACPI_IBM_FAN = '/proc/acpi/ibm/fan' @_bit(7) def _hwtemp(conf=THINKFAN_CONF, fan=ACPI_IBM_FAN): if not os.path.exists(conf): return None, None temps = [] with open('/etc/thinkfan.conf') as tfc_fp: for line in tfc_fp.readlines(): if not line.startswith('hwmon '): continue try: with open(line.split(' ')[1].strip()) as temp_fp: temps.append(float(temp_fp.read())) except (OSError, IOError) as exc: sys.stderr.write(str(exc) + '\n') avg_temp = float(sum(temps)) / len(temps) / 1000.0 color = None fan_level = 'unset' try: with open(fan) as fan_fp: for line in fan_fp.readlines(): if not line.startswith('level:\t\t'): continue fan_level = int(line.replace('level:\t\t', '')) except (OSError, IOError) as exc: sys.stderr.write(str(exc) + '\n') if avg_temp > 75: color = '#ff0000' if avg_temp >= 50: color = '#ffaa00' if avg_temp <= 25: color = '#5599ff' return 'T:{:.1f}°C L:{}'.format(avg_temp, fan_level), color def _print_line(message): sys.stdout.write(message + '\n') sys.stdout.flush() def _read_line(): try: line = sys.stdin.readline().strip() if not line: sys.exit(3) return line except KeyboardInterrupt: sys.exit() def main(bits=_BITS): _print_line(_read_line()) _print_line(_read_line()) while True: line, prefix = _read_line(), '' if line.startswith(','): line, prefix = line[1:], ',' loaded = json.loads(line) for idx, name, func in bits: try: value, color = func() if value is None: continue record = dict(full_text=str(value), name=name) if color is not None: record.update(dict(color=color)) loaded.insert(idx, record) except Exception as exc: sys.stderr.write(str(exc) + '\n') sys.stderr.flush() _print_line(prefix+json.dumps(loaded)) if __name__ == '__main__': main()