-
Notifications
You must be signed in to change notification settings - Fork 485
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
battery2: change battery symbol when discharging
- according to its level - popup notification when battery level < threshold - formatting
- Loading branch information
Showing
10 changed files
with
168 additions
and
82 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,106 +1,153 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# Copyright (C) 2016 James Murphy | ||
# 2024 Gregory David | ||
# Licensed under the GPL version 2 only | ||
# | ||
# A battery indicator blocklet script for i3blocks | ||
|
||
from subprocess import check_output | ||
import os | ||
import re | ||
import sys | ||
from subprocess import CalledProcessError, check_output | ||
from typing import Dict | ||
|
||
config = dict(os.environ) | ||
status = check_output(['acpi'], universal_newlines=True) | ||
|
||
if not status: | ||
# stands for no battery found | ||
color = config.get("color_10", "red") | ||
fulltext = "<span color='{}'><span font='FontAwesome'>\uf00d \uf240</span></span>".format(color) | ||
percentleft = 100 | ||
else: | ||
# if there is more than one battery in one laptop, the percentage left is | ||
# available for each battery separately, although state and remaining | ||
# time for overall block is shown in the status of the first battery | ||
batteries = status.split("\n") | ||
state_batteries=[] | ||
commasplitstatus_batteries=[] | ||
percentleft_batteries=[] | ||
time = "" | ||
for battery in batteries: | ||
if battery!='': | ||
CONFIG = dict(os.environ) | ||
DISCHARGE_LEVEL = { | ||
90: CONFIG.get("discharge_90", "\uf240"), | ||
75: CONFIG.get("discharge_75", "\uf241"), | ||
50: CONFIG.get("discharge_50", "\uf242"), | ||
25: CONFIG.get("discharge_25", "\uf243"), | ||
10: CONFIG.get("discharge_10", "\uf244"), | ||
} | ||
COLOR_LEVEL = { | ||
90: CONFIG.get("color_90", "#FFFFFF"), | ||
80: CONFIG.get("color_80", "#FFFF66"), | ||
70: CONFIG.get("color_70", "#FFFF33"), | ||
60: CONFIG.get("color_60", "#FFFF00"), | ||
50: CONFIG.get("color_50", "#FFCC00"), | ||
40: CONFIG.get("color_40", "#FF9900"), | ||
30: CONFIG.get("color_30", "#FF6600"), | ||
20: CONFIG.get("color_20", "#FF3300"), | ||
10: CONFIG.get("color_10", "#FFFFFF"), | ||
} | ||
WARNING_THRESHOLD = int(CONFIG.get("warning_threshold", 10)) | ||
COLOR_CHARGING = CONFIG.get("color_charging", "yellow") | ||
COLOR_NO_BATTERY = CONFIG.get("color_no_battery", "red") | ||
|
||
|
||
def value_for_level(percent: int, level_mapping: Dict[int, str]): | ||
"""Get symbol associated to a level percentage.""" | ||
levels = sorted(level_mapping.items(), reverse=True) | ||
for lvl, sym in levels: | ||
if lvl <= percent: | ||
return sym | ||
return levels[-1][1] | ||
|
||
|
||
def discharge_level(percent: int): | ||
"""Get battery symbol for given level percentage.""" | ||
return value_for_level(percent, DISCHARGE_LEVEL) | ||
|
||
|
||
def color_level(percent: int): | ||
"""Get color for given level percentage.""" | ||
return value_for_level(percent, COLOR_LEVEL) | ||
|
||
|
||
def battery2(): | ||
"""Main entry point.""" | ||
try: | ||
status = check_output(["acpi", "-b"], universal_newlines=True) | ||
except (FileNotFoundError, CalledProcessError): | ||
status = None | ||
|
||
if not status: | ||
percentleft = 100 | ||
content = discharge_level(percentleft) | ||
if status is None: | ||
content = "no ACPI process" | ||
fulltext = f"<span color='{COLOR_NO_BATTERY}' font='FontAwesome'>\uf00d {content}</span>" | ||
shorttext = fulltext | ||
else: | ||
# if there is more than one battery in one laptop, the percentage left is | ||
# available for each battery separately, although state and remaining | ||
# time for overall block is shown in the status of the first battery | ||
batteries = status.split("\n") | ||
state_batteries = [] | ||
commasplitstatus_batteries = [] | ||
percentleft_batteries = [] | ||
time = "" | ||
for battery in batteries: | ||
if not battery: | ||
continue | ||
state_batteries.append(battery.split(": ")[1].split(", ")[0]) | ||
commasplitstatus = battery.split(", ") | ||
if not time: | ||
time = commasplitstatus[-1].strip() | ||
# check if it matches a time | ||
time = re.match(r"(\d+):(\d+)", time) | ||
timeleft = "" | ||
if time: | ||
time = ":".join(time.groups()) | ||
timeleft = " ({})".format(time) | ||
else: | ||
timeleft = "" | ||
timeleft = f"({time})" | ||
|
||
p = int(commasplitstatus[1].rstrip("%\n")) | ||
if p>0: | ||
if p > 0: | ||
percentleft_batteries.append(p) | ||
commasplitstatus_batteries.append(commasplitstatus) | ||
state = state_batteries[0] | ||
commasplitstatus = commasplitstatus_batteries[0] | ||
if percentleft_batteries: | ||
percentleft = int(sum(percentleft_batteries)/len(percentleft_batteries)) | ||
else: | ||
state = state_batteries[0] | ||
commasplitstatus = commasplitstatus_batteries[0] | ||
percentleft = 0 | ||
if percentleft_batteries: | ||
percentleft = int(sum(percentleft_batteries) / len(percentleft_batteries)) | ||
|
||
# stands for charging | ||
color = config.get("color_charging", "yellow") | ||
FA_LIGHTNING = "<span color='{}'><span font='FontAwesome'>\uf0e7</span></span>".format(color) | ||
fa_plugged_in = "<span font='FontAwesome'>\uf1e6</span>" | ||
fa_battery = f"<span font='FontAwesome'>{discharge_level(percentleft)}</span>" | ||
|
||
# stands for plugged in | ||
FA_PLUG = "<span font='FontAwesome'>\uf1e6</span>" | ||
output = [] | ||
if state == "Discharging": | ||
output.append(f"{fa_battery}") | ||
elif state in ["Full", "Not charging"]: | ||
timeleft = "" | ||
output.append(f"{fa_plugged_in}") | ||
elif state == "Charging": | ||
output.append( | ||
f"<span color='{COLOR_CHARGING}' font='FontAwesome'>\uf0e7</span>" | ||
) | ||
output.append(fa_plugged_in) | ||
else: | ||
# stands for unknown status of battery | ||
timeleft = "" | ||
output.append("<span font='FontAwesome'>\uf128</span>") | ||
output.append(fa_battery) | ||
|
||
# stands for using battery | ||
FA_BATTERY = "<span font='FontAwesome'>\uf240</span>" | ||
output.append(f"<span color='{color_level(percentleft)}'>{percentleft}%</span>") | ||
shorttext = " ".join(output) | ||
output.append(timeleft) | ||
fulltext = " ".join(output) | ||
|
||
# stands for unknown status of battery | ||
FA_QUESTION = "<span font='FontAwesome'>\uf128</span>" | ||
print(fulltext) | ||
print(shorttext) | ||
|
||
if percentleft < WARNING_THRESHOLD and state != "Charging": | ||
check_output( | ||
[ | ||
"notify-send", | ||
"-u", | ||
"critical", | ||
"-a", | ||
"i3blocks.battery2", | ||
"-t", | ||
"0", | ||
"Warning", | ||
f"Battery level <b>{percentleft}%</b> is below <b>{WARNING_THRESHOLD}%</b>, plug power or suspend system", | ||
] | ||
) | ||
# exit code 33 will turn background red | ||
return 33 | ||
return 0 | ||
|
||
if state == "Discharging": | ||
fulltext = FA_BATTERY + " " | ||
elif state == "Full": | ||
fulltext = FA_PLUG + " " | ||
timeleft = "" | ||
elif state == "Unknown": | ||
fulltext = FA_QUESTION + " " + FA_BATTERY + " " | ||
timeleft = "" | ||
else: | ||
fulltext = FA_LIGHTNING + " " + FA_PLUG + " " | ||
|
||
def color(percent): | ||
if percent < 10: | ||
# exit code 33 will turn background red | ||
return config.get("color_10", "#FFFFFF") | ||
if percent < 20: | ||
return config.get("color_20", "#FF3300") | ||
if percent < 30: | ||
return config.get("color_30", "#FF6600") | ||
if percent < 40: | ||
return config.get("color_40", "#FF9900") | ||
if percent < 50: | ||
return config.get("color_50", "#FFCC00") | ||
if percent < 60: | ||
return config.get("color_60", "#FFFF00") | ||
if percent < 70: | ||
return config.get("color_70", "#FFFF33") | ||
if percent < 80: | ||
return config.get("color_80", "#FFFF66") | ||
return config.get("color_full", "#FFFFFF") | ||
|
||
form = '<span color="{}">{}%</span>' | ||
fulltext += form.format(color(percentleft), percentleft) | ||
fulltext += timeleft | ||
|
||
print(fulltext) | ||
print(fulltext) | ||
if percentleft < 10: | ||
exit(33) | ||
|
||
if __name__ == "__main__": | ||
sys.exit(battery2()) |
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
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.