Make helpers.sysctl_async cross-platform & let bat_openbsd use it (#93)

This commit is contained in:
Enric Morales 2019-10-16 16:05:32 +02:00 committed by Nguyễn Gia Phong
parent ee970d0c68
commit 1277889978
2 changed files with 89 additions and 59 deletions

View File

@ -31,6 +31,7 @@
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
-- {{{ Grab environment
local ipairs = ipairs
local pairs = pairs
local rawget = rawget
local require = require
@ -273,13 +274,33 @@ function helpers.sysctl_async(path_table, parse)
path = table.concat(path, " ")
spawn.with_line_callback("sysctl " .. path, {
stdout = function(line)
if not string.find(line, "sysctl: unknown oid") then
local key, value = string.match(line, "(.+): (.+)")
ret[key] = value
stdout = function (line)
local separators = {
freebsd = ": ",
linux = " = ",
openbsd = "="
}
local pattern = ("(.+)%s(.+)"):format(separators[helpers.getos()])
local key, value = string.match(line, pattern)
ret[key] = value
end,
stderr = function (line)
local messages = {
openbsd = { "level name .+ in (.+) is invalid" },
linux = { "cannot stat /proc/sys/(.+):",
"permission denied on key '(.+)'" },
freebsd = { "unknown oid '(.+)'" }
}
for _, error_message in ipairs(messages[helpers.getos()]) do
local key = line:match(error_message)
if key then
key = key:gsub("/", ".")
ret[key] = "N/A"
end
end
end,
output_done = function() parse(ret) end
output_done = function () parse(ret) end
})
end
-- }}}

View File

@ -18,68 +18,77 @@
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
-- {{{ Grab environment
local pairs = pairs
local tonumber = tonumber
local math = { floor = math.floor, modf = math.modf }
local table = {
insert = table.insert
}
local helpers = require"vicious.helpers"
local spawn = require"vicious.spawn"
local math = {
floor = math.floor,
modf = math.modf
}
local helpers = require("vicious.helpers")
-- }}}
local STATES = { [0] = "", -- not charging
[1] = "-", -- discharging
[2] = "!", -- critical
[3] = "+", -- charging
[4] = "N/A", -- unknown status
[255] = "N/A" } -- unimplemented by the driver
local bat_openbsd = {}
function bat_openbsd.async(format, warg, callback)
local battery_id = warg or "bat0"
return helpers.setasyncall{
async = function (format, warg, callback)
local filter = "hw.sensors.acpi" .. (warg or "bat0")
local pattern = filter .. ".(%S+)=(%S+)"
local bat_info = {}
local fields = {
charging_rate = ("hw.sensors.acpi%s.power0"):format(battery_id),
last_full_capacity = ("hw.sensors.acpi%s.watthour0"):format(battery_id),
remaining_capacity = ("hw.sensors.acpi%s.watthour3"):format(battery_id),
design_capacity = ("hw.sensors.acpi%s.watthour4"):format(battery_id),
state = ("hw.sensors.acpi%s.raw0"):format(battery_id)
}
spawn.with_line_callback_with_shell(
("sysctl -a | grep '^%s'"):format(filter),
{ stdout = function (line)
for key, value in line:gmatch(pattern) do
bat_info[key] = value
end
end,
output_done = function ()
-- current state
local state = STATES[tonumber(bat_info.raw0)]
local sysctl_args = {}
for _, v in pairs(fields) do table.insert(sysctl_args, v) end
-- battery capacity in percent
local percent = tonumber(
bat_info.watthour3 / bat_info.watthour0 * 100)
local battery = {}
helpers.sysctl_async(sysctl_args, function (ret)
for k, v in pairs(fields) do
-- discard the description that comes after the values
battery[k] = tonumber(ret[v]:match("(.-) "))
end
local time
if tonumber(bat_info.power0) < 1 then
time = ""
else
local raw_time = bat_info.watthour3 / bat_info.power0
local hours, hour_fraction = math.modf(raw_time)
local minutes = math.floor(60 * hour_fraction)
time = ("%d:%0.2d"):format(hours, minutes)
end
local states = {
[0] = "", -- not charging
[1] = "-", -- discharging
[2] = "!", -- critical
[3] = "+", -- charging
[4] = "N/A", -- unknown status
[255] = "N/A" -- unimplemented by the driver
}
local state = states[battery.state]
-- calculate wear level from (last full / design) capacity
local wear = "N/A"
if bat_info.watthour0 and bat_info.watthour4 then
local l_full = tonumber(bat_info.watthour0)
local design = tonumber(bat_info.watthour4)
wear = math.floor(l_full / design * 100)
end
local charge = tonumber(battery.remaining_capacity
/ battery.last_full_capacity * 100)
-- dis-/charging rate as presented by battery
local rate = bat_info.power0
local remaining_time
if battery.charging_rate < 1 then
remaining_time = ""
else
local raw_time = battery.remaining_capacity / battery.rate
local hours, hour_fraction = math.modf(raw_time)
local minutes = math.floor(60 * hour_fraction)
remaining_time = ("%d:%0.2d"):format(hours, minutes)
end
-- Pass the following arguments to callback function:
-- * battery state symbol (↯, -, !, + or N/A)
-- * remaining_capacity (in percent)
-- * remaining_time, by battery
-- * wear level (in percent)
-- * present_rate (in Watts)
callback{state, percent, time, wear, rate}
end })
end }
local wear = math.floor(battery.last_full_capacity,
battery.design_capacity)
-- Pass the following arguments to callback function:
-- * battery state symbol (↯, -, !, + or N/A)
-- * remaining capacity (in percent)
-- * remaining time, as reported by the battery
-- * wear level (in percent)
-- * present_rate (in Watts/hour)
return callback({ state, charge, remaining_time,
wear, battery.charging_rate })
end)
end
return helpers.setasyncall(bat_openbsd)