~speguero/systemd-autohibernated

ref: e5a81842aa2816548ef21210b7ac44db8fab768e systemd-autohibernated/systemd-autohibernated -rwxr-xr-x 4.2 KiB
e5a81842 — Steven Peguero Change README to Markdown, add install step 1 year, 2 days ago
                                                                                
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
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/env python3

'''
SYSTEMD-AUTOHIBERNATED
----------------------

Hibernates a machine when AC power is nonexistent and available battery
power is scarcely low.

Surprisingly, systemd does not provide a crucial feature to perform what
this custom script accomplishes, like `apmd -Z 5` in OpenBSD.

'''

def main(batt_percent_to_hibernate):
	import platform
	import subprocess
	import time

	os               = platform.system().lower()
	daemon_start_msg = 'This machine will hibernate when discharged to %s%% battery life availability. Waiting for such conditions...' % batt_percent_to_hibernate
	hibernation_msg  = 'This machine will now hibernate!'

	print(daemon_start_msg)

	while True:

		ac_stat      = None
		batt_percent = None
		batt_stat    = None

		time.sleep(1)

		try:
			block_style = process_args(block_style)
		except:
			block_style = 0

		try:
			ac_stat = get_ac_stat()
		except:
			print('> error: Could not determine status of AC (wired) power.')

		try:
			batt_stat = get_batt_stat()
		except:
			print('> error: Could not detect batteries.')

		try:
			batt_percent = get_batt_percent()
		except:
			print('> error: Could not determine available battery power.')

		if os == 'linux':
			if ac_stat == False and batt_stat == True and batt_percent <= batt_percent_to_hibernate:
				print(hibernation_msg)

				try:
					subprocess.run(['systemctl', 'hibernate'])
				except:
					continue

				continue
			else:
				continue

		print('> error: Your system is not supported.')
		exit(1)

def get_ac_stat():

	# Determines whether or not A/C power is connected.

	import platform

	os = platform.system().lower()

	if os == 'linux':
		
		rfile_ac_stat    = None
		fpath_ac_data    = '/sys/class/power_supply/AC/online'
		ac_plugged_codes = [1]
		
		try:
			rfile_ac_stat = open(fpath_ac_data, 'r')
			ac_stat       = int(rfile_ac_stat.read().strip())
			rfile_ac_stat.close()
			
			if ac_stat in ac_plugged_codes:
				ac_stat = True
				return ac_stat
			else:
				ac_stat = False
				return ac_stat

		except:
			ac_stat = None
			return ac_stat
	
	ac_stat = None
	return ac_stat

def get_batt_percent():

	# Determines percentage of battery life or total
	# sum of life between all present batteries.
	# 
	# NOTICE: In the event when a supported platform
	#         is detected and `batt_percent` does not
	#         feature an expected integer, a value of
	#         -1 will be provided in place of the `False`
	#         booloan, as 0 and `False` are identical
	#         in Python. With a battery life percentage
	#         of 0%, misreporting will otherwise occur.

	import platform
	import glob

	os = platform.system().lower()

	if os == 'linux':
		batt_percent          = []
		batt_percent_totalsum = None
		rfile_batt_percent    = None
		dpath_batt_data       = '/sys/class/power_supply/BAT*'
		dpath_batt_device     = []

		try:
			for dpath in glob.glob(dpath_batt_data):  # Search for battery instances.
				dpath_batt_device.append(dpath)

			if len(dpath_batt_device) == 0:  # Battery nonexistent or invalid power supply device path glob.
				raise
			else:
				for battery in dpath_batt_device:
					rfile_batt_percent = open('{}/capacity'.format(battery), 'r')
					batt_percent.append(int(rfile_batt_percent.read().strip()))
					rfile_batt_percent.close()
					
				batt_percent_totalsum = int(sum(batt_percent) / len(batt_percent))
				batt_percent          = batt_percent_totalsum

				if 0 <= batt_percent <= 100:
					return batt_percent
				else:
					raise
		except:
			batt_percent = -1
			return batt_percent
	
	batt_percent = None
	return batt_percent

def get_batt_stat():

	# Determines whether one or more batteries are present.

	import glob
	import platform
	
	os = platform.system().lower()

	if os == 'linux':
		batt_stat         = []
		rfile_batt_stat   = None
		dpath_batt_data   = '/sys/class/power_supply/BAT*'
		dpath_batt_device = []

		try:
			for dpath in glob.glob(dpath_batt_data):  # Search for battery instances.
				dpath_batt_device.append(dpath)

			if len(dpath_batt_device) == 0:  # Battery nonexistent or invalid power supply device path glob.
				raise
			else:
				batt_stat = True
				return batt_stat
		except:
			batt_stat = False
			return batt_stat
	
	batt_stat = None
	return batt_stat

if __name__ == '__main__':
	main(5)
else:
	exit()