Add FraI3mega/battery-graph (#115)
* feat(battery-graph): Initialize plugin files * feat(battery-graph): Add bar widget * feat(battery-graph): Implement logic * docs(battery-graph): Fill out the template README * feat(battery-graph): Improve panel * feat(battery-graph): Implement settings * feat(battery-graph): Improve panel styling * feat(battery-graph): Add desktop widget * docs(battery-graph): Improve wording * docs(battery-graph): Add image * docs(battery-graph): Add tags * docs(battery-graph): Improve README * fix(battery-graph): Fix translations * docs(battery-graph): Fix tags * fix(battery-graph): Fix author name * docs(battery-graph): Rename thumbnail * docs(battery-graph): Add dependencies * docs(battery-graph): Improve README * docs(battery-graph): Bump version to 1.0.0 * fix(battery-graph): Remove leftover log * fix(battery-graph): Wrap battery path in quotes * fix(battery-graph): Implement path validation * docs(battery-graph): Clarify setting * fix(battery-graph): Wrap grapth_time in quoutes * docs(battery-graph): Fix setting description
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
# Battery graph
|
||||||
|
|
||||||
|
Uses the Upowerd to display the historical charge of the battery on a graph.
|
||||||
|
|
||||||
|
## Plugin
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | `frai3mega/battery-graph` |
|
||||||
|
| Entries | Bar widget: `battery-graph-widget`; panel: `battery-panel`; Desktop widget: `battery-graph-desktop` |
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Requires a running `upowerd` deamon.
|
||||||
|
Install `gdbus` on `PATH`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
You can use it as a desktop/locksreen widget or on the bar.
|
||||||
|
|
||||||
|
Show the panel using
|
||||||
|
|
||||||
|
```sh
|
||||||
|
noctalia msg panel-toggle frai3mega/battery-graph:battery-panel
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Settings
|
||||||
|
|
||||||
|
|
||||||
|
| Setting | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `graph_time` | `int` | `6` | Changes the timeframe of the graph |
|
||||||
|
| `battery_path` | `string` | `/org/freedesktop/UPower/devices/battery_BAT0` | The path to the battery to be graphed |
|
||||||
|
| `interpol_time` | `int` | `5` | The time beetween points on the graph. |
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
graph_time = 3600 * noctalia.getConfig("graph_time")
|
||||||
|
battery_path = noctalia.getConfig("battery_path")
|
||||||
|
interpol_time = 60 * noctalia.getConfig("interpol_time")
|
||||||
|
|
||||||
|
local function validate(s)
|
||||||
|
if s:match("^/org/freedesktop/UPower/devices/[%a%d_]+$") ~= nil then
|
||||||
|
return "'" .. tostring(s):gsub("'", "'\\''") .. "'"
|
||||||
|
else
|
||||||
|
noctalia.log("Invalid battery dbus path. Check that it is correct")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local cmd = table.concat({"gdbus call --system --dest org.freedesktop.UPower --object-path",validate(battery_path),"--method org.freedesktop.UPower.Device.GetHistory charge",graph_time, "1000"}, " ")
|
||||||
|
|
||||||
|
function update()
|
||||||
|
noctalia.setUpdateInterval(interpol_time * 1000)
|
||||||
|
noctalia.runAsync(cmd, parse)
|
||||||
|
end
|
||||||
|
|
||||||
|
function parse(result)
|
||||||
|
local points = {}
|
||||||
|
for tuple in result.stdout:gmatch("%(([^%)]+)%)") do
|
||||||
|
local fields = {}
|
||||||
|
for field in tuple:gmatch("[^,]+") do
|
||||||
|
field = field:match("^%s*(.-)%s*$") -- trim whitespace
|
||||||
|
field = field:gsub("^%S+%s+", "") -- strip "uint32 " style prefix (only if followed by more content)
|
||||||
|
table.insert(fields, field)
|
||||||
|
end
|
||||||
|
local ts, value = tonumber(fields[1]), tonumber(fields[2])
|
||||||
|
if value ~= 0.0 then
|
||||||
|
points[ts] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local interpolated_points = interpolate(points)
|
||||||
|
render(table.concat(interpolated_points, " "), interpolated_points)
|
||||||
|
end
|
||||||
|
|
||||||
|
function interpolate(points )
|
||||||
|
local interpolated_points = {}
|
||||||
|
|
||||||
|
local tkeys = {}
|
||||||
|
for k in pairs(points) do
|
||||||
|
table.insert(tkeys, k)
|
||||||
|
end
|
||||||
|
table.sort(tkeys)
|
||||||
|
-- use the keys to retrieve the values in the sorted order
|
||||||
|
local prev_sample = 1
|
||||||
|
local first_sample_time = tkeys[1]
|
||||||
|
table.insert(interpolated_points, tonumber(points[tkeys[1]])/100)
|
||||||
|
local time_done = 0
|
||||||
|
while tkeys[prev_sample + 1] and time_done < graph_time do
|
||||||
|
local cur_time = time_done + first_sample_time
|
||||||
|
if cur_time > tkeys[prev_sample + 1] then
|
||||||
|
prev_sample += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(interpolated_points, tonumber(points[tkeys[prev_sample]])/100)
|
||||||
|
time_done += interpol_time
|
||||||
|
end
|
||||||
|
return interpolated_points
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function render(point_str,points)
|
||||||
|
panel.render(ui.column({ gap = 8, radius = 8, align = "stretch", fill = "surface_variant" }, {
|
||||||
|
ui.row( {paddingH= 10, paddingV = 6},{ ui.label({text = noctalia.tr("text.graph_name"), fontSize = 24, fontWeight = "heavy", textAlign = "center"}),}),
|
||||||
|
ui.graph({
|
||||||
|
values = points,
|
||||||
|
color = "primary",
|
||||||
|
lineWidth = 2,
|
||||||
|
fillOpacity = 0.45,
|
||||||
|
height = 200,
|
||||||
|
width = 400
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
function update()
|
||||||
|
noctalia.setUpdateInterval(1000)
|
||||||
|
barWidget.setGlyph("battery")
|
||||||
|
end
|
||||||
|
|
||||||
|
function onClick()
|
||||||
|
noctalia.togglePanel("frai3mega/battery-graph:battery-panel")
|
||||||
|
end
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
graph_time = 3600 * noctalia.getConfig("graph_time")
|
||||||
|
battery_path = noctalia.getConfig("battery_path")
|
||||||
|
interpol_time = 60 * noctalia.getConfig("interpol_time")
|
||||||
|
|
||||||
|
local function quote(s)
|
||||||
|
return "'" .. tostring(s):gsub("'", "'\\''") .. "'"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function validate(s)
|
||||||
|
if s:match("^/org/freedesktop/UPower/devices/[%a%d_]+$") ~= nil then
|
||||||
|
return quote(s)
|
||||||
|
else
|
||||||
|
noctalia.log("Invalid battery dbus path. Check that it is correct")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local cmd = table.concat({"gdbus call --system --dest org.freedesktop.UPower --object-path",validate(battery_path),"--method org.freedesktop.UPower.Device.GetHistory charge",quote( graph_time ), "1000"}, " ")
|
||||||
|
|
||||||
|
function onOpen()
|
||||||
|
-- noctalia.setUpdateInterval(1000)
|
||||||
|
noctalia.runAsync(cmd, parse)
|
||||||
|
end
|
||||||
|
|
||||||
|
function parse(result)
|
||||||
|
local points = {}
|
||||||
|
for tuple in result.stdout:gmatch("%(([^%)]+)%)") do
|
||||||
|
local fields = {}
|
||||||
|
for field in tuple:gmatch("[^,]+") do
|
||||||
|
field = field:match("^%s*(.-)%s*$") -- trim whitespace
|
||||||
|
field = field:gsub("^%S+%s+", "") -- strip "uint32 " style prefix (only if followed by more content)
|
||||||
|
table.insert(fields, field)
|
||||||
|
end
|
||||||
|
local ts, value = tonumber(fields[1]), tonumber(fields[2])
|
||||||
|
if value ~= 0.0 then
|
||||||
|
points[ts] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local interpolated_points = interpolate(points)
|
||||||
|
render(table.concat(interpolated_points, " "), interpolated_points)
|
||||||
|
end
|
||||||
|
|
||||||
|
function interpolate(points )
|
||||||
|
local interpolated_points = {}
|
||||||
|
|
||||||
|
local tkeys = {}
|
||||||
|
for k in pairs(points) do
|
||||||
|
table.insert(tkeys, k)
|
||||||
|
end
|
||||||
|
table.sort(tkeys)
|
||||||
|
-- use the keys to retrieve the values in the sorted order
|
||||||
|
local prev_sample = 1
|
||||||
|
local first_sample_time = tkeys[1]
|
||||||
|
table.insert(interpolated_points, tonumber(points[tkeys[1]])/100)
|
||||||
|
local time_done = 0
|
||||||
|
while tkeys[prev_sample + 1] and time_done < graph_time do
|
||||||
|
local cur_time = time_done + first_sample_time
|
||||||
|
if cur_time > tkeys[prev_sample + 1] then
|
||||||
|
prev_sample += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(interpolated_points, tonumber(points[tkeys[prev_sample]])/100)
|
||||||
|
time_done += interpol_time
|
||||||
|
end
|
||||||
|
return interpolated_points
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function render(point_str,points)
|
||||||
|
panel.render(ui.column({ gap = 8, radius = 8, align = "stretch", fill = "surface_variant" }, {
|
||||||
|
ui.row( {paddingH= 10, paddingV = 6},{ ui.label({text = noctalia.tr("text.graph_name"), fontSize = 24, fontWeight = "heavy", textAlign = "center"}),}),
|
||||||
|
ui.graph({
|
||||||
|
values = points,
|
||||||
|
color = "primary",
|
||||||
|
lineWidth = 2,
|
||||||
|
fillOpacity = 0.45,
|
||||||
|
height = 200,
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
id = "frai3mega/battery-graph"
|
||||||
|
name = "Battery graph"
|
||||||
|
version = "1.0.0"
|
||||||
|
author = "frai3mega"
|
||||||
|
license = "MIT"
|
||||||
|
icon = "battery"
|
||||||
|
description = "Plots battery level on a graph"
|
||||||
|
plugin_api = 3
|
||||||
|
tags = ["hardware", "utility", "desktop", "panel"]
|
||||||
|
dependencies = ["upowerd", "gdbus"]
|
||||||
|
|
||||||
|
[[setting]]
|
||||||
|
key = "graph_time"
|
||||||
|
type = "int"
|
||||||
|
label_key = "settings.graph_time.label"
|
||||||
|
description_key = "settings.graph_time.description"
|
||||||
|
default = 6
|
||||||
|
|
||||||
|
[[setting]]
|
||||||
|
key = "battery_path"
|
||||||
|
type = "string"
|
||||||
|
label_key = "settings.battery_path.label"
|
||||||
|
description_key = "settings.battery_path.description"
|
||||||
|
default = "/org/freedesktop/UPower/devices/battery_BAT0"
|
||||||
|
|
||||||
|
[[setting]]
|
||||||
|
key = "interpol_time"
|
||||||
|
type = "int"
|
||||||
|
label_key = "settings.interpol_time.label"
|
||||||
|
description_key = "settings.interpol_time.description"
|
||||||
|
default = 5
|
||||||
|
|
||||||
|
|
||||||
|
[[widget]]
|
||||||
|
id = "battery-graph-widget"
|
||||||
|
entry = "battery-graph.luau"
|
||||||
|
|
||||||
|
[[panel]]
|
||||||
|
id = "battery-panel"
|
||||||
|
entry = "battery-panel.luau"
|
||||||
|
|
||||||
|
[[desktop_widget]]
|
||||||
|
id = "battery-graph-desktop"
|
||||||
|
entry = "battery-desktop.luau"
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"settings": {
|
||||||
|
"graph_time": {
|
||||||
|
"label": "Graph timeframe",
|
||||||
|
"description": "How long of a timeframe does the graph plot in hours"
|
||||||
|
},
|
||||||
|
"battery_path": {
|
||||||
|
"label": "Battery path",
|
||||||
|
"description": "Dbus path to the upower battery device"
|
||||||
|
},
|
||||||
|
"interpol_time": {
|
||||||
|
"label": "Time between points",
|
||||||
|
"description": "How long should the thime between points be in minutes"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"graph_name": "Battery"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user