-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbat_mon
executable file
·178 lines (163 loc) · 6.56 KB
/
bat_mon
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/python3
#-*- coding:utf-8 -*-
#import modules
import os #hostname
import time #timers for sleep
import struct # Capture battary capacity
import smbus #both waveshare and UPS-LITE
import syslog
import stat
#import signal # Check for incomming signals from the service and react if there is term signal.
#Declare Variables:
sleep_time = 60
min_bat_cap=2 # setting in percent minimum battery capacity before we'll shutdown.
bus=1
i2c_bus=smbus.SMBus(bus)
bat_cap = min_bat_cap+1 #Define the initial battery capacity.
tmp_dir = "/tmp/"
bat_file = "bat"
shut_file = "shut"
#Setup logging: Work in progress
syslog.openlog(ident="battery_monitor",logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL7)
syslog.syslog(syslog.LOG_INFO, 'bat_mon was started')
#Begin Function defenition:
######################################################################################################
#Capture the bus for ups board, both ups_lite, and pisugar2.
def init_ups_check(i2c_bus, bus):
is_not_ups_lite = False
is_not_pisugar = False
try:
smbus.SMBus(bus) # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)
#Test to see which UPS solution is inatalled, if any:
try:
address = 0x75 # pisugar 2's battery is on 0x75
low = i2c_bus.read_byte_data(address, 0xa2)
except:
is_not_pisugar = True
try:
address = 0x36 # ups_lite's address is on 0x36
read_vol = i2c_bus.read_word_data(address, 0x02)
read_cap = i2c_bus.read_word_data(address, 0x04)
except:
is_not_ups_lite = True
if is_not_ups_lite is True and is_not_pisugar is True:
ups_type = 'none'
address = 'error'
elif is_not_ups_lite is True and is_not_pisugar is False:
ups_type = 'pisugar2'
address = 0x75 #making sure the correct address is set.
elif is_not_ups_lite is False and is_not_pisugar is True:
ups_type = 'ups_lite'
address = 0x36 #Making sure the correct address is set.
syslog.syslog(syslog.LOG_INFO, 'Found and selected the '+ups_type+' UPS option.')
except:
bus="error"
syslog.syslog(syslog.LOG_INFO, 'Did not find a UPS option.')
return ups_type, address
def read_bat_capacity(ups_type, address, bus):
# "This function returns as a float the remaining capacity of the battery
# connected to the Raspi UPS Hat via the pro$
battery_curve = [
[4.16, 5.5, 100, 100],
[4.05, 4.16, 87.5, 100],
[4.00, 4.05, 75, 87.5],
[3.92, 4.00, 62.5, 75],
[3.86, 3.92, 50, 62.5],
[3.79, 3.86, 37.5, 50],
[3.66, 3.79, 25, 37.5],
[3.52, 3.66, 12.5, 25],
[3.49, 3.52, 6.2, 12.5],
[3.1, 3.49, 0, 6.2],
[0, 3.1, 0, 0],
]
battery_level = 0
charge = False
if ups_type == 'ups_lite':
charge = False
try:
#Read Voltage from UPS:
read_vol = i2c_bus.read_word_data(address, 0x02)
swapped = struct.unpack("<H", struct.pack(">H", read_vol))[0]
voltage = swapped * 1.25 /1000/16
#Read capacity from UPS to get voltage:
read_cap = i2c_bus.read_word_data(address, 0x04)
swapped = struct.unpack("<H", struct.pack(">H", read_cap))[0]
battery_level = swapped/256
except:
battery_level = 200.00
elif ups_type == 'pisugar2':
try:
low = bus.read_byte_data(address, 0xa2)
high = bus.read_byte_data(address, 0xa3)
if high & 0x20:
low = ~low & 0xff
high = ~high & 0x1f
v = (((high | 0b1100_0000) << 8) + low)
voltage = (2600.0 - v * 0.26855) / 1000
else:
v = ((high & 0x1f) << 8 ) + low
voltage = (2600 + v * 0.26855) / 1000
except:
battery_v = 0.0
for range in battery_curve:
if range[0] < voltage <= range[1]:
level_base = ((voltage - range[0]) / (range[1] - range[0])) * (range[3] - range[2])
battery_level = level_base + range[2]
else:
battery_level = 999
charge = False
error=True
voltage = 999
return [int(battery_level), voltage, charge]
#End of Function defenition:
######################################################################################################
#determine UPS type, bus number, and if its charging or not:
ups, address = init_ups_check(i2c_bus, bus)
#Check if battery file exists, create if it does not:
if not os.path.exists(tmp_dir+bat_file):
os.mknod(tmp_dir+bat_file)
try:
os.chmod(tmp_dir+bat_file, 0o664)
while (bat_cap > min_bat_cap or charge is True):
bat_cap, volts, charge = read_bat_capacity(ups, address, i2c_bus) #Formatted battery level
bat_lvl=str(bat_cap)+"%"
b_file = open(tmp_dir+bat_file,'w')
b_file.write(str(bat_lvl))
b_file.close()
if int(bat_cap) >=30 and int(bat_cap) <=100:
sleep_time = 60
elif int(bat_cap) >=15 and int(bat_cap) <=29:
sleep_time = 30
elif int(bat_cap) >=8 and int(bat_cap) <=14:
sleep_time = 15
elif int(bat_cap) >=0 and int(bat_cap) <=7:
sleep_time = 10
print(int(sleep_time))
print(str(bat_cap))
time.sleep(sleep_time)
#if the bat_cap is less that min_bat_cap, then bail out of the loop, and follow the remaining code to shutdown.
syslog.syslog(syslog.LOG_INFO, 'Shutting down - battary has reached critical level')
syslog.syslog(syslog.LOG_INFO, 'Battary is: '+bat_lvl+'Uptime was: '+str(os.system("uptime -p")))
s_file = open(tmp_dir+shut_file,'w')
s_file.write(str("p"))
s_file.close()
b_file.close()
os.system('wall -n "Shutdown by way of low battery!"')
os.system("poweroff -p")
exit(0)
except KeyboardInterrupt:
syslog.syslog(syslog.LOG_INFO, 'Quit (SIGINT) Due to Keyboard interrupt when not being run as a service')
s_file = open(tmp_dir+shut_file,'w')
s_file.write(str("e"))
s_file.close()
b_file.close()
exit(1)
except SystemExit:
syslog.syslog(syslog.LOG_INFO, 'Quit (SIGTERM) from service telling us to terminate')
syslog.syslog(syslog.LOG_INFO, 'Shutting Down/Restarting bat_mon - interupted by service stop, from command, shutdown, or reboot')
b_file.close()
exit(0)
except IOError as e:
syslog.syslog(syslog.LOG_ERR, 'Shutting Down bat_mon - traceback.format_exc():\n%s' ,traceback.format_exc())
bat_file.close()
exit(1)