#!/usr/bin/env python3 import sys import re from sys import stdout from os import path from collections import namedtuple, OrderedDict from termcolor import colored POWER_CLASS = '/sys/class/power_supply' BATTERY = 'cw2015-battery' UEVENT = path.join(POWER_CLASS, BATTERY, 'uevent') DISCHARNGING = 'Discharging' BatteryInfo = namedtuple( 'BatteryInfo', [ 'name', 'technology', 'capacity', 'status', 'currrent_percent', 'time_to_empty', 'charging_current' ] ) def print_help(): text = """ battery [-h] [-d] [-i] -h ... help -d ... dump all values -i ... short info """.strip() pattern = re.compile(r'^\s+', re.MULTILINE) text = pattern.sub('', text) print(text) def read_battery(filename): with open(filename) as file: lines = file.readlines() items = map(lambda line: line.strip().split('=', 2), lines) return OrderedDict(items) def load_battery_info(info): return BatteryInfo( name = info['POWER_SUPPLY_NAME'], technology = info['POWER_SUPPLY_TECHNOLOGY'], capacity = float(info['POWER_SUPPLY_CHARGE_FULL']) / 1e6, status = info['POWER_SUPPLY_STATUS'], currrent_percent = int(info['POWER_SUPPLY_CAPACITY']), time_to_empty = int(info['POWER_SUPPLY_TIME_TO_EMPTY_NOW']), charging_current = int(float(info['POWER_SUPPLY_CURRENT_NOW']) / 1e3) ) def terminal_colored(text, color): if sys.stdout.isatty(): return colored(text, color) else: return text def format_status(info): color = 'red' if info.status == DISCHARNGING else 'green' return terminal_colored(info.status, color) def format_percent(info): color = 'green' if info.currrent_percent > 30 else 'red' return terminal_colored(f'{info.currrent_percent}%', color) def format_time_to_empty(info): hours = info.time_to_empty // 60 minutes = info.time_to_empty % 60 return terminal_colored(f"{hours}:{minutes:02d}", 'cyan') def print_battery_detail(info): print(f"Battery: {info.technology} {info.name} {info.capacity} Ah") print("Battery level: " + format_percent(info)) print("Battery status: " + format_status(info)) if info.status == DISCHARNGING: time_to_empty = format_time_to_empty(info) print(f"Time to empty: {time_to_empty} [hour:minutes]") print(f"{info.status} current: {info.charging_current} mA") def print_battery_info(info): percent = format_percent(info) status = format_status(info) state = f"level={percent} status={status}" if info.status == DISCHARNGING: time_to_empty = format_time_to_empty(info) state += f" duration={time_to_empty}" print(state) def dump_battery_info(battery): print(f"# {UEVENT}") for key, value in battery.items(): print(f"{key} = {value}") def main(args): battery = read_battery(UEVENT) info = load_battery_info(battery) if '-h' in args: print_help() elif '-d' in args: dump_battery_info(battery) elif '-i' in args: print_battery_info(info) else: print_battery_detail(info) if __name__ == '__main__': main(sys.argv) """ cat /sys/class/power_supply/cw2015-battery/uevent POWER_SUPPLY_NAME=cw2015-battery POWER_SUPPLY_TYPE=Battery POWER_SUPPLY_CAPACITY=100 POWER_SUPPLY_STATUS=Full POWER_SUPPLY_PRESENT=1 POWER_SUPPLY_VOLTAGE_NOW=4314000 POWER_SUPPLY_TIME_TO_EMPTY_NOW=0 POWER_SUPPLY_TECHNOLOGY=Li-ion POWER_SUPPLY_CHARGE_FULL=9800000 POWER_SUPPLY_CHARGE_FULL_DESIGN=9800000 POWER_SUPPLY_CURRENT_NOW=0 """