standardise interface to metrics
call as follows: (let [m (metricname.new)] (m:read) (m:read) ... )
This commit is contained in:
parent
b6a8048c8b
commit
463c1eea03
@ -17,9 +17,9 @@ Not quite dogfood-ready yet, but fast approaching.
|
|||||||
* blinkenlicht.fnl is the module that parses `bar` and `indicator`
|
* blinkenlicht.fnl is the module that parses `bar` and `indicator`
|
||||||
forms and does all the UI
|
forms and does all the UI
|
||||||
|
|
||||||
* metric.fnl is a collection of functions that read metrics (load
|
* metric/*.fnl is a collection of modules that read metrics (load
|
||||||
average, battery status etc) from the system, for indicators to
|
average, connectivity, battery status etc) from the system, for
|
||||||
display.
|
indicators to display.
|
||||||
|
|
||||||
Use the `default.nix` for guidance as to libraries and other setup
|
Use the `default.nix` for guidance as to libraries and other setup
|
||||||
required - or just use it, of course.
|
required - or just use it, of course.
|
||||||
@ -43,10 +43,10 @@ Gtk will find it anyway. Magic.
|
|||||||
* [X] add some mechanism for indicators that wait for events instead of polling
|
* [X] add some mechanism for indicators that wait for events instead of polling
|
||||||
* [X] set indicator background colour (use css for this?)
|
* [X] set indicator background colour (use css for this?)
|
||||||
* [ ] update image/label widget instead of destroying
|
* [ ] update image/label widget instead of destroying
|
||||||
* [ ] allow height customisation
|
* [ ] allow image height customisation
|
||||||
* [X] set poll interval based on indicators' requested intervals
|
* [X] set poll interval based on indicators' requested intervals
|
||||||
* [X] allow indicator to change styles based on status
|
* [X] allow indicator to change styles based on status
|
||||||
* [ ] add metrics for
|
* [ ] add metrics for
|
||||||
- wireless connected/strength
|
- [X] wireless connected/strength
|
||||||
- wwan connected/type (hspa, lte, etc)/signal
|
- wwan connected/type (hspa, lte, etc)/signal
|
||||||
- cpu %
|
- cpu %
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
(local {: view} (require :fennel))
|
(local {: view} (require :fennel))
|
||||||
|
|
||||||
(local iostream (require :iostream))
|
(local iostream (require :iostream))
|
||||||
(local metric (require :metric))
|
|
||||||
(local uplink (require :uplink))
|
|
||||||
(local modem (require :modem))
|
(local modem (require :modem))
|
||||||
|
|
||||||
|
(local uplink (require :metric.uplink))
|
||||||
|
(local battery (require :metric.battery))
|
||||||
|
(local cpustat (require :metric.cpustat))
|
||||||
|
|
||||||
(stylesheet "licht.css")
|
(stylesheet "licht.css")
|
||||||
|
|
||||||
(fn battery-icon-codepoint [status percent]
|
(fn battery-icon-codepoint [status percent]
|
||||||
@ -40,26 +42,27 @@
|
|||||||
(indicator {
|
(indicator {
|
||||||
:wait-for { :interval (* 1 500) }
|
:wait-for { :interval (* 1 500) }
|
||||||
:refresh
|
:refresh
|
||||||
#(let [current (. (metric.cpustat) :iowait)
|
(let [stat (cpustat.new)]
|
||||||
delta (- current previous)
|
#(let [current (. (stat:read) :iowait)
|
||||||
v (if (> delta 4) "" " ")]
|
delta (- current previous)
|
||||||
(set previous current)
|
v (if (> delta 4) "" " ")]
|
||||||
{:text v})
|
(set previous current)
|
||||||
|
{:text v}))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
(let [modem (modem.new)]
|
(indicator {
|
||||||
(indicator {
|
:wait-for {
|
||||||
:wait-for {
|
|
||||||
:interval (* 4 1000)
|
:interval (* 4 1000)
|
||||||
}
|
}
|
||||||
:refresh
|
:refresh
|
||||||
|
(let [modem (modem.new)]
|
||||||
#(let [{:m3gpp-operator-name operator
|
#(let [{:m3gpp-operator-name operator
|
||||||
:signal-quality quality} (modem:value)]
|
:signal-quality quality} (modem:read)]
|
||||||
{:text (.. operator
|
{:text (.. operator
|
||||||
;" " (. quality 1) "dBm"
|
;;" " (. quality 1) "dBm"
|
||||||
)
|
)
|
||||||
})
|
}))
|
||||||
}))
|
})
|
||||||
|
|
||||||
(let [uplink (uplink.new)
|
(let [uplink (uplink.new)
|
||||||
input (iostream.from-descriptor uplink.fd)]
|
input (iostream.from-descriptor uplink.fd)]
|
||||||
@ -68,7 +71,7 @@
|
|||||||
:input [input]
|
:input [input]
|
||||||
}
|
}
|
||||||
:refresh
|
:refresh
|
||||||
#(let [status (uplink:status)]
|
#(let [status (uplink:read)]
|
||||||
(if status
|
(if status
|
||||||
{:text (.. (or status.ssid status.name "?")
|
{:text (.. (or status.ssid status.name "?")
|
||||||
" "
|
" "
|
||||||
@ -85,15 +88,17 @@
|
|||||||
(indicator {
|
(indicator {
|
||||||
:wait-for { :interval (* 1000 10) }
|
:wait-for { :interval (* 1000 10) }
|
||||||
:refresh
|
:refresh
|
||||||
#(let [{:power-supply-capacity percent
|
(let [battery (battery.new (or (os.getenv "BLINKEN_BATTERY")
|
||||||
:power-supply-status status}
|
"axp20x-battery"))]
|
||||||
(metric.battery "axp20x-battery")
|
#(let [{:power-supply-capacity percent
|
||||||
icon-code (battery-icon-codepoint
|
:power-supply-status status}
|
||||||
status (tonumber percent))]
|
(battery.read)
|
||||||
{:text
|
icon-code (battery-icon-codepoint
|
||||||
(string.format "%s %d%%" (utf8.char icon-code) percent)
|
status (tonumber percent))]
|
||||||
:classes ["battery" (if (< (tonumber percent) 20) "low" "ok")]
|
{:text
|
||||||
})
|
(string.format "%s %d%%" (utf8.char icon-code) percent)
|
||||||
|
:classes ["battery" (if (< (tonumber percent) 20) "low" "ok")]
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
(indicator {
|
(indicator {
|
||||||
:wait-for { :interval 4000 }
|
:wait-for { :interval 4000 }
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
(local {: view} (require :fennel))
|
|
||||||
|
|
||||||
(fn loadavg []
|
|
||||||
(with-open [f (io.open "/proc/loadavg" :r)]
|
|
||||||
(let [line (f:read "*a")
|
|
||||||
(one five fifteen) (line:match "([%d.]+) +([%d.]+) +([%d.]+)")]
|
|
||||||
(values (tonumber one) (tonumber five) (tonumber fifteen)))))
|
|
||||||
|
|
||||||
(fn battery [name]
|
|
||||||
(let [name (.. "/sys/class/power_supply/" name "/uevent")]
|
|
||||||
(with-open [f (io.open name :r)]
|
|
||||||
(let [fields {}]
|
|
||||||
(each [line #(f:read "*l")]
|
|
||||||
(let [(name value) (line:match "([^=]+)=(.+)")]
|
|
||||||
(tset fields (: (name:gsub "_" "-") :lower) value)))
|
|
||||||
fields))))
|
|
||||||
|
|
||||||
(fn parse-cpu-stat-line [line]
|
|
||||||
(let [labels [:user :nice :system :idle :iowait
|
|
||||||
:irq :softirq :steal :guest :guest_nice]
|
|
||||||
vals (icollect [field (line:gmatch "([%d.]+)")]
|
|
||||||
(tonumber field))]
|
|
||||||
(collect [i label (ipairs labels)]
|
|
||||||
label (. vals i))))
|
|
||||||
|
|
||||||
(var proc-stat-handle nil)
|
|
||||||
|
|
||||||
(fn cpustat [path]
|
|
||||||
(if proc-stat-handle
|
|
||||||
(proc-stat-handle:seek :set 0)
|
|
||||||
(set proc-stat-handle (io.open "/proc/stat" :r)))
|
|
||||||
(let [f proc-stat-handle]
|
|
||||||
(accumulate [ret nil
|
|
||||||
line #(f:read "*l") ]
|
|
||||||
(if (= (string.sub line 1 (# "cpu ")) "cpu ")
|
|
||||||
(parse-cpu-stat-line line)
|
|
||||||
ret))))
|
|
||||||
|
|
||||||
{: loadavg
|
|
||||||
: battery
|
|
||||||
: cpustat
|
|
||||||
}
|
|
15
blinkenlicht/metric/battery.fnl
Normal file
15
blinkenlicht/metric/battery.fnl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
(fn battery [name]
|
||||||
|
(let [name (.. "/sys/class/power_supply/" name "/uevent")]
|
||||||
|
(with-open [f (io.open name :r)]
|
||||||
|
(let [fields {}]
|
||||||
|
(each [line #(f:read "*l")]
|
||||||
|
(let [(name value) (line:match "([^=]+)=(.+)")]
|
||||||
|
(tset fields (: (name:gsub "_" "-") :lower) value)))
|
||||||
|
fields))))
|
||||||
|
|
||||||
|
{ :new
|
||||||
|
(fn [name]
|
||||||
|
{
|
||||||
|
:read #(battery name)
|
||||||
|
})
|
||||||
|
}
|
24
blinkenlicht/metric/cpustat.fnl
Normal file
24
blinkenlicht/metric/cpustat.fnl
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
(fn parse-cpu-stat-line [line]
|
||||||
|
(let [labels [:user :nice :system :idle :iowait
|
||||||
|
:irq :softirq :steal :guest :guest_nice]
|
||||||
|
vals (icollect [field (line:gmatch "([%d.]+)")]
|
||||||
|
(tonumber field))]
|
||||||
|
(collect [i label (ipairs labels)]
|
||||||
|
label (. vals i))))
|
||||||
|
|
||||||
|
(fn cpustat [proc-stat-handle]
|
||||||
|
(let [f proc-stat-handle]
|
||||||
|
(f:seek :set 0)
|
||||||
|
(accumulate [ret nil
|
||||||
|
line #(f:read "*l")
|
||||||
|
:until ret]
|
||||||
|
(if (= (string.sub line 1 (# "cpu ")) "cpu ")
|
||||||
|
(parse-cpu-stat-line line)
|
||||||
|
ret))))
|
||||||
|
{
|
||||||
|
:new
|
||||||
|
#(let [handle (io.open "/proc/stat" :r)]
|
||||||
|
{
|
||||||
|
:read #(cpustat handle)
|
||||||
|
})
|
||||||
|
}
|
9
blinkenlicht/metric/loadavg.fnl
Normal file
9
blinkenlicht/metric/loadavg.fnl
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
(fn loadavg []
|
||||||
|
(with-open [f (io.open "/proc/loadavg" :r)]
|
||||||
|
(let [line (f:read "*a")
|
||||||
|
(one five fifteen) (line:match "([%d.]+) +([%d.]+) +([%d.]+)")]
|
||||||
|
(values (tonumber one) (tonumber five) (tonumber fifteen)))))
|
||||||
|
|
||||||
|
{:new #{
|
||||||
|
:read #(loadavg)
|
||||||
|
})
|
@ -90,13 +90,13 @@
|
|||||||
:refresh #(each [_ event (ipairs (sock:event))]
|
:refresh #(each [_ event (ipairs (sock:event))]
|
||||||
(handle-event event))
|
(handle-event event))
|
||||||
:fd (sock:fd)
|
:fd (sock:fd)
|
||||||
:status (fn [self]
|
:read (fn [self]
|
||||||
(self:refresh)
|
(self:refresh)
|
||||||
(let [defaultroute routes.default
|
(let [defaultroute routes.default
|
||||||
interface (and defaultroute
|
interface (and defaultroute
|
||||||
(. links defaultroute.index))]
|
(. links defaultroute.index))]
|
||||||
(and interface (= interface.running "yes")
|
(and interface (= interface.running "yes")
|
||||||
(get-network-info interface))))
|
(get-network-info interface))))
|
||||||
:wait #(sock:poll 1000)
|
:wait #(sock:poll 1000)
|
||||||
:interface (fn [self ifnum]
|
:interface (fn [self ifnum]
|
||||||
(. links ifnum))
|
(. links ifnum))
|
@ -5,25 +5,22 @@
|
|||||||
(local variant dbus.variant)
|
(local variant dbus.variant)
|
||||||
|
|
||||||
;; https://www.freedesktop.org/software/ModemManager/api/latest/ref-dbus.html
|
;; https://www.freedesktop.org/software/ModemManager/api/latest/ref-dbus.html
|
||||||
(var the-modem-manager nil)
|
|
||||||
(fn modem-manager []
|
(fn modem-manager []
|
||||||
(when (not the-modem-manager)
|
(dbus.Proxy:new
|
||||||
(set the-modem-manager
|
{
|
||||||
(dbus.Proxy:new
|
:bus dbus.Bus.SYSTEM
|
||||||
{
|
:name "org.freedesktop.ModemManager1"
|
||||||
:bus dbus.Bus.SYSTEM
|
:interface "org.freedesktop.DBus.ObjectManager"
|
||||||
:name "org.freedesktop.ModemManager1"
|
:path "/org/freedesktop/ModemManager1"
|
||||||
:interface "org.freedesktop.DBus.ObjectManager"
|
}))
|
||||||
:path "/org/freedesktop/ModemManager1"
|
|
||||||
})))
|
|
||||||
the-modem-manager)
|
|
||||||
|
|
||||||
;; this is a function because the path to the modem may change
|
;; this is a function because the path to the modem may change
|
||||||
;; (e.g. due to suspend/resume cycles causing services to be stopped
|
;; (e.g. due to suspend/resume cycles causing services to be stopped
|
||||||
;; and started)
|
;; and started)
|
||||||
|
|
||||||
(fn modem-interface []
|
(fn modem-interface [manager]
|
||||||
(let [modem-path (next (: (assert (modem-manager)) :GetManagedObjects))]
|
(let [modem-path (next (: (assert manager) :GetManagedObjects))]
|
||||||
(dbus.Proxy:new
|
(dbus.Proxy:new
|
||||||
{
|
{
|
||||||
:bus dbus.Bus.SYSTEM
|
:bus dbus.Bus.SYSTEM
|
||||||
@ -33,10 +30,11 @@
|
|||||||
})))
|
})))
|
||||||
|
|
||||||
(fn new-modem-status []
|
(fn new-modem-status []
|
||||||
{
|
(let [manager (modem-manager)]
|
||||||
:value #(let [m (modem-interface)]
|
{
|
||||||
(variant.strip (m:GetStatus)))
|
:read #(let [m (modem-interface manager)]
|
||||||
})
|
(variant.strip (m:GetStatus)))
|
||||||
|
}))
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
(let [ctx (: (GLib.MainLoop) :get_context)
|
(let [ctx (: (GLib.MainLoop) :get_context)
|
||||||
|
Loading…
Reference in New Issue
Block a user