-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathups.py
executable file
·122 lines (104 loc) · 3.64 KB
/
ups.py
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
#!/usr/bin/python3 -u
"""
Description: CyberPower UPS waybar module. Inspired by
https://github.com/bjonnh/cyberpower-usb-watcher
Author: thnikk
"""
import json
import argparse
import sys
import os
import hid
from common import Cache
import tooltip as tt
def parse_args():
""" Parse arguments """
parser = argparse.ArgumentParser(description="CyberPower UPS module")
parser.add_argument('vendor', action='store', type=str, help='Vendor ID')
parser.add_argument('product', action='store', type=str, help='Product ID')
parser.add_argument(
'-o', '--offset', type=int, default=0, help='Wattage offset')
return parser.parse_args()
class CyberPower:
""" Class for CyberPower UPS """
def __init__(self, vendor, product, offset) -> None:
self.device = hid.Device(
path=hid.enumerate(vendor, product)[0]['path'])
self.offset = offset
self.status_report = self.device.get_feature_report(0x0b, 3)[1]
def load_watts(self) -> int:
""" Get load """
return round(self.capacity() * (self.load_percent()/100) / 10) * 10
def offset_watts(self) -> int:
""" Get offset watts """
return self.load_watts() - self.offset
def load_percent(self) -> int:
""" Get load percentage """
return self.device.get_feature_report(0x13, 2)[1]
def capacity(self) -> int:
""" Get capacity in watts """
report = self.device.get_feature_report(0x18, 6)
return report[2] * 256 + report[1]
def runtime(self) -> int:
""" Battery runtime """
report = self.device.get_feature_report(0x08, 6)
return int((report[3]*256+report[2])/60)
def battery_percent(self) -> int:
""" Battery percentage """
return self.device.get_feature_report(0x08, 6)[1]
def ac(self) -> bool:
""" AC status """
return bool(self.status_report & 1)
def charging(self) -> bool:
""" Charging status """
return bool(self.status_report & 2)
def full(self) -> bool:
""" Full status """
return bool((self.status_report & 16) > 0)
def close(self) -> None:
""" Close device """
self.device.close()
def main():
""" Main function """
args = parse_args()
cache = Cache(os.path.expanduser("~/.cache/ups.json"))
try:
try:
ups = CyberPower(
int(args.vendor, 16),
int(args.product, 16),
args.offset
)
except IndexError:
sys.exit(1)
output = {
"text": f" {ups.offset_watts()}W",
"tooltip": "\n".join([
tt.heading('UPS stats'),
f"Runtime: {ups.runtime()} minutes",
f"Load: {ups.load_watts()} Watts ({ups.load_percent()}%)",
f"Battery: {ups.battery_percent()}%",
f"AC power: {ups.ac()}",
f"Charging: {ups.charging()}",
f"Battery full: {ups.full()}",
]),
"widget": {
"load_offset": ups.offset_watts(),
"runtime": ups.runtime(),
"load_watts": ups.load_watts(),
"load_percent": ups.load_percent(),
"battery": ups.battery_percent(),
"ac_power": ups.ac(),
"charging": ups.charging(),
"battery_full": ups.full()
}
}
if not ups.ac():
output['class'] = 'red'
print(json.dumps(output))
cache.save(json.dumps(output))
ups.close()
except hid.HIDException:
print(json.dumps(cache.load()))
if __name__ == "__main__":
main()