Last active
January 10, 2023 16:04
-
-
Save lloeki/2630561 to your computer and use it in GitHub Desktop.
Battery status script for Mac OS X
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from __future__ import print_function | |
from __future__ import division | |
from subprocess import Popen, PIPE | |
def ioreg_battery_info(): | |
output = Popen(["ioreg", "-r", "-k", "LegacyBatteryInfo", "-w", "0"], stdout=PIPE).communicate()[0] | |
try: #python3 | |
return str(output, encoding='utf-8') | |
except TypeError: #python2 | |
return output | |
def parse_ioreg_dict(output): | |
return dict( | |
[ (kw.strip().strip('"'), vw.strip()) | |
for kw, vw | |
in [ line.split("=", 1) | |
for line | |
in output.split('\n') if line.find('=')>0 | |
] | |
] | |
) | |
def is_two_complement_negative(value): | |
return value > (2**63-1) | |
def two_complement(value): | |
return 2**64 - value | |
def fix_negative(value): | |
if is_two_complement_negative(value): | |
return -two_complement(value) | |
else: | |
return value | |
def ioreg_battery_dict(): | |
output = ioreg_battery_info() | |
return parse_ioreg_dict(output) | |
def fix_integer(string): | |
return fix_negative(int(string)) | |
def format_time(string): | |
minutes = int(string) | |
if minutes == 65535: | |
return None | |
else: | |
return "%s:%s" % (minutes//60, minutes%60) | |
def percentage(ratio): | |
return "%s%%" % (int(ratio*100)) | |
humanize_index = { | |
"TimeRemaining": format_time, | |
"AvgTimeToEmpty": format_time, | |
"AvgTimeToFull": format_time, | |
"InstantTimeToEmpty": format_time, | |
"FullToEmptyTime": format_time, | |
"WearRatio": percentage, | |
"ChargeRatio": percentage, | |
} | |
def humanize_data(k, v): | |
if k in humanize_index: | |
return humanize_index[k](v) | |
else: | |
return v | |
def wear_ratio(info): | |
return int(info["MaxCapacity"]) / int(info["DesignCapacity"]) | |
def charge_ratio(info): | |
return int(info["CurrentCapacity"]) / int(info["MaxCapacity"]) | |
def full_to_empty_time(info): | |
if get_data(info, "Amperage") < 0: | |
return -int(info["MaxCapacity"])*60 / get_data(info, "Amperage") | |
else: | |
return 65535 | |
synthetize_index = { | |
"Amperage": lambda i: fix_integer(i["Amperage"]), | |
"InstantAmperage": lambda i: fix_integer(i["InstantAmperage"]), | |
"WearRatio": wear_ratio, | |
"ChargeRatio": charge_ratio, | |
"FullToEmptyTime": full_to_empty_time, | |
} | |
def synthetize_data(battery_info, k): | |
if k in synthetize_index: | |
return synthetize_index[k](battery_info) | |
def get_data(battery_info, k): | |
if k in synthetize_index: | |
return synthetize_data(battery_info, k) | |
elif k in battery_info: | |
return battery_info[k] | |
else: | |
raise KeyError("%s" % k) | |
keys_to_show = [ | |
"Temperature", | |
"CycleCount", | |
#"DesignCycleCount9C", | |
"DesignCapacity", | |
"MaxCapacity", | |
"WearRatio", | |
"CurrentCapacity", | |
"ChargeRatio", | |
"Voltage", | |
"Amperage", | |
"InstantAmperage", | |
"InstantTimeToEmpty", | |
"TimeRemaining", | |
"AvgTimeToEmpty", | |
"AvgTimeToFull", | |
"FullToEmptyTime", | |
] | |
def print_key_value(k, v): | |
if v is not None: | |
print("%s = %s" % (k, v)) | |
battery_info = ioreg_battery_dict() | |
for k in keys_to_show: | |
print_key_value(k, humanize_data(k, get_data(battery_info, k))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment