Skip to content
Snippets Groups Projects
Select Git revision
  • c6014adff2d320a7623bb24da733ae211369d75c
  • main default protected
2 results

battery.go

Blame
  • 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)
    }