diff options
Diffstat (limited to 'battery_mng.lua')
-rw-r--r-- | battery_mng.lua | 139 |
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 |