summaryrefslogtreecommitdiff
path: root/battery_mng.lua
diff options
context:
space:
mode:
Diffstat (limited to 'battery_mng.lua')
-rw-r--r--battery_mng.lua139
1 files changed, 139 insertions, 0 deletions
diff --git a/battery_mng.lua b/battery_mng.lua
new file mode 100644
index 0000000..c04c52f
--- /dev/null
+++ b/battery_mng.lua
@@ -0,0 +1,139 @@
+local GFile = require("lgi").Gio.File
+
+local gears = require("gears")
+local spawn = require("awful.spawn")
+local wibox = require("wibox")
+
+local utils = require('utils')
+
+local BatteryWidget = require('battery_wgt')
+local Battery = require('battery')
+
+
+local BatteryManager = {}
+BatteryManager.__index = BatteryManager
+
+setmetatable(BatteryManager, {
+ __call = function (cls, ...) return cls.new(...) end,
+})
+
+function BatteryManager:_log(msg, ...)
+ utils.log('BatteryManager', msg, ...)
+end
+
+function BatteryManager:_warn(msg, ...)
+ utils.warn('BatteryManager', msg, ...)
+end
+
+function BatteryManager:_battery_add(name)
+ if self._batteries[name] ~= nil then
+ -- only warn for usable batteries that are added twice for some reason
+ if self._batteries[name] ~= false then
+ self:_warn('Battery %s already exists', name)
+ end
+ return
+ end
+
+ self:_log('Trying power supply: ' .. name)
+
+ local bat = Battery(name)
+ if not bat then
+ self:_log('Skipping ' .. name .. ': could not be opened or is not a battery')
+ -- remember device as unusable
+ self._batteries[name] = false
+ return
+ end
+ self:_log('Opened battery %s: %s', name, bat.desc)
+
+ local wgt = BatteryWidget(bat)
+
+ self._layout:add(wgt)
+
+ self._batteries[name] = { widget = wgt, battery = bat }
+end
+
+function BatteryManager:_battery_remove(name)
+ self:_log('Removing battery ' .. name)
+
+ local tbl = self._batteries[name]
+ if tbl then
+ self._layout:remove_widgets(tbl.widget)
+ end
+ self._batteries[name] = nil
+end
+
+function BatteryManager:_refresh()
+ for name, item in pairs(self._batteries) do
+ if item and not item.battery:update() then
+ self:_log('Could not update battery %s, removing', name)
+ self:_battery_remove(name)
+ end
+ end
+end
+
+function BatteryManager.new()
+ local self = setmetatable({}, BatteryManager)
+
+ -- the layout containing the individual battery widgets
+ self._layout = wibox.layout.flex.horizontal()
+
+ -- entries are either
+ -- - tables { battery, widget } for existing batteries
+ -- - false for devices that we've seen, but are not valid batteries
+ self._batteries = {}
+
+ -- try adding all existing batteries
+ local ps = GFile.new_for_path('/sys/class/power_supply')
+ local ret = ps:enumerate_children('*', 0)
+ while true do
+ local file_info = ret:next_file()
+ if not file_info then
+ break
+ end
+
+ self:_battery_add(file_info:get_name())
+ end
+
+ -- monitor udev events
+ local function monitor_stdout(line)
+ local action, device = string.match(line, '^KERNEL%[%d+.%d*%]%s+(%a+)%s+([^%s]+)%s+%(power_supply%)$')
+ if action then
+ local name = string.match(device, '([^/]+)$')
+ if name == nil then
+ self:_warn('Could not extract device name from path: %s', device)
+ return
+ end
+
+ if action == 'add' or action == 'change' then
+ -- battery device not seen before, try adding
+ if self._batteries[name] == nil then
+ self:_battery_add(name)
+ end
+
+ -- device is a valid battery, refresh state
+ if self._batteries[name] then
+ self._batteries[name].battery:update()
+ end
+ elseif action == 'remove' then
+ self:_battery_remove(name)
+ end
+ end
+ end
+
+ local function monitor_exit(reason, code)
+ self:_warn('udevadm monitor exited: %s/%d', reason, code)
+ end
+
+ spawn.with_line_callback('udevadm monitor --kernel --subsystem-match=power_supply',
+ { stdout = monitor_stdout, exit = monitor_exit, })
+
+ self:_refresh()
+ gears.timer.start_new(5, function ()
+ self:_refresh()
+ return true
+ end)
+
+ return self._layout
+end
+
+return BatteryManager