From 8ca22041615d8f902c592f02bd60878eda29bcc3 Mon Sep 17 00:00:00 2001 From: Kevin Lyda <kevin@lyda.ie> Date: Fri, 2 Dec 2022 22:26:10 +0000 Subject: [PATCH] Add battery module. --- go.mod | 2 + go.sum | 7 +++ modules/battery.go | 138 +++++++++++++++++++++++++++++++++++++++++++++ modules/clicks.go | 2 +- modules/date.go | 9 ++- modules/error.go | 7 ++- modules/modules.go | 5 +- modules/text.go | 9 ++- 8 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 modules/battery.go diff --git a/go.mod b/go.mod index f919972..381786f 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( ) require ( + github.com/distatus/battery v0.10.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/magiconair/properties v1.8.6 // indirect @@ -25,4 +26,5 @@ require ( github.com/subosito/gotenv v1.4.1 // indirect golang.org/x/text v0.4.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect ) diff --git a/go.sum b/go.sum index ceb5a35..d003e20 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/distatus/battery v0.10.0 h1:YbizvmV33mqqC1fPCAEaQGV3bBhfYOfM+2XmL+mvt5o= +github.com/distatus/battery v0.10.0/go.mod h1:STnSvFLX//eEpkaN7qWRxCWxrWOcssTDgnG4yqq9BRE= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -125,6 +127,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -282,6 +285,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -466,6 +470,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -479,6 +484,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= +howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/modules/battery.go b/modules/battery.go new file mode 100644 index 0000000..4ea57cd --- /dev/null +++ b/modules/battery.go @@ -0,0 +1,138 @@ +// Package modules implements all the modules. +// Copyright (C) 2022 Kevin Lyda <kevin@lyda.ie> +package modules + +import ( + "fmt" + "math" + "time" + + "github.com/distatus/battery" +) + +type battTS struct { + charge float64 + point time.Time +} + +// BatteryMod module parameters for the battery module. +type BatteryMod struct { + name string + onclick string + battStats []battTS + Battery int `yaml:"battery"` + StatusEmp string `yaml:"status-chr"` + StatusChr string `yaml:"status-chr"` + StatusBat string `yaml:"status-bat"` + StatusUnk string `yaml:"status-unk"` + StatusFull string `yaml:"status-full"` + OnError string `yaml:"on-error"` + ColorOK string `yaml:"color-ok"` + Color20 string `yaml:"color-20"` + Color10 string `yaml:"color-10"` + ColorError string `yaml:"color-error"` +} + +// NewBattery creates a BatteryMod instance. +func NewBattery(m *Module) *BatteryMod { + b := &BatteryMod{ + name: m.Name, + onclick: m.OnClick, + } + if b.name == "" { + b.name = "battery" + } + return b +} + +// SetDefaults sets defaults. +func (b *BatteryMod) SetDefaults() { + if b.StatusEmp != "" { + b.StatusEmp = "---" + } + if b.StatusChr != "" { + b.StatusChr = "CHR" + } + if b.StatusBat != "" { + b.StatusBat = "BAT" + } + if b.StatusUnk != "" { + b.StatusUnk = "UNK" + } + if b.StatusFull != "" { + b.StatusFull = "FULL" + } + if b.OnError != "" { + b.OnError = "No BAT" + } + if b.ColorOK != "" { + b.ColorOK = "#11ff11" + } + if b.Color20 != "" { + b.Color20 = "#ffa500" + } + if b.Color10 != "" { + b.Color10 = "#ffff00" + } + if b.ColorError != "" { + b.ColorError = "#ff1111" + } +} + +// Name returns the name setting for the module. +func (b *BatteryMod) Name() string { + return b.name +} + +// OnClick returns the on-click setting for the module. +func (b *BatteryMod) OnClick() string { + return b.onclick +} + +// Render renders the module. +func (b *BatteryMod) Render() string { + // TODO: Alerting. + + now := time.Now() + batt, err := battery.Get(b.Battery) + if err != nil { + return fmt.Sprintf(`{"name": "%s", "full_text": "%s", "color": "%s"}`, b.name, b.OnError, b.ColorError) + } + left := "(?)" + if len(b.battStats) >= 1 { + b.battStats = append(b.battStats, battTS{ + charge: batt.Current, + point: now, + }) + delta := now.Sub(b.battStats[0].point) + if delta >= (60 * time.Second) { + discharge := math.Abs(batt.Current - b.battStats[0].charge) + timeLeft := time.Duration(batt.Current/discharge) * delta + left = fmt.Sprintf("%dh%dm", int64(timeLeft.Hours()), int64(timeLeft.Minutes())) + b.battStats = b.battStats[1:] + } + } + + states := [...]string{ + battery.Unknown: b.StatusUnk, + battery.Empty: b.StatusEmp, + battery.Full: b.StatusFull, + battery.Charging: b.StatusChr, + battery.Discharging: b.StatusBat, + } + + color := b.ColorOK + percent := batt.Current / batt.Full + if percent < 20 { + if percent < 10 { + color = b.Color10 + } else { + color = b.Color20 + } + } + + if b.Battery > 0 { + return fmt.Sprintf(`{"name": "%s", "full_text": "%s%d %.1f%% %s", "color": "%s"}`, b.name, states[batt.State], b.Battery, percent, left, color) + } + return fmt.Sprintf(`{"name": "%s", "full_text": "%s %.1f%% %s", "color": "%s"}`, b.name, states[batt.State], percent, left, color) +} diff --git a/modules/clicks.go b/modules/clicks.go index 018c331..5921c99 100644 --- a/modules/clicks.go +++ b/modules/clicks.go @@ -1,4 +1,4 @@ -// Package module implements all the modules. +// Package modules implements all the modules. // Copyright (C) 2022 Kevin Lyda <kevin@lyda.ie> package modules diff --git a/modules/date.go b/modules/date.go index a846897..f0c6698 100644 --- a/modules/date.go +++ b/modules/date.go @@ -1,4 +1,4 @@ -// Package module implements all the modules. +// Package modules implements all the modules. // Copyright (C) 2022 Kevin Lyda <kevin@lyda.ie> package modules @@ -29,6 +29,13 @@ func NewDate(m *Module) *DateMod { return d } +// SetDefaults sets defaults. +func (d *DateMod) SetDefaults() { + if d.Format == "" { + d.Format = "06/01/02 15:04" + } +} + // Name returns the name setting for the module. func (d *DateMod) Name() string { return d.name diff --git a/modules/error.go b/modules/error.go index 2213863..ad0eb28 100644 --- a/modules/error.go +++ b/modules/error.go @@ -1,4 +1,4 @@ -// Package module implements all the modules. +// Package modules implements all the modules. // Copyright (C) 2022 Kevin Lyda <kevin@lyda.ie> package modules @@ -25,6 +25,11 @@ func NewError(m *Module) *ErrorMod { return e } +// SetDefaults sets defaults. +func (e *ErrorMod) SetDefaults() { + return +} + // Name returns the name setting for the module. func (e *ErrorMod) Name() string { return e.name diff --git a/modules/modules.go b/modules/modules.go index e66bdcb..2322c63 100644 --- a/modules/modules.go +++ b/modules/modules.go @@ -1,4 +1,4 @@ -// Package module implements all the modules. +// Package modules implements all the modules. // Copyright (C) 2022 Kevin Lyda <kevin@lyda.ie> package modules @@ -11,6 +11,7 @@ import ( // ParamsInterface is the interface for module paramaters. type ParamsInterface interface { + SetDefaults() Name() string OnClick() string Render() string @@ -48,6 +49,8 @@ func (m *Module) UnmarshalYAML(node *yaml.Node) error { m.Params = NewDate(m) case "text": m.Params = NewText(m) + case "battery": + m.Params = NewBattery(m) default: return fmt.Errorf("module '%s' is unknown", params.Module) } diff --git a/modules/text.go b/modules/text.go index e5e845e..4c3be95 100644 --- a/modules/text.go +++ b/modules/text.go @@ -1,4 +1,4 @@ -// Package module implements all the modules. +// Package modules implements all the modules. // Copyright (C) 2022 Kevin Lyda <kevin@lyda.ie> package modules @@ -26,6 +26,13 @@ func NewText(m *Module) *TextMod { return t } +// SetDefaults sets defaults. +func (t *TextMod) SetDefaults() { + if t.Text == "" { + t.Text = "Hello world!" + } +} + // Name returns the name setting for the module. func (t *TextMod) Name() string { return t.name -- GitLab