diff --git a/README.md b/README.md index cbded56..bf3838c 100644 --- a/README.md +++ b/README.md @@ -141,11 +141,12 @@ return a table of values to be formatted by `format`. Provides state, charge, and remaining time for a requested battery. -Supported platforms: GNU/Linux (require `sysfs`), FreeBSD (require `acpiconf`). +Supported platforms: GNU/Linux (require `sysfs`), FreeBSD (require `acpiconf`), OpenBSD (no extra requirements). * `warg` (from now on will be called *argument*): * On GNU/Linux: battery ID, e.g. `"BAT0"` * On FreeBSD (optional): battery ID, e.g. `"batt"` or `"0"` + * On OpenBSD (optional): `bat` followed by battery index, e.g. `bat0` or `bat1` on systems with more than one battery * Returns an array (integer-indexed table) consisting of: * `$1`: State of requested battery * `$2`: Charge level in percent diff --git a/helpers.lua b/helpers.lua index dc7c323..950f0d3 100644 --- a/helpers.lua +++ b/helpers.lua @@ -64,7 +64,8 @@ function helpers.wrequire(table, key) local ostable = { linux = { "linux", "all" }, - freebsd = { "freebsd", "bsd", "all" } + freebsd = { "freebsd", "bsd", "all" }, + openbsd = { "openbsd", "bsd", "all" } } local os = ostable[helpers.getos()] diff --git a/widgets/bat_openbsd.lua b/widgets/bat_openbsd.lua new file mode 100644 index 0000000..15b7598 --- /dev/null +++ b/widgets/bat_openbsd.lua @@ -0,0 +1,72 @@ +-- {{{ Grab environment +local setmetatable = setmetatable +local tonumber = tonumber +local string = { format = string.format, gmatch = string.gmatch } +local io = { popen = io.popen } +local math = { floor = math.floor } +local helpers = require("vicious.helpers") +local string = { + gmatch = string.gmatch, + match = string.match, + format = string.format +} +-- }}} +local bat_openbsd = {} + +local function worker(format, warg) + local battery = warg or "bat0" + local filter = string.format("hw.sensors.acpi%s", battery) + local cmd = string.format("sysctl -a | grep '^%s'", filter) + local proc = io.popen(cmd) + + local bat_info = {} + for line in proc:lines("*l") do + for key, value in string.gmatch(line, "(%S+)=(%S+)") do + key = key:gsub(filter .. ".", "") + bat_info[key] = value + end + end + + -- current state + 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[tonumber(bat_info.raw0)] + + -- battery capacity in percent + local percent = tonumber(bat_info.watthour3 / bat_info.watthour0 * 100) + + local time + if tonumber(bat_info.power0) < 1 then + time = "∞" + else + local raw_time = bat_info.watthour3 / bat_info.power0 + local hours = math.floor(raw_time) + local minutes = raw_time % 1 + time = string.format("%d:%0.2d", hours, minutes) + end + + -- 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 + + -- dis-/charging rate as presented by battery + local rate = bat_info.power0 + + -- returns + -- * state (high "↯", discharging "-", charging "+", N/A "⌁" } + -- * remaining_capacity (percent) + -- * remaining_time, by battery + -- * wear level (percent) + -- * present_rate (W) + return {state, percent, time, wear, rate} +end + +return setmetatable(bat_openbsd, { __call = function(_, ...) return worker(...) end })