mirror of
https://github.com/henrygd/beszel.git
synced 2026-08-17 07:47:48 +02:00
- Report battery data for individual devices - Select a representative battery for legacy fields and alerts - Average named battery data independently - Display multiple batteries in system charts - Add cross-platform coverage and transport tests
77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
//go:build darwin
|
|
|
|
package battery
|
|
|
|
import (
|
|
"os/exec"
|
|
|
|
"howett.net/plist"
|
|
)
|
|
|
|
type macBattery struct {
|
|
CurrentCapacity int `plist:"CurrentCapacity"`
|
|
MaxCapacity int `plist:"MaxCapacity"`
|
|
FullyCharged bool `plist:"FullyCharged"`
|
|
IsCharging bool `plist:"IsCharging"`
|
|
ExternalConnected bool `plist:"ExternalConnected"`
|
|
}
|
|
|
|
func readMacBatteries() ([]macBattery, error) {
|
|
out, err := exec.Command("ioreg", "-n", "AppleSmartBattery", "-r", "-a").Output()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(out) == 0 {
|
|
return nil, nil
|
|
}
|
|
var batteries []macBattery
|
|
if _, err := plist.Unmarshal(out, &batteries); err != nil {
|
|
return nil, err
|
|
}
|
|
return batteries, nil
|
|
}
|
|
|
|
func HasReadableBattery() bool {
|
|
batteries, _ := GetBatteryStats()
|
|
return len(batteries) > 0
|
|
}
|
|
|
|
// GetBatteryStats returns every readable battery reported by macOS.
|
|
func GetBatteryStats() ([]Battery, error) {
|
|
batteries, err := readMacBatteries()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(batteries) == 0 {
|
|
return nil, errNoBatteries
|
|
}
|
|
result := make([]Battery, 0, len(batteries))
|
|
for _, bat := range batteries {
|
|
if bat.MaxCapacity <= 0 {
|
|
// skip ghost batteries with 0 capacity
|
|
// https://github.com/distatus/battery/issues/34
|
|
continue
|
|
}
|
|
percent := min(max(float64(bat.CurrentCapacity)/float64(bat.MaxCapacity)*100, 0), 100)
|
|
state := stateUnknown
|
|
switch {
|
|
case !bat.ExternalConnected:
|
|
state = stateDischarging
|
|
case bat.IsCharging:
|
|
state = stateCharging
|
|
case bat.CurrentCapacity == 0:
|
|
state = stateEmpty
|
|
case !bat.FullyCharged:
|
|
state = stateIdle
|
|
default:
|
|
state = stateFull
|
|
}
|
|
result = append(result, Battery{Name: "Primary", Percent: uint8(percent), State: state,
|
|
FullChargeCapacity: uint64(bat.MaxCapacity), HasFullChargeCapacity: true, System: true})
|
|
}
|
|
if len(result) == 0 {
|
|
return nil, errNoBatteries
|
|
}
|
|
return normalizeBatteries(result), nil
|
|
}
|