fix new battery plugin to work better with multiple batteries present
[wmiirc-lua.git] / src / plugins / battery.lua
blobf9838ceb7fef0d135e95db096bf5824a23dcc631
1 --[[
2 =pod
4 =head1 NAME
6 battery.lua - wmiirc-lua plugin for battery percentage
8 =head1 SYNOPSIS
10 -- in your wmiirc
11 wmii.load_plugin("battery")
13 -- To configure (after loading plugin)
15 -- Multiple batteries
16 wmii.set_conf("battery.names", "BAT0,BAT1");
18 -- Polling rate (in seconds)
19 wmii.set_conf("battery.poll_rate", 30)
21 =head1 DESCRIPTION
23 This plugin module provides a battery usage display.
25 =head1 CONFIGURATION AND ENVIRONMENT
27 There are several configurable options at the moment, most of which will not
28 need to be modified from the defaults for most users.
30 =over 4
32 =item battery.names
34 A comma-separated list of battery names to poll for status. This allows the
35 widget to display multiple battery names. If left blank, will display all
36 batteries.
38 Defaults to ""
40 =item battery.poll_rate
42 Time in seconds to wait between checks for battery status.
44 Defaults to 30
46 =item battery.low
48 Provide a "low battery" warning at this percentage of remaining capacity.
49 Colour of widget will change to the defined value, and the low_action, if any,
50 will be invoked.
52 Defaults to 15
54 =item battery.low_fgcolor
56 Foreground colour of widget when in low battery state.
58 Defaults to #000000
60 =item battery.low_bgcolor
62 Background colour of widget when in low battery state.
64 Defaults to #FFFF66
66 =item battery.low_action
68 Shell command to invoke on entering low battery state.
70 Defaults to
72 echo "Low battery" | xmessage -center -buttons quit:0 -default quit -file -
74 =item battery.critical
76 Provide a "critical battery" warning at this percentage of remaining capacity.
77 Colour of widget will change to the defined value, and the critical_action, if any,
78 will be invoked.
80 Defaults to 5
82 =item battery.critical_fgcolor
84 Foreground colour of widget when in critical battery state.
86 Defaults to #000000
88 =item battery.critical_bgcolor
90 Background colour of widget when in critical battery state.
92 Defaults to #FF0000
94 =item battery.critical_action
96 Shell command to invoke on entering critical battery state.
98 Defaults to
100 echo "Critical battery" | xmessage -center -buttons quit:0 -default quit -file -
102 =item battery.practically_full_percentage
104 This is a workaround for faulty batteries. Set this lower if you want your battery to report being
105 full at a lower percentage than 100.
107 Defaults to 99
109 =back
111 =head1 BUGS AND LIMITATIONS
113 Please report problems to the author.
114 Patches are welcome.
116 =over 4
118 =item *
120 You can't have different low/critical warning thresholds or colours per
121 battery. If you actually want this, please send a patch.
123 =back
125 =head1 SEE ALSO
127 L<wmii(1)>, L<lua(1)>
129 =head1 AUTHOR
131 Dave O'Neill <dmo@dmo.ca>
132 Bart Trojanowski <bart@jukie.net>
134 Based on a port by Stefan Riegler <sr@bigfatflat.net> of the ruby-wmiirc
135 standard-plugin.rb battery handling originally written Mauricio Fernandez.
137 =head1 LICENCE AND COPYRIGHT
139 Copyright (c) 2007, Stefan Riegler <sr@bigfatflat.net>
140 Copyright (c) 2008, Dave O'Neill <dmo@dmo.ca>
141 Copyright (c) 2010, Bart Trojanowski <bart@jukie.net>
143 This is free software. You may redistribute copies of it under the terms of
144 the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>. There
145 is NO WARRANTY, to the extent permitted by law.
147 =cut
149 --]]
151 local wmii = require("wmii")
152 local io = require("io")
153 local os = require("os")
154 local string = require("string")
155 local posix = require("posix")
156 local type = type
157 local tostring = tostring
159 module("battery")
160 api_version=0.1
163 -- Configuration Settings
165 wmii.set_conf ("battery.poll_rate", 30)
167 wmii.set_conf ("battery.names", "") -- leave empty to use all available batteries
169 wmii.set_conf ("battery.low", 15)
170 wmii.set_conf ("battery.low_fgcolor", "#000000")
171 wmii.set_conf ("battery.low_bgcolor", "#FFFF66")
172 wmii.set_conf ("battery.low_action", 'echo "Low battery" | xmessage -center -buttons quit:0 -default quit -file -')
174 wmii.set_conf ("battery.critical", 5)
175 wmii.set_conf ("battery.critical_fgcolor", "#000000")
176 wmii.set_conf ("battery.critical_bgcolor", "#FF0000")
177 wmii.set_conf ("battery.critical_action", 'echo "Critical battery" | xmessage -center -buttons quit:0 -default quit -file -')
179 wmii.set_conf ("battery.practically_full_percentage", 99)
181 -- Should not need to be modified on Linux
182 wmii.set_conf ("battery.sysdir", "/sys/class/power_supply")
183 -- ... see http://wiki.openmoko.org/wiki/GTA02_sysfs#power_supply_battery_information for more info
185 wmii.set_conf ("battery.showtime", true)
186 wmii.set_conf ("battery.showrate", true)
189 -- Local Variables
191 local batteries = { }
193 -- read a /sys file, return the first line
194 local function read_sys_line(file, fmt)
195 local ret = nil
196 local fd = io.open(file)
197 if fd then
198 ret = fd:read(fmt or "*l")
200 return ret
202 local function read_sys_number(file)
203 local ret = read_sys_line(file, "*n")
204 if type(ret) ~= type(1) then
205 ret = 0
207 return ret
210 -- The actual work performed here.
211 -- parses info, state file and preps for display
212 local function update_single_battery ( name )
214 local battery = batteries[name]
215 if not battery then
216 batteries[name] = {
217 name = name,
218 widget = wmii.widget:new ("901_battery_" .. name),
219 warned_low = false,
220 warned_crit = false,
222 battery = batteries[name]
225 local printout = "N/A"
226 local colors = wmii.get_ctl("normcolors")
228 local sysdir = string.format("%s/%s", wmii.get_conf("battery.sysdir"), name)
230 local batt_present = read_sys_number(sysdir .. '/present') -- 0 or 1
231 local batt_energy_now = read_sys_number(sysdir .. '/energy_now') -- µWh
232 local batt_energy_full = read_sys_number(sysdir .. '/energy_full') -- µWh
233 local batt_current_now = read_sys_number(sysdir .. '/current_now') -- µAh
234 local batt_power_now = read_sys_number(sysdir .. '/power_now') -- µW
235 local batt_status = read_sys_line(sysdir .. '/status') -- Full, Charging, Discharging, Unknown
237 -- the /sys reporting interface is not present
238 if not batt_present or not batt_energy_now or not batt_energy_full or not batt_status then
239 return battery["widget"]:show(printout, colors)
242 local batt_percent = batt_energy_now / batt_energy_full * 100
243 if batt_percent > 100 then
244 batt_percent = 100
247 local low = wmii.get_conf ("battery.low")
248 local critical = wmii.get_conf ("battery.critical")
249 local practically_full = wmii.get_conf ("battery.practically_full_percentage")
251 -- Take action in case battery is low/critical
252 if batt_percent <= critical then
253 if batt_status == "Discharging" and not battery["warned_crit"] then
254 wmii.log("Warning about critical battery.")
255 os.execute(wmii.get_conf("battmon.critical_action"), "&")
256 battery["warned_crit"] = true
258 colors = string.gsub(colors, "^%S+ %S+",
259 wmii.get_conf ("battery.critical_fgcolor")
260 .. " "
261 .. wmii.get_conf ("battery.critical_bgcolor"),
263 elseif batt_percent <= low then
264 if batt_status == "Discharging" and not battery["warned_low"] then
265 wmii.log("Warning about low battery.")
266 os.execute(wmii.get_conf("battmon.low_action"), "&")
267 battery["warned_low"] = true
269 colors = string.gsub(colors, "^%S+ %S+",
270 wmii.get_conf ("battery.low_fgcolor")
271 .. " "
272 .. wmii.get_conf ("battery.low_bgcolor"),
274 else
275 battery["warned_low"] = true
276 battery["warned_crit"] = true
280 -- If percent is 100 and state is discharging then
281 -- the battery is full and not discharging.
282 local batt_state = "?"
283 if batt_status == "Unknown" then
284 batt_state = "-"
285 elseif (batt_status == "Full") or (batt_percent >= practically_full) then
286 batt_state = "="
287 elseif batt_status == "Charging" then
288 batt_state = "^"
289 elseif batt_status == "Discharging" then
290 batt_state = "v"
293 -- done calculating, compose the output
294 printout = ""
296 if wmii.get_conf(battery.showrate) and batt_power_now then
297 printout = printout .. string.format("%.2fW ", batt_power_now / 1000000)
300 if wmii.get_conf(battery.showtime) and batt_current_now and batt_current_now ~= 0 then
301 local hours = 0
302 if batt_state == "^" then
303 hours = (batt_energy_full - batt_energy_now) / batt_current_now
304 else
305 hours = batt_energy_now / batt_current_now
307 printout = printout .. string.format("%d:%0.2d ", hours, (hours*60) % 60)
310 printout = printout .. '(' .. batt_state .. string.format("%.0f", batt_percent) .. batt_state .. ')'
312 battery["widget"]:show(printout, colors)
315 -- ------------------------------------------------------------
316 -- The battery status update function (wmii.timer function)
317 local function update_batt_data (time_since_update)
319 local batt_names = wmii.get_conf("battery.names");
321 if type(batt_names) == type("") and batt_names ~= "" then
322 for name in batt_names:gmatch("%w+") do
323 update_single_battery(name)
325 else
326 local sysdir = wmii.get_conf("battery.sysdir")
327 for name in posix.files(sysdir) do
328 local type_file = string.format("%s/%s/type", sysdir, name)
329 local batt_type = read_sys_line(type_file)
330 if batt_type == "Battery" then
331 update_single_battery(name)
336 return wmii.get_conf("battery.poll_rate")
340 local timer = wmii.timer:new (update_batt_data, 1)