-
Notifications
You must be signed in to change notification settings - Fork 0
/
power.go
124 lines (105 loc) · 3.13 KB
/
power.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main
import (
"fmt"
"io"
"time"
dbus "github.com/guelfey/go.dbus"
)
const (
// Unknown = PowerState(0)
Charging = PowerState(1)
// Discharging = PowerState(2)
// Empty = PowerState(3)
FullyCharged = PowerState(4)
)
type PowerState uint32
func (ps PowerState) String() string {
switch ps {
case 1:
return "Charging"
case 2:
return "Discharging"
case 3:
return "Empty"
case 4:
return "Fully Charged"
default:
return "Unknown"
}
}
type BatteryStatus struct {
// Capacity is the percentage of how full the battery is
Capacity float64
// Usage is the power usage in watts. Negative indicates charging, positive indicates discharging
Usage float64
// TimeUntilFull is how long until the battery is full. 0 when fully charged or discharging
TimeUntilFull time.Duration
// TimeUntilEmpty is how long until the battery is empty. 0 when charging o
TimeUntilEmpty time.Duration
// State is the status of the battery
State PowerState
// IsCharging is if the State of the battery == Charging
IsCharging bool
}
type PowerClient interface {
io.Closer
GetBatteryStatus() (BatteryStatus, error)
}
type powerDBusInterface struct {
Conn *dbus.Conn
BatObj *dbus.Object
}
func NewPowerClient() (PowerClient, error) {
conn, err := dbus.SystemBus()
if err != nil {
return nil, fmt.Errorf("Failed to connect to session bus: %w", err)
}
batteryObj := conn.Object("org.freedesktop.UPower", "/org/freedesktop/UPower/devices/battery_BAT0")
return &powerDBusInterface{
Conn: conn,
BatObj: batteryObj,
}, nil
}
func (pdi *powerDBusInterface) GetBatteryStatus() (BatteryStatus, error) {
var bs BatteryStatus
stateProp, err := pdi.BatObj.GetProperty("org.freedesktop.UPower.Device.State")
if err != nil {
return bs, fmt.Errorf("could not get online property: %w", err)
}
if value, ok := stateProp.Value().(uint32); ok {
bs.State = PowerState(value)
bs.IsCharging = PowerState(value) == Charging || PowerState(value) == FullyCharged
}
timeToFullProp, err := pdi.BatObj.GetProperty("org.freedesktop.UPower.Device.TimeToFull")
if err != nil {
return bs, fmt.Errorf("could not get time to full property: %w", err)
}
if value, ok := timeToFullProp.Value().(int64); ok {
bs.TimeUntilFull = time.Duration(value) * time.Second
}
timeToEmptyProp, err := pdi.BatObj.GetProperty("org.freedesktop.UPower.Device.TimeToEmpty")
if err != nil {
return bs, fmt.Errorf("could not get time to empty property: %w", err)
}
if value, ok := timeToEmptyProp.Value().(int64); ok {
bs.TimeUntilEmpty = time.Duration(value) * time.Second
}
energyRateProp, err := pdi.BatObj.GetProperty("org.freedesktop.UPower.Device.EnergyRate")
if err != nil {
return bs, fmt.Errorf("could not get energy rate property: %w", err)
}
if value, ok := energyRateProp.Value().(float64); ok {
bs.Usage = value
}
pctProp, err := pdi.BatObj.GetProperty("org.freedesktop.UPower.Device.Percentage")
if err != nil {
return bs, fmt.Errorf("could not get percentage property: %w", err)
}
if value, ok := pctProp.Value().(float64); ok {
bs.Capacity = value
}
return bs, nil
}
func (pdi *powerDBusInterface) Close() error {
return pdi.Conn.Close()
}