Python + Linux индикатор заряда батареи

On: 17 февраля 2011 г.

Недавно разбирался с определением времени продолжительности работы ноутбука от батареи средствами простой православной консоли. Но на этом дело не закончилось. Обретя эти знания я задался вопросом написания индикатора заряда батареи ноутбука на python-е. Для того что бы получить возможность узнавать данные про батарею от acpi необходимо подключить (раза во или при загрузке) модуль battery

Разовый запуск:

# modprobe battery

С включением это модуля появиться каталог /proc/acpi/battery. В котором будут располагаться каталоги всех присутствующих батарей. У меня ноутбук и появилась только одна папка BAT0. В это папке находятся такие файлы: alarm, info, state. Файл alarm содержит информацию о предупреждении о низком заряде баттареи и потому его описывать я не стану. Расмотрим два остальных файла:



$ cat /proc/acpi/battery/BAT0/info
present:                 yes
design capacity:         52800 mWh
last full capacity:      28952 mWh
battery technology:      rechargeable
design voltage:          11100 mV
design capacity warning: 5280 mWh
design capacity low:     2640 mWh
cycle count:          0
capacity granularity 1:  528 mWh
capacity granularity 2:  528 mWh
model number:            A8---24
serial number:           
battery type:            LIon
OEM info:                ASUSTEK

Для расчета продолжительности работы ноутбука от батареи мы будем использовать следующую строку (про предназначение других можно и самому догадаться):

  • last full capacity - последняя максимальная емкость батареи

С этим файлов все рассмотрим второй

$ cat /proc/acpi/battery/BAT0/state

present:                 yes
capacity state:          ok
charging state:          charged
present rate:            0 mW
remaining capacity:      28952 mWh
present voltage:         12377 mV

строки которые нам понадобятся:

  • charging state - строка указывающая на то в каком режиме работает батарея (заряжается, заряжена, используется)
  • present rate - собственно "нагрузка" (потребляемая мощность ноутбука во время работы от батарее)
  • remaining capacity - текущая емкость батареи

Теперь арифметические преобразования:

Для вычисления процента зарядки батареи ноутбука необходимо разделить значение текущей емкости (remaining capacity) из файла state с значением последней максимальной емкости (last full capacity) из файла info
полученное число умножим на 100. Таким образом получаем значение (в процентах) уровня заряда батареи.

Для получение значения времени которое осталось работать ноутбуку при текущей нагрузки от батареи необходимо взять значение текущей емкости (remaining capacity) из файла state и разделить его на значение текущей нагрузки на батарею (present rate) из файла state. Вы получите количество часов работы от батареи при текущей нагрузке. Что бы получить значение минут необходимо остаток от этого деления и поделить на значение текущей нагрузки на батарею (present rate) из файла state умноженное на 60.

(если после деления и умножения на 100 при полном заряде батареи 100 процентов не получается то советую провести калибровку батареи средствами BIOS либо вручную пару раз разрядить ноутбук до такого состояния что он сам отключиться и зарядить до максимума) 

Все выше сказанное в тексте программы:

#!/usr/bin/python2
# -*- coding: utf-8 -*-

import os
import re
import gtk
import time
import threading
import subprocess

path = '/proc/acpi/battery'
def battery_life():
    rate = {}
    if os.path.isdir(path):
        for i in os.listdir(path):
            if os.path.isdir(path + '/' + i):
                try: f = open(path + '/' + i + '/info', 'r')
                except: return None
                else:
                    fr = f.read()
                    f.close()
                    r = re.search(r'last full capacity:.*', fr).group()
                    last_full_capacity = int(re.search(r'\d+', r).group())
                try: f = open(path + '/' + i + '/state', 'r')
                except: return None
                else:
                    fr = f.read()
                    r = re.search(r'charging state:.*', fr).group()[16:]
                    charging_state = re.search(r'\S+', r).group()
                    r = re.search(r'present rate:.*', fr).group()
                    present_rate = int(re.search(r'\d+', r).group())
                    r = re.search(r'remaining capacity:.*', fr).group()
                    remaining_capacity = int(re.search(r'\d+', r).group())
                    f.close()
                rate[i] = []
                if charging_state == 'charging':
                    rate[i].append('зарядка')
                elif charging_state == 'charged':
                    rate[i].append('заряжено')
                else:
                    rate[i].append('')
               
                rate[i].append(int((float(remaining_capacity) / float(last_full_capacity)) * 100))
                if present_rate == 0:
                    rate[i].append('')
                else:
                    hours = int(float(remaining_capacity) * 1.0 / float(present_rate) * 1.0)
                    minutes = int(((float(remaining_capacity) % float(present_rate)) / float(present_rate)) * 60)
                    rate[i].append(str(hours).zfill(2) + ':' + str(minutes).zfill(2))
                return rate

def bat():
    gtk.gdk.threads_enter()
    pixb = gtk.icon_theme_get_default().load_icon('notification-battery-100-plugged', 22, gtk.ICON_LOOKUP_USE_BUILTIN)
    icon = gtk.status_icon_new_from_pixbuf(pixb)
    gtk.gdk.threads_leave()
    now = []
    while 1:
        now_old = now   
        now = battery_life()
        now = now[now.keys()[0]]
        if now != now_old:
            if now[0] == 'зарядка' or now[0] == 'заряжено':
                plugged = '-plugged'
            else:
                plugged = ''
               
            if now[1] <= 100 and now[1] >= 90:
                prc = '100'
            elif now[1] < 90 and now[1] >= 70:
                prc = '080'
            elif now[1] < 70 and now[1] >= 50:
                prc = '060'
            elif now[1] < 50 and now[1] >= 30:
                prc = '040'
            elif now[1] < 30 and now[1] >= 10:
                prc = '020'
            else:
                prc = '000'
            gtk.gdk.threads_enter()
            pixb = gtk.icon_theme_get_default().load_icon('notification-battery-' + prc + plugged, 22, gtk.ICON_LOOKUP_USE_BUILTIN)
            icon.set_from_pixbuf(pixb)
            gtk.gdk.threads_leave()
        time.sleep(4)

def main():
    gtk.gdk.threads_init()
    t = threading.Timer(1, bat)
    t.start()
    gtk.gdk.threads_enter()
    gtk.main()
    gtk.gdk.threads_leave()
    return 0

if __name__ == '__main__':
    main()

Эта программа выбрасывает иконку в трей. Программа была написана для темы иконок Imperfection в которой есть неплохой набор иконок индикации батареи начинающихся с notification-battery-*. Так же этот пример показывает как работать в gtk с потоками. В принцепе все. Длительного вам времени работы от батареи:)

P.S. Мое приложение, которое я поддерживаю скачать 


Оригинал и более новую версию статьи Вы найдете здесь.

0 коммент. on "Python + Linux индикатор заряда батареи"