File: battery.py

package info (click to toggle)
python-osd 0.2.14-5.1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 144 kB
  • sloc: ansic: 447; python: 298; makefile: 47
file content (157 lines) | stat: -rw-r--r-- 4,835 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env python
#
# Copyright (C) Damien Elmes <resolve@repose.cx>, 2001.
# This file is licensed under the GPL. Please see COPYING for more details.
#


"""
Display battery usage information and monitor for low available battery.

The default warn and shutdown percentages are very conservative, due
to a badly designed Compaq laptop I own which 'loses' 10% of the total
capacity if allowed to fully discharge. Ideally the info file's
warning and low capacity information should be used instead.
"""

# percentage when a warning should appear
THRESHOLD_WARN = 11
# percentage when the computer should be automatically shut down
THRESHOLD_SHUTDOWN = 9
# total battery capacity (if acpi doesn't know this value)
TOTAL_CAPACITY = 3736.0

ACPI_PROC_DIR = "/proc/acpi/battery/"
STATE_FILE = "state"
INFO_FILE = "info"

import commands
import os
import re
import string
import pyosd, pyosd.daemon as pyd

class BatteryStatus:
    """Provides battery status information.

    Provides status information such as the charging state and
    remaining capacity. Usage:

       bs = BatteryStatus()
       bs.check()
       print bs.availablePercentage"""


    def __init__(self, battery="BAT0"):
        """The battery argument can be used to specify a particular battery to
        use, otherwise the first one will be used."""

        self.batteryPath = os.path.join(ACPI_PROC_DIR, battery)
        stateFilePath = os.path.join(self.batteryPath, STATE_FILE)

        try:
            self.stateFile = open(stateFilePath)
        except:
            raise "Couldn't open battery state file: %s" % \
                  stateFilePath

        self.findTotalCapacity()

    def findTotalCapacity(self):
        "Try and derive the total capacity if it's available"

        infoFilePath = os.path.join(self.batteryPath, INFO_FILE)
        try:
            infoFile = open(infoFilePath)
            data = self.readFile(infoFile)
            if data['last full capacity']:
                full = int(string.split(
                    data['last full capacity'])[0])
                if full:
                    self.totalCapacity = full
                    return

        except IOError:
            self.totalCapacity = TOTAL_CAPACITY

    def check(self):
        """Check battery status"""

        self.data = self.readFile(self.stateFile)
        self.remainingCapacity = int(string.split(self.data['remaining capacity'])[0])
        self.percentAvailable = (self.remainingCapacity / float(self.totalCapacity)) * 100

    def readFile(self, fileObj):
        """Read an ACPI info or state file into a hash"""

        fileObj.seek(0)
        lines = fileObj.readlines()

        data = {}
        for line in lines:
            (id, val) = string.split(line, ":", maxsplit=1)
            data[id] = string.strip(val)

        return data

class plugin:

    def __init__(self):
        self.plugin_name = "battery"
        self.plugin_desc = "Display ACPI battery status"
        self.plugin_keys = ["bat"]

        self.batstat = BatteryStatus()
        self.increment = 100

        self.check_battery()

    def check_battery(self):
        """Check battery status and warn when it reaches a certain level"""

        self.batstat.check()

        if self.batstat.data['charging state'] == 'discharging':
            # if the battery is discharging, check we're not running out of
            # power

            if self.batstat.percentAvailable < THRESHOLD_SHUTDOWN:
                pyd.top.set_timeout(-1)
                pyd.top.display(("Critical! Battery at less than %d%%" +
                                " - shutting down") % threshhold_shutdown)
                os.system("sync")
                os.system("sudo halt")
                return

            if self.batstat.percentAvailable < THRESHOLD_WARN:
                pyd.top.set_timeout(-1)
                pyd.top.display("Alert! Battery at %d%%" %
                                self.batstat.percentAvailable)

            if self.batstat.percentAvailable < self.increment:
                self.bat()
                self.increment = self.batstat.percentAvailable - 5
        else:
            pyd.top.set_timeout(3)
            self.increment = 100

        pyd.reactor.callLater(30, self.check_battery)

    def bat(self, *args):
        """Display battery info"""

        self.batstat.check()

        if self.batstat.data['charging state'] in ('unknown', 'charged'):
            state = "On A/C power."
        else:
            state = self.batstat.data['charging state']

        state = state + " (at %d%%)" % self.batstat.percentAvailable

        pyd.top.set_colour("#bbbbFF")
        pyd.top.set_timeout(3)
        pyd.top.display(state)
        pyd.top.display(self.batstat.percentAvailable,
                        type=pyosd.TYPE_PERCENT, line=1)