From 8ee5950308ef08a4f2805486660c677a3dac1bd1 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Tue, 18 Feb 2020 11:27:29 -0600 Subject: [PATCH] Adds a battery gauge. --- CHANGELOG.md | 6 +++- README.md | 2 +- layout/layout.go | 4 +++ termui/gauge.go | 22 ++++++++++++ widgets/batterygauge.go | 77 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 termui/gauge.go create mode 100644 widgets/batterygauge.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 32bd5e4..91f6405 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > - **Fixed**: for any bug fixes. > - **Security**: in case of vulnerabilities. -## [3.3.0] - +## [3.x.x] - + +- Adds a battery gauge as `power` + +## [3.3.0] - 2020-02-17 - Added: Logs are now rotated. Settings are currently hard-coded at 4 files of 5MB each, so logs shouldn't take up more than 20MB. I'm going to see how many diff --git a/README.md b/README.md index a3ff80c..b2dcebc 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ and these are separated by spaces. 1. Each line is a row 2. Empty lines are skipped 3. Spaces are compressed (so you can do limited visual formatting) -4. Legal widget names are: cpu, disk, mem, temp, batt, net, procs +4. Legal widget names are: cpu, disk, mem, temp, batt, net, procs, power 5. Widget names are not case sensitive 4. The simplest row is a single widget, by name, e.g. ``` diff --git a/layout/layout.go b/layout/layout.go index c78bb67..5872cf2 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -170,6 +170,10 @@ func makeWidget(c gotop.Config, widRule widgetRule) interface{} { i++ } w = b + case "power": + b := widgets.NewBatteryGauge() + b.BarColor = ui.Color(c.Colorscheme.ProcCursor) + w = b default: log.Printf("Invalid widget name %s. Must be one of %v", widRule.Widget, widgetNames) return ui.NewBlock() diff --git a/termui/gauge.go b/termui/gauge.go new file mode 100644 index 0000000..db9a9c0 --- /dev/null +++ b/termui/gauge.go @@ -0,0 +1,22 @@ +package termui + +import ( + . "github.com/gizak/termui/v3" + gizak "github.com/gizak/termui/v3/widgets" +) + +// LineGraph implements a line graph of data points. +type Gauge struct { + *gizak.Gauge +} + +func NewGauge() *Gauge { + return &Gauge{ + Gauge: gizak.NewGauge(), + } +} + +func (self *Gauge) Draw(buf *Buffer) { + self.Gauge.Draw(buf) + self.Gauge.SetRect(self.Min.X, self.Min.Y, self.Inner.Dx(), self.Inner.Dy()) +} diff --git a/widgets/batterygauge.go b/widgets/batterygauge.go new file mode 100644 index 0000000..04b1434 --- /dev/null +++ b/widgets/batterygauge.go @@ -0,0 +1,77 @@ +package widgets + +import ( + "fmt" + "log" + //"math" + //"strconv" + "time" + + "github.com/distatus/battery" + "github.com/prometheus/client_golang/prometheus" + + . "github.com/xxxserxxx/gotop/termui" +) + +type BatteryGauge struct { + *Gauge + metric prometheus.Gauge +} + +func NewBatteryGauge() *BatteryGauge { + self := &BatteryGauge{Gauge: NewGauge()} + self.Title = " Power Level " + + self.update() + + go func() { + for range time.NewTicker(time.Second).C { + self.Lock() + self.update() + self.Unlock() + } + }() + + return self +} + +func (b *BatteryGauge) EnableMetric() { + bats, err := battery.GetAll() + if err != nil { + log.Printf("error setting up metrics: %v", err) + return + } + mx := 0.0 + cu := 0.0 + for _, bat := range bats { + mx += bat.Full + cu += bat.Current + gauge := prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "gotop", + Subsystem: "battery", + Name: "total", + }) + gauge.Set(cu / mx) + b.metric = gauge + prometheus.MustRegister(gauge) + } +} + +func (self *BatteryGauge) update() { + bats, err := battery.GetAll() + if err != nil { + log.Printf("error setting up metrics: %v", err) + return + } + mx := 0.0 + cu := 0.0 + for _, bat := range bats { + mx += bat.Full + cu += bat.Current + } + self.Percent = int((cu / mx) * 100.0) + self.Label = fmt.Sprintf("%d%%", self.Percent) + if self.metric != nil { + self.metric.Set(cu / mx) + } +}