Initial commit
This commit is contained in:
1
vendor/github.com/distatus/battery/.gitignore
generated
vendored
Normal file
1
vendor/github.com/distatus/battery/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
cmd/battery/battery*
|
||||
7
vendor/github.com/distatus/battery/BREAKING.md
generated
vendored
Normal file
7
vendor/github.com/distatus/battery/BREAKING.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# 0.11.0
|
||||
|
||||
The `State` field is no longer just an `int`, but a separate `struct`.
|
||||
|
||||
It still implements the `Stringer` and `GoStringer` interfaces, so if you were just displaying the value, it should continue working as before.
|
||||
|
||||
For comparison purposes, the `State.Raw` field should be used now. It has all the same values as before + 2 new (`Undefined` and `Idle`).
|
||||
21
vendor/github.com/distatus/battery/LICENSE.md
generated
vendored
Normal file
21
vendor/github.com/distatus/battery/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2016 Karol 'Kenji Takahashi' Woźniak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
73
vendor/github.com/distatus/battery/README.md
generated
vendored
Normal file
73
vendor/github.com/distatus/battery/README.md
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
battery [](https://github.com/distatus/battery/actions/workflows/tests.yml) [](https://goreportcard.com/report/github.com/distatus/battery) [](https://pkg.go.dev/github.com/distatus/battery)
|
||||
=======
|
||||
|
||||
Cross-platform, normalized battery information library.
|
||||
|
||||
Gives access to a system independent, typed battery state, capacity, charge and voltage values recalculated as necessary to be returned in mW, mWh or V units.
|
||||
|
||||
Currently supported systems:
|
||||
|
||||
* Linux 2.6.39+
|
||||
* OS X 10.10+
|
||||
* Windows XP+
|
||||
* FreeBSD
|
||||
* DragonFlyBSD
|
||||
* NetBSD
|
||||
* OpenBSD
|
||||
* Solaris
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/distatus/battery
|
||||
```
|
||||
|
||||
Code Example
|
||||
------------
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/distatus/battery"
|
||||
)
|
||||
|
||||
func main() {
|
||||
batteries, err := battery.GetAll()
|
||||
if err != nil {
|
||||
fmt.Println("Could not get battery info!")
|
||||
return
|
||||
}
|
||||
for i, battery := range batteries {
|
||||
fmt.Printf("Bat%d: ", i)
|
||||
fmt.Printf("state: %s, ", battery.State.String())
|
||||
fmt.Printf("current capacity: %f mWh, ", battery.Current)
|
||||
fmt.Printf("last full capacity: %f mWh, ", battery.Full)
|
||||
fmt.Printf("design capacity: %f mWh, ", battery.Design)
|
||||
fmt.Printf("charge rate: %f mW, ", battery.ChargeRate)
|
||||
fmt.Printf("voltage: %f V, ", battery.Voltage)
|
||||
fmt.Printf("design voltage: %f V\n", battery.DesignVoltage)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
CLI
|
||||
---
|
||||
|
||||
There is also a little utility which - more or less - mimicks the GNU/Linux `acpi -b` command.
|
||||
|
||||
*Installation*
|
||||
|
||||
```bash
|
||||
$ go install github.com/distatus/battery/cmd/battery@latest
|
||||
```
|
||||
|
||||
*Usage*
|
||||
|
||||
```bash
|
||||
$ battery
|
||||
BAT0: Full, 95.61% [Voltage: 12.15V (design: 12.15V)]
|
||||
```
|
||||
174
vendor/github.com/distatus/battery/battery.go
generated
vendored
Normal file
174
vendor/github.com/distatus/battery/battery.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Package battery provides cross-platform, normalized battery information.
|
||||
//
|
||||
// Gives access to a system independent, typed battery state, capacity, charge and voltage values recalculated as necessary to be returned in mW, mWh or V units.
|
||||
//
|
||||
// Currently supported systems:
|
||||
//
|
||||
// Linux 2.6.39+
|
||||
// OS X 10.10+
|
||||
// Windows XP+
|
||||
// FreeBSD
|
||||
// DragonFlyBSD
|
||||
// NetBSD
|
||||
// OpenBSD
|
||||
// Solaris
|
||||
package battery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// AgnosticState type enumerates possible battery states, using platform agnostic naming.
|
||||
type AgnosticState int8
|
||||
|
||||
const (
|
||||
// Undefined specifies a state that was returned by the controller, but there is no
|
||||
// platform agnostic mapping for it.
|
||||
// This generally shouldn't happen, if it does consider opening a report for the library
|
||||
// (ideally with the contents of `State.Explain()` call as well).
|
||||
Undefined AgnosticState = -1
|
||||
// Unknown specifies a literal unknown state returned by the controller.
|
||||
// This state is also considered the "default", therefore it will be set when an Error
|
||||
// was returned from the Get/GetAll call.
|
||||
Unknown AgnosticState = iota - 1
|
||||
Empty
|
||||
Full
|
||||
Charging
|
||||
Discharging
|
||||
// Idle specifies a state where battery is in "capacity saving" mode.
|
||||
// It usually means that it sits idle at around 80% charge while power source is plugged in.
|
||||
Idle
|
||||
)
|
||||
|
||||
var states = map[AgnosticState]string{
|
||||
Undefined: "Undefined",
|
||||
Unknown: "Unknown",
|
||||
Empty: "Empty",
|
||||
Full: "Full",
|
||||
Charging: "Charging",
|
||||
Discharging: "Discharging",
|
||||
Idle: "Idle",
|
||||
}
|
||||
|
||||
func (s AgnosticState) String() string {
|
||||
return states[s]
|
||||
}
|
||||
|
||||
type State struct {
|
||||
Raw AgnosticState
|
||||
specific string
|
||||
}
|
||||
|
||||
func (s State) Explain() string {
|
||||
return s.specific
|
||||
}
|
||||
|
||||
func (s State) String() string {
|
||||
return s.Raw.String()
|
||||
}
|
||||
|
||||
func (s State) GoString() string {
|
||||
return fmt.Sprintf("%s (%s)", s.Raw, s.specific)
|
||||
}
|
||||
|
||||
// Battery type represents a single battery entry information.
|
||||
type Battery struct {
|
||||
// Current battery state.
|
||||
State State
|
||||
// Current (momentary) capacity (in mWh).
|
||||
Current float64
|
||||
// Last known full capacity (in mWh).
|
||||
Full float64
|
||||
// Reported design capacity (in mWh).
|
||||
Design float64
|
||||
// Current (momentary) charge rate (in mW).
|
||||
// It is always non-negative, consult .State field to check
|
||||
// whether it means charging or discharging.
|
||||
ChargeRate float64
|
||||
// Current voltage (in V).
|
||||
Voltage float64
|
||||
// Design voltage (in V).
|
||||
// Some systems (e.g. macOS) do not provide a separate
|
||||
// value for this. In such cases, or if getting this fails,
|
||||
// but getting `Voltage` succeeds, this field will have
|
||||
// the same value as `Voltage`, for convenience.
|
||||
DesignVoltage float64
|
||||
}
|
||||
|
||||
func (b *Battery) String() string {
|
||||
return fmt.Sprintf("%+v", *b)
|
||||
}
|
||||
|
||||
func get(sg func(idx int) (*Battery, error), idx int) (*Battery, error) {
|
||||
b, err := sg(idx)
|
||||
return b, wrapError(err)
|
||||
}
|
||||
|
||||
// Get returns battery information for given index.
|
||||
//
|
||||
// Note that index taken here is normalized, such that GetAll()[idx] == Get(idx).
|
||||
// It does not necessarily represent the "name" or "position" a battery was given
|
||||
// by the underlying system.
|
||||
//
|
||||
// If error != nil, it will be either ErrFatal or ErrPartial.
|
||||
func Get(idx int) (*Battery, error) {
|
||||
return get(systemGet, idx)
|
||||
}
|
||||
|
||||
func getAll(sg func() ([]*Battery, error)) ([]*Battery, error) {
|
||||
bs, err := sg()
|
||||
if errors, ok := err.(Errors); ok {
|
||||
nils := 0
|
||||
partials := 0
|
||||
for i, err := range errors {
|
||||
err = wrapError(err)
|
||||
if err == nil {
|
||||
nils++
|
||||
}
|
||||
if _, ok := err.(ErrPartial); ok {
|
||||
partials++
|
||||
}
|
||||
errors[i] = err
|
||||
}
|
||||
if nils == len(errors) {
|
||||
return bs, nil
|
||||
}
|
||||
if nils > 0 || partials > 0 {
|
||||
return bs, errors
|
||||
}
|
||||
return nil, ErrFatal{ErrAllNotNil}
|
||||
}
|
||||
if err != nil {
|
||||
return bs, ErrFatal{err}
|
||||
}
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
// GetAll returns information about all batteries in the system.
|
||||
//
|
||||
// If error != nil, it will be either ErrFatal or Errors.
|
||||
// If error is of type Errors, it is guaranteed that length of both returned slices is the same and that i-th error coresponds with i-th battery structure.
|
||||
func GetAll() ([]*Battery, error) {
|
||||
return getAll(systemGetAll)
|
||||
}
|
||||
117
vendor/github.com/distatus/battery/battery_darwin.go
generated
vendored
Normal file
117
vendor/github.com/distatus/battery/battery_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os/exec"
|
||||
|
||||
plist "howett.net/plist"
|
||||
)
|
||||
|
||||
type battery struct {
|
||||
Voltage int
|
||||
CurrentCapacity int `plist:"AppleRawCurrentCapacity"`
|
||||
MaxCapacity int `plist:"AppleRawMaxCapacity"`
|
||||
DesignCapacity int
|
||||
Amperage int64
|
||||
FullyCharged bool
|
||||
IsCharging bool
|
||||
ExternalConnected bool
|
||||
}
|
||||
|
||||
func readBatteries() ([]*battery, error) {
|
||||
out, err := exec.Command("ioreg", "-n", "AppleSmartBattery", "-r", "-a").Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(out) == 0 {
|
||||
// No batteries.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var data []*battery
|
||||
if _, err = plist.Unmarshal(out, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func convertBattery(battery *battery) *Battery {
|
||||
volts := float64(battery.Voltage) / 1000
|
||||
b := &Battery{
|
||||
Current: float64(battery.CurrentCapacity) * volts,
|
||||
Full: float64(battery.MaxCapacity) * volts,
|
||||
Design: float64(battery.DesignCapacity) * volts,
|
||||
ChargeRate: math.Abs(float64(battery.Amperage)) * volts,
|
||||
Voltage: volts,
|
||||
DesignVoltage: volts,
|
||||
}
|
||||
switch {
|
||||
case !battery.ExternalConnected:
|
||||
b.State.Raw = Discharging
|
||||
b.State.specific = "not(ExternalConnected)"
|
||||
case battery.IsCharging:
|
||||
b.State.Raw = Charging
|
||||
b.State.specific = "IsCharging"
|
||||
case battery.CurrentCapacity == 0:
|
||||
b.State.Raw = Empty
|
||||
b.State.specific = "CurrentCapacity is 0"
|
||||
case !battery.FullyCharged:
|
||||
b.State.Raw = Idle
|
||||
b.State.specific = "not(FullyCharged)"
|
||||
case battery.FullyCharged:
|
||||
b.State.Raw = Full
|
||||
b.State.specific = "FullyCharged"
|
||||
default:
|
||||
b.State.Raw = Undefined
|
||||
b.State.specific = fmt.Sprintf("%+v", *battery)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
batteries, err := readBatteries()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if idx >= len(batteries) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return convertBattery(batteries[idx]), nil
|
||||
}
|
||||
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
_batteries, err := readBatteries()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
batteries := make([]*Battery, len(_batteries))
|
||||
for i, battery := range _batteries {
|
||||
batteries[i] = convertBattery(battery)
|
||||
}
|
||||
return batteries, nil
|
||||
}
|
||||
153
vendor/github.com/distatus/battery/battery_freebsd_dragonfly_.go
generated
vendored
Normal file
153
vendor/github.com/distatus/battery/battery_freebsd_dragonfly_.go
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
//go:build freebsd || dragonfly
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func readUint32(bytes []byte) uint32 {
|
||||
var ret uint32
|
||||
for i, b := range bytes {
|
||||
ret |= uint32(b) << uint(i*8)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func uint32ToFloat64(num uint32) (float64, error) {
|
||||
if num == 0xffffffff {
|
||||
return 0, errors.New("Unknown value received")
|
||||
}
|
||||
return float64(num), nil
|
||||
}
|
||||
|
||||
func ioctl_(fd int, nr int64, retptr *[164]byte) error {
|
||||
return ioctl(fd, nr, 'B', unsafe.Sizeof(*retptr), unsafe.Pointer(retptr))
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
fd, err := unix.Open("/dev/acpi", unix.O_RDONLY, 0777)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer unix.Close(fd)
|
||||
|
||||
b := &Battery{}
|
||||
e := ErrPartial{}
|
||||
|
||||
// No unions in Go, so lets "emulate" union with byte array ;-].
|
||||
var retptr [164]byte
|
||||
// XXX What about byte encoding idx and storing it in retptr?
|
||||
// Then we wouldn't need this unsafe pointer manipulations
|
||||
unit := (*int)(unsafe.Pointer(&retptr[0]))
|
||||
|
||||
*unit = idx
|
||||
err = ioctl_(fd, 0x10, &retptr) // ACPIIO_BATT_GET_BIF
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mw := readUint32(retptr[0:4]) == 0 // acpi_bif.units
|
||||
|
||||
b.Design, e.Design = uint32ToFloat64(readUint32(retptr[4:8])) // acpi_bif.dcap
|
||||
b.Full, e.Full = uint32ToFloat64(readUint32(retptr[8:12])) // acpi_bif.lfcap
|
||||
b.DesignVoltage, e.DesignVoltage = uint32ToFloat64(readUint32(retptr[16:20])) // acpi_bif.dvol
|
||||
b.DesignVoltage /= 1000
|
||||
|
||||
*unit = idx
|
||||
err = ioctl_(fd, 0x11, &retptr) // APCIIO_BATT_GET_BST
|
||||
if err == nil {
|
||||
state := readUint32(retptr[0:4]) // acpi_bst.state
|
||||
b.State.specific = fmt.Sprintf("%x", state)
|
||||
switch state {
|
||||
case 0x0000:
|
||||
b.State.Raw = Full
|
||||
case 0x0001:
|
||||
b.State.Raw = Discharging
|
||||
case 0x0002:
|
||||
b.State.Raw = Charging
|
||||
case 0x0004:
|
||||
b.State.Raw = Empty
|
||||
default:
|
||||
b.State.Raw = Undefined
|
||||
}
|
||||
b.ChargeRate, e.ChargeRate = uint32ToFloat64(readUint32(retptr[4:8])) // acpi_bst.rate
|
||||
b.Current, e.Current = uint32ToFloat64(readUint32(retptr[8:12])) // acpi_bst.cap
|
||||
b.Voltage, e.Voltage = uint32ToFloat64(readUint32(retptr[12:16])) // acpi_bst.volt
|
||||
b.Voltage /= 1000
|
||||
} else {
|
||||
e.State = err
|
||||
e.ChargeRate = err
|
||||
e.Current = err
|
||||
e.Voltage = err
|
||||
}
|
||||
|
||||
if e.DesignVoltage != nil && e.Voltage == nil {
|
||||
b.DesignVoltage, e.DesignVoltage = b.Voltage, nil
|
||||
}
|
||||
|
||||
if !mw {
|
||||
if e.DesignVoltage == nil {
|
||||
b.Design *= b.DesignVoltage
|
||||
} else {
|
||||
e.Design = e.DesignVoltage
|
||||
}
|
||||
if e.Voltage == nil {
|
||||
b.Full *= b.Voltage
|
||||
b.ChargeRate *= b.Voltage
|
||||
b.Current *= b.Voltage
|
||||
} else {
|
||||
e.Full = e.Voltage
|
||||
e.ChargeRate = e.Voltage
|
||||
e.Current = e.Voltage
|
||||
}
|
||||
}
|
||||
|
||||
return b, e
|
||||
}
|
||||
|
||||
// There is no way to iterate over available batteries.
|
||||
// Therefore we assume here that if we were not able to retrieve
|
||||
// anything, it means we're done.
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
var batteries []*Battery
|
||||
var errors Errors
|
||||
for i := 0; ; i++ {
|
||||
b, err := systemGet(i)
|
||||
if perr, ok := err.(ErrPartial); ok && perr.noNil() {
|
||||
break
|
||||
}
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == 6 {
|
||||
break
|
||||
}
|
||||
batteries = append(batteries, b)
|
||||
errors = append(errors, err)
|
||||
}
|
||||
|
||||
return batteries, errors
|
||||
}
|
||||
165
vendor/github.com/distatus/battery/battery_linux.go
generated
vendored
Normal file
165
vendor/github.com/distatus/battery/battery_linux.go
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const sysfs = "/sys/class/power_supply"
|
||||
|
||||
func readFloat(path, filename string) (float64, error) {
|
||||
str, err := ioutil.ReadFile(filepath.Join(path, filename))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
num, err := strconv.ParseFloat(string(str[:len(str)-1]), 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return num / 1000, nil // Convert micro->milli
|
||||
}
|
||||
|
||||
func readAmp(path, filename string, volts float64) (float64, error) {
|
||||
val, err := readFloat(path, filename)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return val * volts, nil
|
||||
}
|
||||
|
||||
func isBattery(path string) bool {
|
||||
t, err := ioutil.ReadFile(filepath.Join(path, "type"))
|
||||
return err == nil && string(t) == "Battery\n"
|
||||
}
|
||||
|
||||
func getBatteryFiles() ([]string, error) {
|
||||
files, err := ioutil.ReadDir(sysfs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var bFiles []string
|
||||
for _, file := range files {
|
||||
path := filepath.Join(sysfs, file.Name())
|
||||
if isBattery(path) {
|
||||
bFiles = append(bFiles, path)
|
||||
}
|
||||
}
|
||||
return bFiles, nil
|
||||
}
|
||||
|
||||
func getByPath(path string) (*Battery, error) {
|
||||
b := &Battery{}
|
||||
e := ErrPartial{}
|
||||
b.Current, e.Current = readFloat(path, "energy_now")
|
||||
b.Voltage, e.Voltage = readFloat(path, "voltage_now")
|
||||
b.Voltage /= 1000
|
||||
|
||||
b.DesignVoltage, e.DesignVoltage = readFloat(path, "voltage_max_design")
|
||||
if e.DesignVoltage != nil {
|
||||
b.DesignVoltage, e.DesignVoltage = readFloat(path, "voltage_min_design")
|
||||
}
|
||||
if e.DesignVoltage != nil && e.Voltage == nil {
|
||||
b.DesignVoltage, e.DesignVoltage = b.Voltage, nil
|
||||
}
|
||||
b.DesignVoltage /= 1000
|
||||
|
||||
if os.IsNotExist(e.Current) {
|
||||
if e.DesignVoltage == nil {
|
||||
b.Design, e.Design = readAmp(path, "charge_full_design", b.DesignVoltage)
|
||||
} else {
|
||||
e.Design = e.DesignVoltage
|
||||
}
|
||||
if e.Voltage == nil {
|
||||
b.Current, e.Current = readAmp(path, "charge_now", b.Voltage)
|
||||
b.Full, e.Full = readAmp(path, "charge_full", b.Voltage)
|
||||
b.ChargeRate, e.ChargeRate = readAmp(path, "current_now", b.Voltage)
|
||||
} else {
|
||||
e.Current = e.Voltage
|
||||
e.Full = e.Voltage
|
||||
e.ChargeRate = e.Voltage
|
||||
}
|
||||
} else {
|
||||
b.Full, e.Full = readFloat(path, "energy_full")
|
||||
b.Design, e.Design = readFloat(path, "energy_full_design")
|
||||
b.ChargeRate, e.ChargeRate = readFloat(path, "power_now")
|
||||
}
|
||||
|
||||
status, err := ioutil.ReadFile(filepath.Join(path, "status"))
|
||||
if err == nil {
|
||||
status := string(status[:len(status)-1])
|
||||
b.State.specific = status
|
||||
switch status {
|
||||
case "Unknown":
|
||||
b.State.Raw = Unknown
|
||||
case "Empty":
|
||||
b.State.Raw = Empty
|
||||
case "Full":
|
||||
b.State.Raw = Full
|
||||
case "Charging":
|
||||
b.State.Raw = Charging
|
||||
case "Discharging":
|
||||
b.State.Raw = Discharging
|
||||
case "Not charging":
|
||||
b.State.Raw = Idle
|
||||
default:
|
||||
b.State.Raw = Undefined
|
||||
}
|
||||
} else {
|
||||
e.State = err
|
||||
}
|
||||
|
||||
return b, e
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
bFiles, err := getBatteryFiles()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if idx >= len(bFiles) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return getByPath(bFiles[idx])
|
||||
}
|
||||
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
bFiles, err := getBatteryFiles()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
batteries := make([]*Battery, len(bFiles))
|
||||
errors := make(Errors, len(bFiles))
|
||||
for i, bFile := range bFiles {
|
||||
battery, err := getByPath(bFile)
|
||||
batteries[i] = battery
|
||||
errors[i] = err
|
||||
}
|
||||
|
||||
return batteries, errors
|
||||
}
|
||||
221
vendor/github.com/distatus/battery/battery_netbsd.go
generated
vendored
Normal file
221
vendor/github.com/distatus/battery/battery_netbsd.go
generated
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
plist "howett.net/plist"
|
||||
)
|
||||
|
||||
type plistref struct {
|
||||
pref_plist unsafe.Pointer
|
||||
pref_len uint64
|
||||
}
|
||||
|
||||
type values struct {
|
||||
Description string `plist:"description"`
|
||||
CurValue int `plist:"cur-value"`
|
||||
MaxValue int `plist:"max-value"`
|
||||
State string `plist:"state"`
|
||||
Type string `plist:"type"`
|
||||
}
|
||||
|
||||
type prop []values
|
||||
|
||||
type props map[string]prop
|
||||
|
||||
func readBytes(ptr unsafe.Pointer, length uint64) []byte {
|
||||
buf := make([]byte, length-1)
|
||||
var i uint64
|
||||
for ; i < length-1; i++ {
|
||||
buf[i] = *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(i)))
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
func readProps() (props, error) {
|
||||
fd, err := unix.Open("/dev/sysmon", unix.O_RDONLY, 0777)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer unix.Close(fd)
|
||||
|
||||
var retptr plistref
|
||||
|
||||
if err = ioctl(fd, 0, 'E', unsafe.Sizeof(retptr), unsafe.Pointer(&retptr)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes := readBytes(retptr.pref_plist, retptr.pref_len)
|
||||
|
||||
var props props
|
||||
if _, err = plist.Unmarshal(bytes, &props); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return props, nil
|
||||
}
|
||||
|
||||
func handleValue(val values, div float64, res *float64, amps *[]string) error {
|
||||
if val.State == "invalid" || val.State == "unknown" {
|
||||
return errors.New("Unknown value received")
|
||||
}
|
||||
|
||||
*res = float64(val.CurValue) / div
|
||||
|
||||
if amps != nil && strings.HasPrefix(val.Type, "Amp") {
|
||||
*amps = append(*amps, val.Description)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deriveState(cr1, cr2 error, current float64, max int) (AgnosticState, error) {
|
||||
if cr1 == nil && cr2 != nil {
|
||||
return Charging, nil
|
||||
}
|
||||
if cr1 != nil && cr2 == nil {
|
||||
return Discharging, nil
|
||||
}
|
||||
if cr1 != nil && cr2 != nil && current == float64(max)/1000 {
|
||||
return Full, nil
|
||||
}
|
||||
return Unknown, errors.New("Contradicting values received")
|
||||
}
|
||||
|
||||
func handleVoltage(amps []string, b *Battery, e *ErrPartial) {
|
||||
if e.DesignVoltage != nil && e.Voltage == nil {
|
||||
b.DesignVoltage, e.DesignVoltage = b.Voltage, nil
|
||||
}
|
||||
|
||||
for _, val := range amps {
|
||||
switch val {
|
||||
case "design cap":
|
||||
if e.DesignVoltage == nil {
|
||||
b.Design *= b.DesignVoltage
|
||||
} else {
|
||||
e.Design = e.DesignVoltage
|
||||
}
|
||||
case "last full cap":
|
||||
if e.Voltage == nil {
|
||||
b.Full *= b.Voltage
|
||||
} else {
|
||||
e.Full = e.Voltage
|
||||
}
|
||||
case "charge":
|
||||
if e.Voltage == nil {
|
||||
b.Current *= b.Voltage
|
||||
} else {
|
||||
e.Current = e.Voltage
|
||||
}
|
||||
case "charge rate", "discharge rate":
|
||||
if e.Voltage == nil {
|
||||
b.ChargeRate *= b.Voltage
|
||||
} else {
|
||||
e.ChargeRate = e.Voltage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sortFilterProps(props props) []string {
|
||||
var keys []string
|
||||
for key := range props {
|
||||
if key[:7] != "acpibat" {
|
||||
continue
|
||||
}
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func convertBattery(prop prop) (*Battery, error) {
|
||||
b := &Battery{}
|
||||
e := ErrPartial{}
|
||||
|
||||
amps := []string{}
|
||||
var cr1, cr2 error
|
||||
var maxCharge int
|
||||
|
||||
for _, val := range prop {
|
||||
switch val.Description {
|
||||
case "voltage":
|
||||
e.Voltage = handleValue(val, 1000000, &b.Voltage, nil)
|
||||
case "design voltage":
|
||||
e.DesignVoltage = handleValue(val, 1000000, &b.DesignVoltage, nil)
|
||||
case "design cap":
|
||||
e.Design = handleValue(val, 1000, &b.Design, &s)
|
||||
case "last full cap":
|
||||
e.Full = handleValue(val, 1000, &b.Full, &s)
|
||||
case "charge":
|
||||
e.Current = handleValue(val, 1000, &b.Current, &s)
|
||||
maxCharge = val.MaxValue
|
||||
case "charge rate":
|
||||
cr1 = handleValue(val, 1000, &b.ChargeRate, &s)
|
||||
case "discharge rate":
|
||||
cr2 = handleValue(val, 1000, &b.ChargeRate, &s)
|
||||
b.ChargeRate = math.Abs(b.ChargeRate)
|
||||
}
|
||||
}
|
||||
|
||||
b.State.Raw, e.State = deriveState(cr1, cr2, b.Current, maxCharge)
|
||||
b.State.specific = fmt.Sprintf("cr1: %v, cr2: %v")
|
||||
|
||||
handleVoltage(amps, b, &e)
|
||||
|
||||
return b, e
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
props, err := readProps()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys := sortFilterProps(props)
|
||||
if idx >= len(keys) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
return convertBattery(props[keys[idx]])
|
||||
}
|
||||
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
props, err := readProps()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keys := sortFilterProps(props)
|
||||
batteries := make([]*Battery, len(keys))
|
||||
errors := make(Errors, len(keys))
|
||||
for i, key := range keys {
|
||||
batteries[i], errors[i] = convertBattery(props[key])
|
||||
}
|
||||
|
||||
return batteries, errors
|
||||
}
|
||||
282
vendor/github.com/distatus/battery/battery_openbsd.go
generated
vendored
Normal file
282
vendor/github.com/distatus/battery/battery_openbsd.go
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2019,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func sysctl(mib []int32, out unsafe.Pointer, n uintptr) unix.Errno {
|
||||
_, _, e := unix.Syscall6(
|
||||
unix.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
uintptr(len(mib)),
|
||||
uintptr(out),
|
||||
uintptr(unsafe.Pointer(&n)),
|
||||
uintptr(unsafe.Pointer(nil)),
|
||||
0,
|
||||
)
|
||||
return e
|
||||
}
|
||||
|
||||
var errValueNotFound = fmt.Errorf("Value not found")
|
||||
|
||||
func setErr(err *error, newErr error) {
|
||||
if *err == errValueNotFound {
|
||||
*err = newErr
|
||||
}
|
||||
}
|
||||
|
||||
var sensorW = [4]int32{
|
||||
2, // SENSOR_VOLTS_DC (uV)
|
||||
5, // SENSOR_WATTS (uW)
|
||||
7, // SENSOR_WATTHOUR (uWh)
|
||||
10, // SENSOR_INTEGER
|
||||
}
|
||||
|
||||
const (
|
||||
sensorA = 6 // SENSOR_AMPS (uA)
|
||||
sensorAH = 8 // SENSOR_AMPHOUR (uAh)
|
||||
)
|
||||
|
||||
type sensorStatus int32
|
||||
|
||||
const (
|
||||
unspecified sensorStatus = iota
|
||||
ok
|
||||
warning
|
||||
critical
|
||||
unknown
|
||||
)
|
||||
|
||||
type sensor struct {
|
||||
desc [32]byte
|
||||
tv [16]byte // struct timeval
|
||||
value int64
|
||||
typ [4]byte // enum sensor_type
|
||||
status sensorStatus
|
||||
numt int32
|
||||
flags int32
|
||||
}
|
||||
|
||||
func (s *sensor) readValue(div float64) (float64, error) {
|
||||
if s.status == unknown {
|
||||
return 0, fmt.Errorf("Unknown value received")
|
||||
}
|
||||
|
||||
return float64(s.value) / div, nil
|
||||
}
|
||||
|
||||
func (s *sensor) handleA(factor float64, field *float64, fieldErr *error) {
|
||||
*field, *fieldErr = s.readValue(1000)
|
||||
if *fieldErr == nil {
|
||||
*field *= factor
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sensor) handleAH(factor float64, factorErr error, field *float64, fieldErr *error) {
|
||||
if factorErr != nil {
|
||||
*fieldErr = factorErr
|
||||
return
|
||||
}
|
||||
s.handleA(factor, field, fieldErr)
|
||||
}
|
||||
|
||||
type sensordev struct {
|
||||
num int32
|
||||
xname [16]byte
|
||||
maxnumt [23]int32
|
||||
sensors_count int32
|
||||
}
|
||||
|
||||
func (sd *sensordev) get() (*Battery, error) {
|
||||
var battery Battery
|
||||
err := ErrPartial{
|
||||
Design: errValueNotFound,
|
||||
Full: errValueNotFound,
|
||||
Current: errValueNotFound,
|
||||
ChargeRate: errValueNotFound,
|
||||
State: errValueNotFound,
|
||||
Voltage: errValueNotFound,
|
||||
DesignVoltage: errValueNotFound,
|
||||
}
|
||||
|
||||
mib := []int32{unix.CTL_HW, 11, sd.num, 0, 0}
|
||||
var s sensor
|
||||
|
||||
iter := func(maxnumtIdx int32, cb func(string)) {
|
||||
mib[3] = maxnumtIdx
|
||||
|
||||
for i := int32(0); i < sd.maxnumt[maxnumtIdx]; i++ {
|
||||
mib[4] = i
|
||||
|
||||
if errno := sysctl(mib, unsafe.Pointer(&s), unsafe.Sizeof(s)); errno != 0 {
|
||||
setErr(&err.Design, errno)
|
||||
setErr(&err.Full, errno)
|
||||
setErr(&err.Current, errno)
|
||||
setErr(&err.ChargeRate, errno)
|
||||
setErr(&err.Voltage, errno)
|
||||
setErr(&err.DesignVoltage, errno)
|
||||
setErr(&err.State, errno)
|
||||
}
|
||||
|
||||
// Convert 0-terminated C-string to a Go string
|
||||
cb(string(s.desc[:bytes.IndexByte(s.desc[:], 0)]))
|
||||
}
|
||||
}
|
||||
|
||||
for _, w := range sensorW {
|
||||
mib[3] = w
|
||||
|
||||
iter(w, func(desc string) {
|
||||
if strings.HasPrefix(desc, "battery ") {
|
||||
battery.State.specific, err.State = desc, nil
|
||||
|
||||
switch desc[8:] {
|
||||
case "unknown":
|
||||
battery.State.Raw = Unknown
|
||||
case "full":
|
||||
battery.State.Raw = Full
|
||||
case "charging":
|
||||
battery.State.Raw = Charging
|
||||
case "discharging":
|
||||
battery.State.Raw = Discharging
|
||||
case "idle":
|
||||
battery.State.Raw = Idle
|
||||
case "critical":
|
||||
battery.State.Raw = Empty
|
||||
default:
|
||||
battery.State.Raw = Undefined
|
||||
}
|
||||
return
|
||||
}
|
||||
switch desc {
|
||||
case "rate":
|
||||
battery.ChargeRate, err.ChargeRate = s.readValue(1000)
|
||||
case "design capacity":
|
||||
battery.Design, err.Design = s.readValue(1000)
|
||||
case "last full capacity":
|
||||
battery.Full, err.Full = s.readValue(1000)
|
||||
case "remaining capacity":
|
||||
battery.Current, err.Current = s.readValue(1000)
|
||||
case "current voltage":
|
||||
battery.Voltage, err.Voltage = s.readValue(1000_000)
|
||||
case "voltage":
|
||||
battery.DesignVoltage, err.DesignVoltage = s.readValue(1000_000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if err.DesignVoltage != nil && err.Voltage == nil {
|
||||
battery.DesignVoltage, err.DesignVoltage = battery.Voltage, nil
|
||||
}
|
||||
if err.ChargeRate == errValueNotFound {
|
||||
if err.Voltage == nil {
|
||||
iter(sensorA, func(desc string) {
|
||||
if desc == "rate" {
|
||||
s.handleA(battery.Voltage, &battery.ChargeRate, &err.ChargeRate)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
err.ChargeRate = err.Voltage
|
||||
}
|
||||
}
|
||||
if err.Design == errValueNotFound || err.Full == errValueNotFound || err.Current == errValueNotFound {
|
||||
iter(sensorAH, func(desc string) {
|
||||
switch desc {
|
||||
case "design capacity":
|
||||
s.handleAH(battery.DesignVoltage, err.DesignVoltage, &battery.Design, &err.Design)
|
||||
case "last full capacity":
|
||||
s.handleAH(battery.Voltage, err.Voltage, &battery.Full, &err.Full)
|
||||
case "remaining capacity":
|
||||
s.handleAH(battery.Voltage, err.Voltage, &battery.Current, &err.Current)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return &battery, err
|
||||
}
|
||||
|
||||
func getBatteryAtMIBIndex(i int32) (*Battery, int32, error) {
|
||||
mib := []int32{
|
||||
unix.CTL_HW,
|
||||
11, // HW_SENSORS
|
||||
0,
|
||||
}
|
||||
var sd sensordev
|
||||
for ; ; i++ {
|
||||
mib[2] = i
|
||||
|
||||
errno := sysctl(mib, unsafe.Pointer(&sd), unsafe.Sizeof(sd))
|
||||
if errno == unix.ENOENT {
|
||||
break
|
||||
}
|
||||
if errno != 0 {
|
||||
continue
|
||||
}
|
||||
if bytes.HasPrefix(sd.xname[:], []byte("acpibat")) {
|
||||
battery, err := sd.get()
|
||||
return battery, i + 1, err
|
||||
}
|
||||
}
|
||||
return nil, i, nil
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
var i int32
|
||||
for idxCurr := 0; ; idxCurr++ {
|
||||
battery, iNext, err := getBatteryAtMIBIndex(i)
|
||||
// If this is the index we look for, grab it.
|
||||
// Otherwise just move on, regardless of errors etc.
|
||||
if idxCurr == idx {
|
||||
return battery, err
|
||||
}
|
||||
|
||||
i = iNext
|
||||
}
|
||||
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
var batteries []*Battery
|
||||
var errors Errors
|
||||
|
||||
var i int32
|
||||
for {
|
||||
battery, iNext, err := getBatteryAtMIBIndex(i)
|
||||
if battery == nil && err == nil { // no more batteries
|
||||
break
|
||||
}
|
||||
batteries = append(batteries, battery)
|
||||
errors = append(errors, err)
|
||||
|
||||
i = iNext
|
||||
}
|
||||
|
||||
return batteries, errors
|
||||
}
|
||||
260
vendor/github.com/distatus/battery/battery_solaris.go
generated
vendored
Normal file
260
vendor/github.com/distatus/battery/battery_solaris.go
generated
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var errValueNotFound = fmt.Errorf("Value not found")
|
||||
|
||||
func readFloat(val string) (float64, error) {
|
||||
num, err := strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if num == math.MaxUint32 {
|
||||
return 0, fmt.Errorf("Unknown value received")
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
func readVoltage(val string) (float64, error) {
|
||||
voltage, err := readFloat(val)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return voltage / 1000, nil
|
||||
}
|
||||
|
||||
func readState(val string) (AgnosticState, error) {
|
||||
state, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return Unknown, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case state&1 != 0:
|
||||
return Discharging, nil
|
||||
case state&2 != 0:
|
||||
return Charging, nil
|
||||
case state&4 != 0:
|
||||
return Empty, nil
|
||||
default:
|
||||
return Undefined, nil
|
||||
}
|
||||
}
|
||||
|
||||
type errParse int
|
||||
|
||||
func (p errParse) Error() string {
|
||||
return fmt.Sprintf("Parse error: `%d`", p)
|
||||
}
|
||||
|
||||
type batteryReader struct {
|
||||
cmdout *bufio.Scanner
|
||||
li int
|
||||
lline []byte
|
||||
e ErrPartial
|
||||
}
|
||||
|
||||
func (r *batteryReader) setErrParse(n int) {
|
||||
if r.e.Design == errValueNotFound {
|
||||
r.e.Design = errParse(n)
|
||||
}
|
||||
if r.e.Full == errValueNotFound {
|
||||
r.e.Full = errParse(n)
|
||||
}
|
||||
if r.e.Current == errValueNotFound {
|
||||
r.e.Current = errParse(n)
|
||||
}
|
||||
if r.e.ChargeRate == errValueNotFound {
|
||||
r.e.ChargeRate = errParse(n)
|
||||
}
|
||||
if r.e.State == errValueNotFound {
|
||||
r.e.State = errParse(n)
|
||||
}
|
||||
if r.e.Voltage == errValueNotFound {
|
||||
r.e.Voltage = errParse(n)
|
||||
}
|
||||
if r.e.DesignVoltage == errValueNotFound {
|
||||
r.e.DesignVoltage = errParse(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *batteryReader) readValue() (string, string, int) {
|
||||
var piece []byte
|
||||
if r.lline != nil {
|
||||
piece = r.lline
|
||||
r.lline = nil
|
||||
} else {
|
||||
pieces := bytes.Split(r.cmdout.Bytes(), []byte{':'})
|
||||
if len(pieces) < 4 {
|
||||
return "", "", 4
|
||||
}
|
||||
|
||||
i, err := strconv.Atoi(string(pieces[1]))
|
||||
if err != nil {
|
||||
return "", "", 1
|
||||
}
|
||||
|
||||
if i != r.li {
|
||||
r.li = i
|
||||
r.lline = pieces[3]
|
||||
return "", "", 666
|
||||
}
|
||||
|
||||
piece = pieces[3]
|
||||
}
|
||||
|
||||
values := bytes.Split(piece, []byte{'\t'})
|
||||
if len(values) < 2 {
|
||||
return "", "", 2
|
||||
}
|
||||
return string(values[0]), string(values[1]), 0
|
||||
}
|
||||
|
||||
func (r *batteryReader) readBattery() (*Battery, bool, bool) {
|
||||
b := &Battery{}
|
||||
var exists, amps bool
|
||||
|
||||
for r.cmdout.Scan() {
|
||||
exists = true
|
||||
|
||||
name, value, errno := r.readValue()
|
||||
if errno == 666 {
|
||||
break
|
||||
}
|
||||
if errno != 0 {
|
||||
r.setErrParse(errno)
|
||||
continue
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "bif_design_cap":
|
||||
b.Design, r.e.Design = readFloat(value)
|
||||
case "bif_last_cap":
|
||||
b.Full, r.e.Full = readFloat(value)
|
||||
case "bif_unit":
|
||||
amps = value != "0"
|
||||
case "bif_voltage":
|
||||
b.DesignVoltage, r.e.DesignVoltage = readVoltage(value)
|
||||
case "bst_voltage":
|
||||
b.Voltage, r.e.Voltage = readVoltage(value)
|
||||
case "bst_rem_cap":
|
||||
b.Current, r.e.Current = readFloat(value)
|
||||
case "bst_rate":
|
||||
b.ChargeRate, r.e.ChargeRate = readFloat(value)
|
||||
case "bst_state":
|
||||
b.State.Raw, r.e.State = readState(value)
|
||||
b.State.specific = value
|
||||
}
|
||||
}
|
||||
|
||||
return b, amps, exists
|
||||
}
|
||||
|
||||
func (r *batteryReader) next() (*Battery, error) {
|
||||
r.e = ErrPartial{
|
||||
Design: errValueNotFound,
|
||||
Full: errValueNotFound,
|
||||
Current: errValueNotFound,
|
||||
ChargeRate: errValueNotFound,
|
||||
State: errValueNotFound,
|
||||
Voltage: errValueNotFound,
|
||||
DesignVoltage: errValueNotFound,
|
||||
}
|
||||
|
||||
b, amps, exists := r.readBattery()
|
||||
|
||||
if !exists {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
if r.e.DesignVoltage != nil && r.e.Voltage == nil {
|
||||
b.DesignVoltage, r.e.DesignVoltage = b.Voltage, nil
|
||||
}
|
||||
|
||||
if amps {
|
||||
if r.e.DesignVoltage == nil {
|
||||
b.Design *= b.DesignVoltage
|
||||
} else {
|
||||
r.e.Design = r.e.DesignVoltage
|
||||
}
|
||||
if r.e.Voltage == nil {
|
||||
b.Full *= b.Voltage
|
||||
b.Current *= b.Voltage
|
||||
b.ChargeRate *= b.Voltage
|
||||
} else {
|
||||
r.e.Full = r.e.Voltage
|
||||
r.e.Current = r.e.Voltage
|
||||
r.e.ChargeRate = r.e.Voltage
|
||||
}
|
||||
}
|
||||
|
||||
if b.State.Raw == Unknown && r.e.Current == nil && r.e.Full == nil && b.Current >= b.Full {
|
||||
b.State.Raw = Full
|
||||
b.State.specific = fmt.Sprintf("current >= full")
|
||||
}
|
||||
|
||||
return b, r.e
|
||||
}
|
||||
|
||||
func newBatteryReader() (*batteryReader, error) {
|
||||
out, err := exec.Command("kstat", "-p", "-m", "acpi_drv", "-n", "battery B*").Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &batteryReader{cmdout: bufio.NewScanner(bytes.NewReader(out))}, nil
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
br, err := newBatteryReader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return br.next()
|
||||
}
|
||||
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
br, err := newBatteryReader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var batteries []*Battery
|
||||
var errors Errors
|
||||
for b, e := br.next(); e != io.EOF; b, e = br.next() {
|
||||
batteries = append(batteries, b)
|
||||
errors = append(errors, e)
|
||||
}
|
||||
|
||||
return batteries, errors
|
||||
}
|
||||
320
vendor/github.com/distatus/battery/battery_windows.go
generated
vendored
Normal file
320
vendor/github.com/distatus/battery/battery_windows.go
generated
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type batteryQueryInformation struct {
|
||||
BatteryTag uint32
|
||||
InformationLevel int32
|
||||
AtRate int32
|
||||
}
|
||||
|
||||
type batteryInformation struct {
|
||||
Capabilities uint32
|
||||
Technology uint8
|
||||
Reserved [3]uint8
|
||||
Chemistry [4]uint8
|
||||
DesignedCapacity uint32
|
||||
FullChargedCapacity uint32
|
||||
DefaultAlert1 uint32
|
||||
DefaultAlert2 uint32
|
||||
CriticalBias uint32
|
||||
CycleCount uint32
|
||||
}
|
||||
|
||||
type batteryWaitStatus struct {
|
||||
BatteryTag uint32
|
||||
Timeout uint32
|
||||
PowerState uint32
|
||||
LowCapacity uint32
|
||||
HighCapacity uint32
|
||||
}
|
||||
|
||||
type batteryStatus struct {
|
||||
PowerState uint32
|
||||
Capacity uint32
|
||||
Voltage uint32
|
||||
Rate int32
|
||||
}
|
||||
|
||||
type guid struct {
|
||||
Data1 uint32
|
||||
Data2 uint16
|
||||
Data3 uint16
|
||||
Data4 [8]byte
|
||||
}
|
||||
|
||||
type spDeviceInterfaceData struct {
|
||||
cbSize uint32
|
||||
InterfaceClassGuid guid
|
||||
Flags uint32
|
||||
Reserved uint
|
||||
}
|
||||
|
||||
var guidDeviceBattery = guid{
|
||||
0x72631e54,
|
||||
0x78A4,
|
||||
0x11d0,
|
||||
[8]byte{0xbc, 0xf7, 0x00, 0xaa, 0x00, 0xb7, 0xb3, 0x2a},
|
||||
}
|
||||
|
||||
func int32ToFloat64(num int32) (float64, error) {
|
||||
// There is something wrong with this constant, but
|
||||
// it appears to work so far...
|
||||
if num == -0x80000000 { // BATTERY_UNKNOWN_RATE
|
||||
return 0, errors.New("Unknown value received")
|
||||
}
|
||||
return math.Abs(float64(num)), nil
|
||||
}
|
||||
|
||||
func uint32ToFloat64(num uint32) (float64, error) {
|
||||
if num == 0xffffffff { // BATTERY_UNKNOWN_CAPACITY
|
||||
return 0, errors.New("Unknown value received")
|
||||
}
|
||||
return float64(num), nil
|
||||
}
|
||||
|
||||
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)
|
||||
if windows.Handle(r1) == windows.InvalidHandle {
|
||||
if errno != 0 {
|
||||
return 0, error(errno)
|
||||
}
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
return r1, nil
|
||||
}
|
||||
|
||||
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)
|
||||
if r1 == 0 {
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return syscall.EINVAL
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var setupapi = &windows.LazyDLL{Name: "setupapi.dll", System: true}
|
||||
var setupDiGetClassDevsW = setupapi.NewProc("SetupDiGetClassDevsW")
|
||||
var setupDiEnumDeviceInterfaces = setupapi.NewProc("SetupDiEnumDeviceInterfaces")
|
||||
var setupDiGetDeviceInterfaceDetailW = setupapi.NewProc("SetupDiGetDeviceInterfaceDetailW")
|
||||
var setupDiDestroyDeviceInfoList = setupapi.NewProc("SetupDiDestroyDeviceInfoList")
|
||||
|
||||
func readState(powerState uint32) AgnosticState {
|
||||
switch {
|
||||
case powerState&0x00000004 != 0:
|
||||
return Charging
|
||||
case powerState&0x00000008 != 0:
|
||||
return Empty
|
||||
case powerState&0x00000002 != 0:
|
||||
return Discharging
|
||||
case powerState&0x00000001 != 0:
|
||||
return Full
|
||||
default:
|
||||
return Undefined
|
||||
}
|
||||
}
|
||||
|
||||
func systemGet(idx int) (*Battery, error) {
|
||||
hdev, err := setupDiSetup(
|
||||
setupDiGetClassDevsW,
|
||||
4,
|
||||
uintptr(unsafe.Pointer(&guidDeviceBattery)),
|
||||
0,
|
||||
0,
|
||||
2|16, // DIGCF_PRESENT|DIGCF_DEVICEINTERFACE
|
||||
0, 0,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.Syscall(setupDiDestroyDeviceInfoList.Addr(), 1, hdev, 0, 0)
|
||||
|
||||
var did spDeviceInterfaceData
|
||||
did.cbSize = uint32(unsafe.Sizeof(did))
|
||||
errno := setupDiCall(
|
||||
setupDiEnumDeviceInterfaces,
|
||||
5,
|
||||
hdev,
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&guidDeviceBattery)),
|
||||
uintptr(idx),
|
||||
uintptr(unsafe.Pointer(&did)),
|
||||
0,
|
||||
)
|
||||
if errno == 259 { // ERROR_NO_MORE_ITEMS
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
var cbRequired uint32
|
||||
errno = setupDiCall(
|
||||
setupDiGetDeviceInterfaceDetailW,
|
||||
6,
|
||||
hdev,
|
||||
uintptr(unsafe.Pointer(&did)),
|
||||
0,
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&cbRequired)),
|
||||
0,
|
||||
)
|
||||
if errno != 0 && errno != 122 { // ERROR_INSUFFICIENT_BUFFER
|
||||
return nil, errno
|
||||
}
|
||||
// The god damn struct with ANYSIZE_ARRAY of utf16 in it is crazy.
|
||||
// So... let's emulate it with array of uint16 ;-D.
|
||||
// Keep in mind that the first two elements are actually cbSize.
|
||||
didd := make([]uint16, cbRequired/2)
|
||||
cbSize := (*uint32)(unsafe.Pointer(&didd[0]))
|
||||
if unsafe.Sizeof(uint(0)) == 8 {
|
||||
*cbSize = 8
|
||||
} else {
|
||||
*cbSize = 6
|
||||
}
|
||||
errno = setupDiCall(
|
||||
setupDiGetDeviceInterfaceDetailW,
|
||||
6,
|
||||
hdev,
|
||||
uintptr(unsafe.Pointer(&did)),
|
||||
uintptr(unsafe.Pointer(&didd[0])),
|
||||
uintptr(cbRequired),
|
||||
uintptr(unsafe.Pointer(&cbRequired)),
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
devicePath := &didd[2:][0]
|
||||
|
||||
handle, err := windows.CreateFile(
|
||||
devicePath,
|
||||
windows.GENERIC_READ|windows.GENERIC_WRITE,
|
||||
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE,
|
||||
nil,
|
||||
windows.OPEN_EXISTING,
|
||||
windows.FILE_ATTRIBUTE_NORMAL,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer windows.CloseHandle(handle)
|
||||
|
||||
var dwOut uint32
|
||||
|
||||
var dwWait uint32
|
||||
var bqi batteryQueryInformation
|
||||
err = windows.DeviceIoControl(
|
||||
handle,
|
||||
2703424, // IOCTL_BATTERY_QUERY_TAG
|
||||
(*byte)(unsafe.Pointer(&dwWait)),
|
||||
uint32(unsafe.Sizeof(dwWait)),
|
||||
(*byte)(unsafe.Pointer(&bqi.BatteryTag)),
|
||||
uint32(unsafe.Sizeof(bqi.BatteryTag)),
|
||||
&dwOut,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bqi.BatteryTag == 0 {
|
||||
return nil, errors.New("BatteryTag not returned")
|
||||
}
|
||||
|
||||
b := &Battery{}
|
||||
e := ErrPartial{}
|
||||
|
||||
var bi batteryInformation
|
||||
err = windows.DeviceIoControl(
|
||||
handle,
|
||||
2703428, // IOCTL_BATTERY_QUERY_INFORMATION
|
||||
(*byte)(unsafe.Pointer(&bqi)),
|
||||
uint32(unsafe.Sizeof(bqi)),
|
||||
(*byte)(unsafe.Pointer(&bi)),
|
||||
uint32(unsafe.Sizeof(bi)),
|
||||
&dwOut,
|
||||
nil,
|
||||
)
|
||||
if err == nil {
|
||||
b.Full = float64(bi.FullChargedCapacity)
|
||||
b.Design = float64(bi.DesignedCapacity)
|
||||
} else {
|
||||
e.Full = err
|
||||
e.Design = err
|
||||
}
|
||||
|
||||
bws := batteryWaitStatus{BatteryTag: bqi.BatteryTag}
|
||||
var bs batteryStatus
|
||||
err = windows.DeviceIoControl(
|
||||
handle,
|
||||
2703436, // IOCTL_BATTERY_QUERY_STATUS
|
||||
(*byte)(unsafe.Pointer(&bws)),
|
||||
uint32(unsafe.Sizeof(bws)),
|
||||
(*byte)(unsafe.Pointer(&bs)),
|
||||
uint32(unsafe.Sizeof(bs)),
|
||||
&dwOut,
|
||||
nil,
|
||||
)
|
||||
if err == nil {
|
||||
b.Current, e.Current = uint32ToFloat64(bs.Capacity)
|
||||
b.ChargeRate, e.ChargeRate = int32ToFloat64(bs.Rate)
|
||||
b.Voltage, e.Voltage = uint32ToFloat64(bs.Voltage)
|
||||
b.Voltage /= 1000
|
||||
b.State.Raw = readState(bs.PowerState)
|
||||
b.State.specific = fmt.Sprintf("%x", bs.PowerState)
|
||||
} else {
|
||||
e.Current = err
|
||||
e.ChargeRate = err
|
||||
e.Voltage = err
|
||||
e.State = err
|
||||
}
|
||||
|
||||
b.DesignVoltage, e.DesignVoltage = b.Voltage, e.Voltage
|
||||
|
||||
return b, e
|
||||
}
|
||||
|
||||
func systemGetAll() ([]*Battery, error) {
|
||||
var batteries []*Battery
|
||||
var errors Errors
|
||||
for i := 0; ; i++ {
|
||||
b, err := systemGet(i)
|
||||
if err == ErrNotFound {
|
||||
break
|
||||
}
|
||||
batteries = append(batteries, b)
|
||||
errors = append(errors, err)
|
||||
}
|
||||
return batteries, errors
|
||||
}
|
||||
147
vendor/github.com/distatus/battery/errors.go
generated
vendored
Normal file
147
vendor/github.com/distatus/battery/errors.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// battery
|
||||
// Copyright (C) 2016-2017 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package battery
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ErrNotFound variable represents battery not found error.
|
||||
//
|
||||
// Only ever returned wrapped in ErrFatal.
|
||||
var ErrNotFound = fmt.Errorf("Not found")
|
||||
|
||||
// ErrAllNotNil variable says that backend returned ErrPartial with
|
||||
// all fields having not nil values, hence it was converted to ErrFatal.
|
||||
//
|
||||
// Only ever returned wrapped in ErrFatal.
|
||||
var ErrAllNotNil = fmt.Errorf("All fields had not nil errors")
|
||||
|
||||
// ErrFatal type represents a fatal error.
|
||||
//
|
||||
// It indicates that either the library was not able to perform some kind
|
||||
// of operation critical to retrieving any data, or all partials have failed at
|
||||
// once (which would be equivalent to returning a ErrPartial with no nils).
|
||||
//
|
||||
// As such, the caller should assume that no meaningful data was
|
||||
// returned alongside the error and act accordingly.
|
||||
type ErrFatal struct {
|
||||
Err error // The actual error that happened.
|
||||
}
|
||||
|
||||
func (f ErrFatal) Error() string {
|
||||
return fmt.Sprintf("Could not retrieve battery info: `%s`", f.Err)
|
||||
}
|
||||
|
||||
// ErrPartial type represents a partial error.
|
||||
//
|
||||
// It indicates that there were problems retrieving some of the data,
|
||||
// but some was also retrieved successfully.
|
||||
// If there would be all nils, nil is returned instead.
|
||||
// If there would be all not nils, ErrFatal is returned instead.
|
||||
//
|
||||
// The fields represent fields in the Battery type.
|
||||
type ErrPartial struct {
|
||||
State error
|
||||
Current error
|
||||
Full error
|
||||
Design error
|
||||
ChargeRate error
|
||||
Voltage error
|
||||
DesignVoltage error
|
||||
}
|
||||
|
||||
func (p ErrPartial) Error() string {
|
||||
if p.isNil() {
|
||||
return "{}"
|
||||
}
|
||||
errors := map[string]error{
|
||||
"State": p.State,
|
||||
"Current": p.Current,
|
||||
"Full": p.Full,
|
||||
"Design": p.Design,
|
||||
"ChargeRate": p.ChargeRate,
|
||||
"Voltage": p.Voltage,
|
||||
"DesignVoltage": p.DesignVoltage,
|
||||
}
|
||||
keys := []string{"State", "Current", "Full", "Design", "ChargeRate", "Voltage", "DesignVoltage"}
|
||||
s := "{"
|
||||
for _, name := range keys {
|
||||
err := errors[name]
|
||||
if err != nil {
|
||||
s += fmt.Sprintf("%s:%s ", name, err.Error())
|
||||
}
|
||||
}
|
||||
return s[:len(s)-1] + "}"
|
||||
}
|
||||
|
||||
func (p ErrPartial) isNil() bool {
|
||||
return p.State == nil &&
|
||||
p.Current == nil &&
|
||||
p.Full == nil &&
|
||||
p.Design == nil &&
|
||||
p.ChargeRate == nil &&
|
||||
p.Voltage == nil &&
|
||||
p.DesignVoltage == nil
|
||||
}
|
||||
|
||||
func (p ErrPartial) noNil() bool {
|
||||
return p.State != nil &&
|
||||
p.Current != nil &&
|
||||
p.Full != nil &&
|
||||
p.Design != nil &&
|
||||
p.ChargeRate != nil &&
|
||||
p.Voltage != nil &&
|
||||
p.DesignVoltage != nil
|
||||
}
|
||||
|
||||
// Errors type represents an array of ErrFatal, ErrPartial or nil values.
|
||||
//
|
||||
// Can only possibly be returned by GetAll() call.
|
||||
type Errors []error
|
||||
|
||||
func (e Errors) Error() string {
|
||||
s := "["
|
||||
for _, err := range e {
|
||||
if err != nil {
|
||||
s += err.Error() + " "
|
||||
}
|
||||
}
|
||||
if len(s) > 1 {
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
return s + "]"
|
||||
}
|
||||
|
||||
func wrapError(err error) error {
|
||||
if perr, ok := err.(ErrPartial); ok {
|
||||
if perr.isNil() {
|
||||
return nil
|
||||
}
|
||||
if perr.noNil() {
|
||||
return ErrFatal{ErrAllNotNil}
|
||||
}
|
||||
return perr
|
||||
}
|
||||
if err != nil {
|
||||
return ErrFatal{err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
48
vendor/github.com/distatus/battery/ioctl.go
generated
vendored
Normal file
48
vendor/github.com/distatus/battery/ioctl.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// battery
|
||||
// Copyright (C) 2016,2023 Karol 'Kenji Takahashi' Woźniak
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
//go:build freebsd || dragonfly || netbsd
|
||||
|
||||
package battery
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func ioctl(fd int, nr int64, typ byte, size uintptr, retptr unsafe.Pointer) error {
|
||||
_, _, errno := unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(fd),
|
||||
// Some magicks derived from sys/ioccom.h.
|
||||
uintptr((0x40000000|0x80000000)|
|
||||
((int64(size)&(1<<13-1))<<16)|
|
||||
(int64(typ)<<8)|
|
||||
nr,
|
||||
),
|
||||
uintptr(retptr),
|
||||
)
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user