103 lines
2.9 KiB
Python
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 plyer.facades import Battery
|
||
|
from 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()
|