Sideband/sbapp/plyer/platforms/linux/battery.py
2024-06-02 18:31:58 +02:00

103 lines
2.9 KiB
Python

'''
Module of Linux API for plyer.battery.
'''
from math import floor
from os import environ
from os.path import exists, join
from subprocess import Popen, PIPE
from sbapp.plyer.facades import Battery
from sbapp.plyer.utils import whereis_exe
class LinuxBattery(Battery):
'''
Implementation of Linux battery API via accessing the sysclass power_supply
path from the kernel.
'''
def _get_state(self):
status = {"isCharging": None, "percentage": None}
kernel_bat_path = join('/sys', 'class', 'power_supply', 'BAT0')
uevent = join(kernel_bat_path, 'uevent')
with open(uevent) as fle:
lines = [
line.decode('utf-8').strip()
for line in fle.readlines()
]
output = {
line.split('=')[0]: line.split('=')[1]
for line in lines
}
is_charging = output['POWER_SUPPLY_STATUS'] == 'Charging'
total = float(output['POWER_SUPPLY_CHARGE_FULL'])
now = float(output['POWER_SUPPLY_CHARGE_NOW'])
capacity = floor(now / total * 100)
status['percentage'] = capacity
status['isCharging'] = is_charging
return status
class UPowerBattery(Battery):
'''
Implementation of UPower battery API.
'''
def _get_state(self):
# if no LANG specified, return empty string
old_lang = environ.get('LANG', '')
environ['LANG'] = 'C'
status = {"isCharging": None, "percentage": None}
# We are supporting only one battery now
# this will fail if there is no object with such path,
# however it's safer than 'upower -d' which provides
# multiple unrelated 'state' and 'percentage' keywords
dev = "/org/freedesktop/UPower/devices/battery_BAT0"
upower_process = Popen(
["upower", "--show-info", dev],
stdout=PIPE
)
output = upower_process.communicate()[0].decode()
environ['LANG'] = old_lang
if not output:
return status
state = percentage = None
for line in output.splitlines():
if 'state' in line:
state = line.rpartition(':')[-1].strip()
if 'percentage' in line:
percentage = line.rpartition(':')[-1].strip()[:-1]
# switching decimal comma to dot
# (different LC_NUMERIC locale)
percentage = float(
percentage.replace(',', '.')
)
if state:
status['isCharging'] = state == "charging"
status['percentage'] = percentage
return status
def instance():
'''
Instance for facade proxy.
'''
import sys
if whereis_exe('upower'):
return UPowerBattery()
sys.stderr.write("upower not found.")
if exists(join('/sys', 'class', 'power_supply', 'BAT0')):
return LinuxBattery()
return Battery()