Files
linux-workspace/bin/battery
2022-07-19 13:49:53 +02:00

179 lines
4.0 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import re
from sys import stdout
from os import path, environ
from os.path import join, isdir
from collections import namedtuple, OrderedDict
POWER_CLASS = '/sys/class/power_supply'
BATTERIES = (
environ.get('BATTERY', 'BAT0'),
'cw2015-battery'
)
DISCHARNGING = 'Discharging'
RESET = '0'
RED = '0;31'
GREEN = '0;32'
YELLOW = '0;33'
BLUE = '0;34'
MAGENTA = '0;35'
CYAN = '0;36'
BatteryInfo = namedtuple(
'BatteryInfo',
[
'name',
'model',
'manufacturer',
'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 find_battery_uevent(batteries):
for battery in batteries:
path = join(POWER_CLASS, battery)
if isdir(path):
return join(path, 'uevent')
return None
def start_color(color):
return '\033[' + color + 'm'
def colored(text, color):
return start_color(color) + text + start_color(RESET)
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'],
model = info['POWER_SUPPLY_MODEL_NAME'],
manufacturer = info['POWER_SUPPLY_MANUFACTURER'],
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.get('POWER_SUPPLY_TIME_TO_EMPTY_NOW', 0)),
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):
if info.time_to_empty == 0:
return '??:??'
else:
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.model} - {info.manufacturer}: {info.technology} {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(uevent, battery):
print(f"# {uevent}")
for key, value in battery.items():
print(f"{key} = {value}")
def main(args):
uevent = find_battery_uevent(BATTERIES)
if not uevent:
print("No battery found")
return
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(uevent, 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
"""