Skip to content

Instantly share code, notes, and snippets.

@nicoe
Created July 9, 2019 11:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicoe/31c3c7a0bf15f8d982adea4c8e2fd417 to your computer and use it in GitHub Desktop.
Save nicoe/31c3c7a0bf15f8d982adea4c8e2fd417 to your computer and use it in GitHub Desktop.
A battery block with notification for i3
#!/usr/bin/env python3
#
# Copyright (C) 2016 James Murphy
# Licensed under the GPL version 2 only
#
# A battery indicator blocklet script for i3blocks
import gi
import re
import pathlib
import tempfile
from subprocess import check_output
gi.require_version('Gio', '2.0')
from gi.repository import Gio
SIZE = 32
ICON_PREFIX = pathlib.Path(f'/usr/share/icons/gnome/{SIZE}x{SIZE}/status/')
def notify(new_status):
if not new_status:
return
if 'low' in new_status:
priority = Gio.NotificationPriority.URGENT
message = "Battery LOW"
icon = ICON_PREFIX / 'battery-caution.png'
elif 'charging' in new_status:
priority = Gio.NotificationPriority.NORMAL
message = "Battery charging"
icon = ICON_PREFIX / 'battery-low-charging.png'
elif 'discharging' in new_status:
priority = Gio.NotificationPriority.NORMAL
message = "Battery discharging"
icon = ICON_PREFIX / 'battery-low.png'
else:
priority = Gio.NotificationPriority.LOW
message = "Battery normal"
icon = ICON_PREFIX / 'battery-good.png'
application = Gio.Application.new(
'battery.notification', Gio.ApplicationFlags.FLAGS_NONE)
application.register()
notification = Gio.Notification.new(message)
notification.set_priority(priority)
notification.set_icon(Gio.FileIcon.new(Gio.File.new_for_path(str(icon))))
application.send_notification(None, notification)
def get_status():
tmpdir = pathlib.Path(tempfile.gettempdir()) / 'battery-block'
if not tmpdir.exists():
tmpdir.mkdir()
return set(f.name for f in tmpdir.iterdir())
def set_status(status):
tmpdir = pathlib.Path(tempfile.gettempdir()) / 'battery-block'
if not tmpdir.exists():
tmpdir.mkdir()
try:
(tmpdir / status).touch(exist_ok=False)
except FileExistsError:
pass
try:
if status == 'charging':
(tmpdir / 'discharging').unlink()
elif status == 'discharging':
(tmpdir / 'charging').unlink()
elif status == 'low':
(tmpdir / 'normal').unlink()
elif status == 'normal':
(tmpdir / 'low').unlink()
except FileNotFoundError:
pass
status = check_output(['acpi', '-ab'], universal_newlines=True)
previous_status = get_status()
if not status:
# stands for no battery found
fulltext = "<span color='red'><span font='Font Awesome 5 Free'>\uf00d \uf240</span></span>"
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.splitlines()
state_batteries = []
commasplitstatus_batteries = []
percentleft_batteries = []
time = ""
plugged = False
for battery in batteries:
if not battery:
continue
if battery.startswith('Battery'):
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)
if time:
time = ":".join(time.groups())
timeleft = " ({})".format(time)
else:
timeleft = ""
p = int(commasplitstatus[1].rstrip("%\n"))
if p > 0:
percentleft_batteries.append(p)
commasplitstatus_batteries.append(commasplitstatus)
elif battery.startswith('Adapter'):
plugged = plugged or battery.endswith('on-line')
state = state_batteries[0]
commasplitstatus = commasplitstatus_batteries[0]
if percentleft_batteries:
percentleft = int(
sum(percentleft_batteries) / len(percentleft_batteries))
else:
percentleft = 0
fulltext = ''
if state == "Charging" or plugged:
fulltext += '<span font="Font Awesome 5 Free">\uf0e7</span> '
set_status('charging')
else:
set_status('discharging')
def battery_icon(percent):
if 10 < percent < 30:
color = '#FF3300'
else:
color = '#FFFFFF'
fa = chr(int('f170', 16) + (percent // 10) % 10)
tmpl = '<span color="{}"><span font="Material Design Icons">{}</span></span>'
return tmpl.format(color, fa)
if percentleft < 10:
set_status('low')
else:
set_status('normal')
fulltext += battery_icon(percentleft)
fulltext += timeleft
if previous_status:
notify(get_status() - previous_status)
print(fulltext)
print(fulltext)
if percentleft < 10:
exit(33)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment