mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-03 03:21:50 +02:00
agent: refactor new battery package (#1872)
This commit is contained in:
@@ -1,14 +1,11 @@
|
||||
//go:build !freebsd && !darwin && !linux && !windows
|
||||
|
||||
// Package battery provides functions to check if the system has a battery and to get the battery stats.
|
||||
package battery
|
||||
|
||||
import "errors"
|
||||
|
||||
func HasReadableBattery() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func GetBatteryStats() (uint8, uint8, error) {
|
||||
return 0, 0, errors.ErrUnsupported
|
||||
}
|
||||
const (
|
||||
stateUnknown uint8 = iota
|
||||
stateEmpty
|
||||
stateFull
|
||||
stateCharging
|
||||
stateDischarging
|
||||
stateIdle
|
||||
)
|
||||
|
||||
@@ -7,19 +7,11 @@ import (
|
||||
"log/slog"
|
||||
"math"
|
||||
"os/exec"
|
||||
"sync"
|
||||
|
||||
"howett.net/plist"
|
||||
)
|
||||
|
||||
const (
|
||||
stateUnknown uint8 = 0
|
||||
stateEmpty uint8 = 1
|
||||
stateFull uint8 = 2
|
||||
stateCharging uint8 = 3
|
||||
stateDischarging uint8 = 4
|
||||
stateIdle uint8 = 5
|
||||
)
|
||||
|
||||
type macBattery struct {
|
||||
CurrentCapacity int `plist:"CurrentCapacity"`
|
||||
MaxCapacity int `plist:"MaxCapacity"`
|
||||
@@ -28,11 +20,6 @@ type macBattery struct {
|
||||
ExternalConnected bool `plist:"ExternalConnected"`
|
||||
}
|
||||
|
||||
var (
|
||||
systemHasBattery = false
|
||||
haveCheckedBattery = false
|
||||
)
|
||||
|
||||
func readMacBatteries() ([]macBattery, error) {
|
||||
out, err := exec.Command("ioreg", "-n", "AppleSmartBattery", "-r", "-a").Output()
|
||||
if err != nil {
|
||||
@@ -49,11 +36,8 @@ func readMacBatteries() ([]macBattery, error) {
|
||||
}
|
||||
|
||||
// HasReadableBattery checks if the system has a battery and returns true if it does.
|
||||
func HasReadableBattery() bool {
|
||||
if haveCheckedBattery {
|
||||
return systemHasBattery
|
||||
}
|
||||
haveCheckedBattery = true
|
||||
var HasReadableBattery = sync.OnceValue(func() bool {
|
||||
systemHasBattery := false
|
||||
batteries, err := readMacBatteries()
|
||||
for _, bat := range batteries {
|
||||
if bat.MaxCapacity > 0 {
|
||||
@@ -65,7 +49,7 @@ func HasReadableBattery() bool {
|
||||
slog.Debug("No battery found", "err", err)
|
||||
}
|
||||
return systemHasBattery
|
||||
}
|
||||
})
|
||||
|
||||
// GetBatteryStats returns the current battery percent and charge state.
|
||||
// Uses CurrentCapacity/MaxCapacity to match the value macOS displays.
|
||||
|
||||
@@ -9,27 +9,14 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/henrygd/beszel/agent/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
stateUnknown uint8 = 0
|
||||
stateEmpty uint8 = 1
|
||||
stateFull uint8 = 2
|
||||
stateCharging uint8 = 3
|
||||
stateDischarging uint8 = 4
|
||||
stateIdle uint8 = 5
|
||||
)
|
||||
|
||||
const sysfsPowerSupply = "/sys/class/power_supply"
|
||||
|
||||
var (
|
||||
systemHasBattery = false
|
||||
haveCheckedBattery = false
|
||||
)
|
||||
|
||||
func getBatteryPaths() ([]string, error) {
|
||||
var getBatteryPaths = sync.OnceValues(func() ([]string, error) {
|
||||
entries, err := os.ReadDir(sysfsPowerSupply)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -42,7 +29,7 @@ func getBatteryPaths() ([]string, error) {
|
||||
}
|
||||
}
|
||||
return paths, nil
|
||||
}
|
||||
})
|
||||
|
||||
func parseSysfsState(status string) uint8 {
|
||||
switch status {
|
||||
@@ -62,11 +49,8 @@ func parseSysfsState(status string) uint8 {
|
||||
}
|
||||
|
||||
// HasReadableBattery checks if the system has a battery and returns true if it does.
|
||||
func HasReadableBattery() bool {
|
||||
if haveCheckedBattery {
|
||||
return systemHasBattery
|
||||
}
|
||||
haveCheckedBattery = true
|
||||
var HasReadableBattery = sync.OnceValue(func() bool {
|
||||
systemHasBattery := false
|
||||
paths, err := getBatteryPaths()
|
||||
for _, path := range paths {
|
||||
if _, ok := utils.ReadStringFileOK(filepath.Join(path, "capacity")); ok {
|
||||
@@ -78,7 +62,7 @@ func HasReadableBattery() bool {
|
||||
slog.Debug("No battery found", "err", err)
|
||||
}
|
||||
return systemHasBattery
|
||||
}
|
||||
})
|
||||
|
||||
// GetBatteryStats returns the current battery percent and charge state.
|
||||
// Reads /sys/class/power_supply/*/capacity directly so the kernel-reported
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build freebsd
|
||||
//go:build !darwin && !linux && !windows
|
||||
|
||||
package battery
|
||||
|
||||
@@ -6,21 +6,13 @@ import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"math"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
stateUnknown uint8 = 0
|
||||
stateEmpty uint8 = 1
|
||||
stateFull uint8 = 2
|
||||
stateCharging uint8 = 3
|
||||
stateDischarging uint8 = 4
|
||||
stateIdle uint8 = 5
|
||||
)
|
||||
|
||||
type batteryQueryInformation struct {
|
||||
BatteryTag uint32
|
||||
InformationLevel int32
|
||||
@@ -77,15 +69,16 @@ var guidDeviceBattery = winGUID{
|
||||
}
|
||||
|
||||
var (
|
||||
setupapi = &windows.LazyDLL{Name: "setupapi.dll", System: true}
|
||||
setupDiGetClassDevsW = setupapi.NewProc("SetupDiGetClassDevsW")
|
||||
setupDiEnumDeviceInterfaces = setupapi.NewProc("SetupDiEnumDeviceInterfaces")
|
||||
setupapi = &windows.LazyDLL{Name: "setupapi.dll", System: true}
|
||||
setupDiGetClassDevsW = setupapi.NewProc("SetupDiGetClassDevsW")
|
||||
setupDiEnumDeviceInterfaces = setupapi.NewProc("SetupDiEnumDeviceInterfaces")
|
||||
setupDiGetDeviceInterfaceDetailW = setupapi.NewProc("SetupDiGetDeviceInterfaceDetailW")
|
||||
setupDiDestroyDeviceInfoList = setupapi.NewProc("SetupDiDestroyDeviceInfoList")
|
||||
setupDiDestroyDeviceInfoList = setupapi.NewProc("SetupDiDestroyDeviceInfoList")
|
||||
)
|
||||
|
||||
func setupDiSetup(proc *windows.LazyProc, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, error) {
|
||||
r1, _, errno := syscall.Syscall6(proc.Addr(), nargs, a1, a2, a3, a4, a5, a6)
|
||||
_ = nargs
|
||||
r1, _, errno := syscall.SyscallN(proc.Addr(), a1, a2, a3, a4, a5, a6)
|
||||
if windows.Handle(r1) == windows.InvalidHandle {
|
||||
if errno != 0 {
|
||||
return 0, error(errno)
|
||||
@@ -96,7 +89,8 @@ func setupDiSetup(proc *windows.LazyProc, nargs, a1, a2, a3, a4, a5, a6 uintptr)
|
||||
}
|
||||
|
||||
func setupDiCall(proc *windows.LazyProc, nargs, a1, a2, a3, a4, a5, a6 uintptr) syscall.Errno {
|
||||
r1, _, errno := syscall.Syscall6(proc.Addr(), nargs, a1, a2, a3, a4, a5, a6)
|
||||
_ = nargs
|
||||
r1, _, errno := syscall.SyscallN(proc.Addr(), a1, a2, a3, a4, a5, a6)
|
||||
if r1 == 0 {
|
||||
if errno != 0 {
|
||||
return errno
|
||||
@@ -137,7 +131,7 @@ func winBatteryGet(idx int) (full, current uint32, state uint8, err error) {
|
||||
if err != nil {
|
||||
return 0, 0, stateUnknown, err
|
||||
}
|
||||
defer syscall.Syscall(setupDiDestroyDeviceInfoList.Addr(), 1, hdev, 0, 0)
|
||||
defer syscall.SyscallN(setupDiDestroyDeviceInfoList.Addr(), hdev)
|
||||
|
||||
var did spDeviceInterfaceData
|
||||
did.cbSize = uint32(unsafe.Sizeof(did))
|
||||
@@ -256,17 +250,9 @@ func winBatteryGet(idx int) (full, current uint32, state uint8, err error) {
|
||||
return bi.FullChargedCapacity, bs.Capacity, readWinBatteryState(bs.PowerState), nil
|
||||
}
|
||||
|
||||
var (
|
||||
systemHasBattery = false
|
||||
haveCheckedBattery = false
|
||||
)
|
||||
|
||||
// HasReadableBattery checks if the system has a battery and returns true if it does.
|
||||
func HasReadableBattery() bool {
|
||||
if haveCheckedBattery {
|
||||
return systemHasBattery
|
||||
}
|
||||
haveCheckedBattery = true
|
||||
var HasReadableBattery = sync.OnceValue(func() bool {
|
||||
systemHasBattery := false
|
||||
full, _, _, err := winBatteryGet(0)
|
||||
if err == nil && full > 0 {
|
||||
systemHasBattery = true
|
||||
@@ -275,7 +261,7 @@ func HasReadableBattery() bool {
|
||||
slog.Debug("No battery found", "err", err)
|
||||
}
|
||||
return systemHasBattery
|
||||
}
|
||||
})
|
||||
|
||||
// GetBatteryStats returns the current battery percent and charge state.
|
||||
func GetBatteryStats() (batteryPercent uint8, batteryState uint8, err error) {
|
||||
|
||||
2
go.mod
2
go.mod
@@ -5,7 +5,7 @@ go 1.26.1
|
||||
require (
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/coreos/go-systemd/v22 v22.7.0
|
||||
github.com/ebitengine/purego v0.10.0
|
||||
github.com/ebitengine/purego v0.10.0
|
||||
github.com/fxamacker/cbor/v2 v2.9.0
|
||||
github.com/gliderlabs/ssh v0.3.8
|
||||
github.com/google/uuid v1.6.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -17,8 +17,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/distatus/battery v0.11.0 h1:KJk89gz90Iq/wJtbjjM9yUzBXV+ASV/EG2WOOL7N8lc=
|
||||
github.com/distatus/battery v0.11.0/go.mod h1:KmVkE8A8hpIX4T78QRdMktYpEp35QfOL8A8dwZBxq2k=
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8=
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
|
||||
Reference in New Issue
Block a user