]> git.madduck.net Git - etc/awesome.git/blob - widgets/bat.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Add possibility to give a list of batteries instead of only one.
[etc/awesome.git] / widgets / bat.lua
1
2 --[[
3                                                                                                                         
4          Licensed under GNU General Public License v2 
5           * (c) 2013,      Luke Bonham                
6           * (c) 2010-2012, Peter Hofmann              
7                                                                                                                         
8 --]]
9
10 local newtimer     = require("lain.helpers").newtimer
11 local first_line   = require("lain.helpers").first_line
12
13 local naughty      = require("naughty")
14 local wibox        = require("wibox")
15
16 local math         = { floor  = math.floor, min = math.min }
17 local string       = { format = string.format }
18 local tonumber     = tonumber
19
20 local setmetatable = setmetatable
21
22 -- Battery infos
23 -- lain.widgets.bat
24
25 local function worker(args)
26     local bat       = {}
27     local args      = args or {}
28     local timeout   = args.timeout or 30
29     local batteries = args.batteries or (args.battery and {args.battery}) or {"BAT0"}
30     local ac        = args.ac or "AC0"
31     local notify    = args.notify or "on"
32     local settings = args.settings or function() end
33
34     bat.widget = wibox.widget.textbox('')
35
36     bat_notification_low_preset = {
37         title   = "Battery low",
38         text    = "Plug the cable!",
39         timeout = 15,
40         fg      = "#202020",
41         bg      = "#CDCDCD"
42     }
43
44     bat_notification_critical_preset = {
45         title   = "Battery exhausted",
46         text    = "Shutdown imminent",
47         timeout = 15,
48         fg      = "#000000",
49         bg      = "#FFFFFF"
50     }
51
52     function update()
53         bat_now = {
54             status    = "Not present",
55             ac_status = "N/A",
56             perc      = "N/A",
57             time      = "N/A",
58             watt      = "N/A"
59         }
60
61         local sum_rate_current = 0
62         local sum_rate_voltage = 0
63         local sum_rate_power = 0
64         local sum_energy_now = 0
65         local sum_energy_full = 0
66         local sum_energy_percentage = 0
67
68         for i, battery in ipairs(batteries) do
69             local bstr    = "/sys/class/power_supply/" .. battery
70             local present = first_line(bstr .. "/present")
71
72             if present == "1"
73             then
74                 -- current_now(I)[uA], voltage_now(U)[uV], power_now(P)[uW]
75                 local rate_current      = tonumber(first_line(bstr .. "/current_now"))
76                 local rate_voltage      = tonumber(first_line(bstr .. "/voltage_now"))
77                 local rate_power        = tonumber(first_line(bstr .. "/power_now"))
78
79                 -- energy_now(P)[uWh], charge_now(I)[uAh]
80                 local energy_now        = tonumber(first_line(bstr .. "/energy_now") or
81                                           first_line(bstr .. "/charge_now"))
82
83                 -- energy_full(P)[uWh], charge_full(I)[uAh]
84                 local energy_full       = tonumber(first_line(bstr .. "/energy_full") or
85                                           first_line(bstr .. "/charge_full"))
86
87                 local energy_percentage = tonumber(first_line(bstr .. "/capacity")) or
88                                           math.floor((energy_now / energy_full) * 100)
89
90                 if bat_now.status ~= "Charging" and bat_now.status ~= "Discharging"
91                 then
92                     bat_now.status = first_line(bstr .. "/status") or "N/A"
93                 end
94
95                 sum_rate_current = sum_rate_current + (rate_current or 0)
96                 sum_rate_voltage = sum_rate_voltage + rate_voltage
97                 sum_rate_power = sum_rate_power + (rate_power or ((rate_voltage * rate_current) / 1e6))
98                 sum_energy_now = sum_energy_now + energy_now
99                 sum_energy_full = sum_energy_full + energy_full
100                 sum_energy_percentage = sum_energy_percentage + energy_percentage
101             end
102         end
103
104         local astr    = "/sys/class/power_supply/" .. ac
105         bat_now.ac_status = first_line(astr .. "/online") or "N/A"
106
107         -- update {perc,time,watt} iff rate > 0 and battery not full
108         if ((sum_rate_current > 0) or (sum_rate_power > 0))
109             and bat_now.status ~= "N/A" and bat_now.status ~= "Full"
110         then
111             local rate_time = 0
112             if bat_now.status == "Charging" then
113                 rate_time = (sum_energy_full - sum_energy_now) / (sum_rate_power or sum_rate_current)
114             elseif bat_now.status == "Discharging" then
115                 rate_time = sum_energy_now / (sum_rate_power or sum_rate_current)
116             end
117
118             local hours   = math.floor(rate_time)
119             local minutes = math.floor((rate_time - hours) * 60)
120             local watt    = sum_rate_power / 1e6
121             bat_now.perc  = string.format("%d", math.min(100, sum_energy_percentage / table.getn(batteries)))
122             bat_now.time  = string.format("%02d:%02d", hours, minutes)
123             bat_now.watt  = string.format("%.2fW", watt)
124         end
125
126         widget = bat.widget
127         settings()
128
129         -- notifications for low and critical states
130         if bat_now.status == "Discharging" and notify == "on" and bat_now.perc then
131             local nperc = tonumber(bat_now.perc) or 100
132             if nperc <= 5 then
133                 bat.id = naughty.notify({
134                     preset = bat_notification_critical_preset,
135                     replaces_id = bat.id,
136                 }).id
137             elseif nperc <= 15 then
138                 bat.id = naughty.notify({
139                     preset = bat_notification_low_preset,
140                     replaces_id = bat.id,
141                 }).id
142             end
143         end
144     end
145
146     newtimer(battery, timeout, update)
147
148     return setmetatable(bat, { __index = bat.widget })
149 end
150
151 return setmetatable({}, { __call = function(_, ...) return worker(...) end })