From 703f7e23f134fc4f92079b566037e46fe2179308 Mon Sep 17 00:00:00 2001 From: eylles Date: Mon, 24 May 2021 15:56:28 -0600 Subject: [PATCH 1/3] upower backend for battery widget --- battery-widget/battery.lua | 165 ++++++++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 50 deletions(-) diff --git a/battery-widget/battery.lua b/battery-widget/battery.lua index 0422fcc7..bd887a78 100644 --- a/battery-widget/battery.lua +++ b/battery-widget/battery.lua @@ -31,6 +31,7 @@ local function worker(user_args) local show_current_level = args.show_current_level or false local margin_left = args.margin_left or 0 local margin_right = args.margin_right or 0 + local battery_backend = args.battery_backend or "acpi" local display_notification = args.display_notification or false local display_notification_onClick = args.display_notification_onClick or true @@ -120,69 +121,133 @@ local function worker(user_args) local last_battery_check = os.time() local batteryType = "battery-good-symbolic" - watch("acpi -i", timeout, - function(widget, stdout) - local battery_info = {} - local capacities = {} - for s in stdout:gmatch("[^\r\n]+") do - local status, charge_str, _ = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?(.*)') - if status ~= nil then - table.insert(battery_info, {status = status, charge = tonumber(charge_str)}) - else - local cap_str = string.match(s, '.+:.+last full capacity (%d+)') - table.insert(capacities, tonumber(cap_str)) + if battery_backend == "acpi" then + watch("acpi -i", timeout, + function(widget, stdout) + local battery_info = {} + local capacities = {} + for s in stdout:gmatch("[^\r\n]+") do + local status, charge_str, _ = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?(.*)') + if status ~= nil then + table.insert(battery_info, {status = status, charge = tonumber(charge_str)}) + else + local cap_str = string.match(s, '.+:.+last full capacity (%d+)') + table.insert(capacities, tonumber(cap_str)) + end end - end - local capacity = 0 - for _, cap in ipairs(capacities) do - capacity = capacity + cap - end + local capacity = 0 + for _, cap in ipairs(capacities) do + capacity = capacity + cap + end + + local charge = 0 + local status + for i, batt in ipairs(battery_info) do + if capacities[i] ~= nil then + if batt.charge >= charge then + status = batt.status -- use most charged battery status + -- this is arbitrary, and maybe another metric should be used + end - local charge = 0 - local status - for i, batt in ipairs(battery_info) do - if capacities[i] ~= nil then - if batt.charge >= charge then - status = batt.status -- use most charged battery status - -- this is arbitrary, and maybe another metric should be used + charge = charge + batt.charge * capacities[i] end + end + charge = charge / capacity - charge = charge + batt.charge * capacities[i] + if show_current_level then + level_widget.text = string.format('%d%%', charge) end - end - charge = charge / capacity - if show_current_level then - level_widget.text = string.format('%d%%', charge) - end + if (charge >= 0 and charge < 15) then + batteryType = "battery-empty%s-symbolic" + if enable_battery_warning and status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then + -- if 5 minutes have elapsed since the last warning + last_battery_check = os.time() - if (charge >= 0 and charge < 15) then - batteryType = "battery-empty%s-symbolic" - if enable_battery_warning and status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then - -- if 5 minutes have elapsed since the last warning - last_battery_check = os.time() + show_battery_warning() + end + elseif (charge >= 15 and charge < 40) then batteryType = "battery-caution%s-symbolic" + elseif (charge >= 40 and charge < 60) then batteryType = "battery-low%s-symbolic" + elseif (charge >= 60 and charge < 80) then batteryType = "battery-good%s-symbolic" + elseif (charge >= 80 and charge <= 100) then batteryType = "battery-full%s-symbolic" + end - show_battery_warning() + if status == 'Charging' then + batteryType = string.format(batteryType, '-charging') + else + batteryType = string.format(batteryType, '') end - elseif (charge >= 15 and charge < 40) then batteryType = "battery-caution%s-symbolic" - elseif (charge >= 40 and charge < 60) then batteryType = "battery-low%s-symbolic" - elseif (charge >= 60 and charge < 80) then batteryType = "battery-good%s-symbolic" - elseif (charge >= 80 and charge <= 100) then batteryType = "battery-full%s-symbolic" - end - if status == 'Charging' then - batteryType = string.format(batteryType, '-charging') - else - batteryType = string.format(batteryType, '') - end + widget.icon:set_image(path_to_icons .. batteryType .. ".svg") + + -- Update popup text + -- battery_popup.text = string.gsub(stdout, "\n$", "") + end, + icon_widget) + elseif battery_backend == "upower" then + watch( + { awful.util.shell, "-c", "upower -i $(upower -e | grep BAT) | sed -n '/present/,/icon-name/p'" }, + timeout, + function(widget, stdout) + local bat_now = { + present = "N/A", + state = "N/A", + warninglevel = "N/A", + energy = "N/A", + energyfull = "N/A", + energyrate = "N/A", + voltage = "N/A", + percentage = "N/A", + capacity = "N/A", + icon = "N/A" + } + + for k, v in string.gmatch(stdout, '([%a]+[%a|-]+):%s*([%a|%d]+[,|%a|%d]-)') do + if k == "present" then bat_now.present = v + elseif k == "state" then bat_now.state = v + elseif k == "warning-level" then bat_now.warninglevel = v + elseif k == "energy" then bat_now.energy = string.gsub(v, ",", ".") -- Wh + elseif k == "energy-full" then bat_now.energyfull = string.gsub(v, ",", ".") -- Wh + elseif k == "energy-rate" then bat_now.energyrate = string.gsub(v, ",", ".") -- W + elseif k == "voltage" then bat_now.voltage = string.gsub(v, ",", ".") -- V + elseif k == "percentage" then bat_now.percentage = tonumber(v) -- % + elseif k == "capacity" then bat_now.capacity = string.gsub(v, ",", ".") -- % + elseif k == "icon-name" then bat_now.icon = v + end + end + + -- customize here + local charge = bat_now.percentage + local status = bat_now.state + if show_current_level then + level_widget.text = string.format('%d%%', charge) + end + + if (charge >= 0 and charge < 15) then + batteryType = "battery-empty%s-symbolic" + if enable_battery_warning and status ~= 'charging' and os.difftime(os.time(), last_battery_check) > 300 then + -- if 5 minutes have elapsed since the last warning + last_battery_check = os.time() + + show_battery_warning() + end + elseif (charge >= 15 and charge < 40) then batteryType = "battery-caution%s-symbolic" + elseif (charge >= 40 and charge < 60) then batteryType = "battery-low%s-symbolic" + elseif (charge >= 60 and charge < 80) then batteryType = "battery-good%s-symbolic" + elseif (charge >= 80 and charge <= 100) then batteryType = "battery-full%s-symbolic" + end - widget.icon:set_image(path_to_icons .. batteryType .. ".svg") + if status == 'charging' then + batteryType = string.format(batteryType, '-charging') + else + batteryType = string.format(batteryType, '') + end - -- Update popup text - -- battery_popup.text = string.gsub(stdout, "\n$", "") - end, - icon_widget) + widget.icon:set_image(path_to_icons .. batteryType .. ".svg") + end, + icon_widget) + end if display_notification then battery_widget:connect_signal("mouse::enter", function() show_battery_status(batteryType) end) From 1a4f8e04fdca007f72f8b72dcd7624d53836e1e3 Mon Sep 17 00:00:00 2001 From: eylles Date: Mon, 24 May 2021 21:58:37 -0600 Subject: [PATCH 2/3] use time to full charge to decide if charging icon, cleaned up upower call --- battery-widget/battery.lua | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/battery-widget/battery.lua b/battery-widget/battery.lua index bd887a78..fe9e99d7 100644 --- a/battery-widget/battery.lua +++ b/battery-widget/battery.lua @@ -191,29 +191,15 @@ local function worker(user_args) timeout, function(widget, stdout) local bat_now = { - present = "N/A", state = "N/A", - warninglevel = "N/A", - energy = "N/A", - energyfull = "N/A", - energyrate = "N/A", - voltage = "N/A", + timefull = "N/A", percentage = "N/A", - capacity = "N/A", - icon = "N/A" } for k, v in string.gmatch(stdout, '([%a]+[%a|-]+):%s*([%a|%d]+[,|%a|%d]-)') do - if k == "present" then bat_now.present = v - elseif k == "state" then bat_now.state = v - elseif k == "warning-level" then bat_now.warninglevel = v - elseif k == "energy" then bat_now.energy = string.gsub(v, ",", ".") -- Wh - elseif k == "energy-full" then bat_now.energyfull = string.gsub(v, ",", ".") -- Wh - elseif k == "energy-rate" then bat_now.energyrate = string.gsub(v, ",", ".") -- W - elseif k == "voltage" then bat_now.voltage = string.gsub(v, ",", ".") -- V + if k == "state" then bat_now.state = v + elseif k == 'full' then bat_now.timefull = v elseif k == "percentage" then bat_now.percentage = tonumber(v) -- % - elseif k == "capacity" then bat_now.capacity = string.gsub(v, ",", ".") -- % - elseif k == "icon-name" then bat_now.icon = v end end @@ -238,7 +224,7 @@ local function worker(user_args) elseif (charge >= 80 and charge <= 100) then batteryType = "battery-full%s-symbolic" end - if status == 'charging' then + if (status == 'charging' and bat_now.timefull ~= "N/A") then batteryType = string.format(batteryType, '-charging') else batteryType = string.format(batteryType, '') From 1d74d69ae1c6cc9935a179f689c31dbeb7db2f2a Mon Sep 17 00:00:00 2001 From: eylles Date: Sun, 12 Dec 2021 20:13:13 -0600 Subject: [PATCH 3/3] added notification with upower backend --- battery-widget/battery.lua | 46 ++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/battery-widget/battery.lua b/battery-widget/battery.lua index fe9e99d7..f6711ca5 100644 --- a/battery-widget/battery.lua +++ b/battery-widget/battery.lua @@ -78,21 +78,39 @@ local function worker(user_args) -- One way of creating a pop-up notification - naughty.notify local notification local function show_battery_status(batteryType) - awful.spawn.easy_async([[bash -c 'acpi']], - function(stdout, _, _, _) - naughty.destroy(notification) - notification = naughty.notify{ - text = stdout, - title = "Battery status", - icon = path_to_icons .. batteryType .. ".svg", - icon_size = dpi(16), - position = position, - timeout = 5, hover_timeout = 0.5, - width = 200, - screen = mouse.screen - } + if battery_backend == "acpi" then + awful.spawn.easy_async([[bash -c 'acpi']], + function(stdout, _, _, _) + naughty.destroy(notification) + notification = naughty.notify{ + text = stdout, + title = "Battery status", + icon = path_to_icons .. batteryType .. ".svg", + icon_size = dpi(16), + position = position, + timeout = 5, hover_timeout = 0.5, + width = 200, + screen = mouse.screen + } + end + ) + elseif battery_backend == "upower" then + awful.spawn.easy_async({ awful.util.shell, "-c", [[ upower -i $(upower -e | grep BAT) | awk '{ if ($1 == "native-path:") {print $2} else if ($1 == "percentage:") {print $2} else if ($1 == "state:") {print $2} else if ($1 == "time") {print $4" "$5} }' ]] }, + function(stdout, _, _, _) + naughty.destroy(notification) + notification = naughty.notify{ + text = stdout, + title = "Battery status", + icon = path_to_icons .. batteryType .. ".svg", + icon_size = dpi(16), + position = position, + timeout = 5, hover_timeout = 0.5, + width = 200, + screen = mouse.screen + } + end + ) end - ) end -- Alternative to naughty.notify - tooltip. You can compare both and choose the preferred one