package main import ( "strings" "sync" "time" ) const batteryCacheSeconds = 15 type BatteryProbe func() (bool, error) type batteryWatch struct { mu sync.Mutex probe BatteryProbe now func() time.Time debugf func(format string, args ...any) checked time.Time value bool warned bool } func newBatteryWatch(probe BatteryProbe, now func() time.Time) *batteryWatch { return &batteryWatch{probe: probe, now: now} } func (w *batteryWatch) OnBattery() bool { w.mu.Lock() defer w.mu.Unlock() moment := w.now() if !w.checked.IsZero() && moment.Sub(w.checked) < time.Duration(batteryCacheSeconds)*time.Second { return w.value } w.checked = moment value, err := w.probe() if err != nil { value = false if !w.warned && w.debugf != nil { w.debugf("battery state unknown, treating as mains power: %v", err) } w.warned = true } w.value = value return value } func parsePmset(text string) bool { return strings.Contains(text, "Now drawing from 'Battery Power'") } func windowsOnBattery(acLine, batteryFlag byte) bool { return acLine == 0 && batteryFlag != 128 && batteryFlag != 255 }