Select Git revision
battery.go 3.20 KiB
// 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 {
delta := now.Sub(b.battStats[0].point)
if delta >= (60 * time.Second) {
discharge := math.Abs(batt.Current - b.battStats[0].charge)
if discharge > 0 {
timeLeft := time.Duration((batt.Full-batt.Current)/discharge) * delta
left = fmt.Sprintf("%dh%dm", int64(timeLeft.Hours()), int64(timeLeft.Minutes()-(timeLeft.Hours()*60)))
b.battStats = b.battStats[1:]
} else {
left = "0h0m"
}
}
}
b.battStats = append(b.battStats, battTS{
charge: batt.Current,
point: now,
})
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 := 100 * (batt.Current / batt.Design)
if percent < 20 {
color = b.Color20
}
if percent < 10 {
color = b.Color10
}
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)
}