Sideband/sbapp/plyer/platforms/linux/battery.py

103 lines
2.9 KiB
Python
Raw Normal View History

2022-09-16 10:07:57 -06:00
'''
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
2024-06-02 10:31:58 -06:00
from sbapp.plyer.facades import Battery
from sbapp.plyer.utils import whereis_exe
2022-09-16 10:07:57 -06:00
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}
2024-06-02 10:31:58 -06:00
kernel_bat_path = join('/sys', 'class', 'power_supply', 'BAT0')
2022-09-16 10:07:57 -06:00
uevent = join(kernel_bat_path, 'uevent')
2024-06-02 10:31:58 -06:00
with open(uevent) as fle:
2022-09-16 10:07:57 -06:00
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'
2024-06-02 10:31:58 -06:00
total = float(output['POWER_SUPPLY_CHARGE_FULL'])
now = float(output['POWER_SUPPLY_CHARGE_NOW'])
2022-09-16 10:07:57 -06:00
2024-06-02 10:31:58 -06:00
capacity = floor(now / total * 100)
status['percentage'] = capacity
2022-09-16 10:07:57 -06:00
status['isCharging'] = is_charging
return status
2024-06-02 10:31:58 -06:00
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
2022-09-16 10:07:57 -06:00
def instance():
'''
Instance for facade proxy.
'''
import sys
2024-06-02 10:31:58 -06:00
if whereis_exe('upower'):
return UPowerBattery()
sys.stderr.write("upower not found.")
2022-09-16 10:07:57 -06:00
2024-06-02 10:31:58 -06:00
if exists(join('/sys', 'class', 'power_supply', 'BAT0')):
return LinuxBattery()
2022-09-16 10:07:57 -06:00
return Battery()