aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/critical_hibernate.py
blob: 8db2edc56753c791b0d32ad8e77dc33f3e51ce3b (plain)
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
#!/usr/bin/python3
import os
import subprocess
import sys
import time

# For use with systemd as a service:
# copy this script to /usr/local/sbin/critical_hibernate.py with:
# install -m 0755 -o root -g root critical_hibernate.py
# /usr/local/sbin/critical_hibernate.py
# and:
# /etc/systemd/system/critical_hibernate.service
#
#   [Service]
#   ExecStart=/usr/local/sbin/critical_hibernate.py
#   Restart=on-failure
#   KillMode=process
#
#   [Install]
#   WantedBy=multi-user.target
#
# Then, do a systemctl enable --now critical_hibernate

sysfs_path = '/sys/class/power_supply/BAT0/uevent'
threshold = 9
run_hibernate = True

original_print = print
def flush_print(*args, **kw):
    original_print(*args, **kw)
    filelike = kw.get('file', sys.stdout)
    filelike.flush()
print = flush_print

try:
    while True:
        batfd = None
        try:
            batfd = os.open(sysfs_path, os.O_RDONLY)
            print('monitoring %s (threshold %d%%)' % (sysfs_path, threshold))
            while True:
                uevent_dict = dict((e.split(b'=')
                                    for e in os.pread(batfd, 1024, 0).split()))
                capacity = int(uevent_dict[b'POWER_SUPPLY_CAPACITY'])
                status   = uevent_dict[b'POWER_SUPPLY_STATUS']
                if status == b'Discharging' and capacity <= threshold:
                    print('low battery %d <= %d' % (capacity, threshold))
                    if run_hibernate:
                        print('running systemctl hibernate')
                        subprocess.run(['/bin/systemctl', 'hibernate'])

                time.sleep(60)
        except OSError:
            print('io error on %s, assume battery changement' % sysfs_path)
        except FileNotFoundError:
            print('file %s is missing' % sysfs_path)
        finally:
            if batfd is not None:
                os.close(batfd)

        print('retrying to open %s in 60 seconds' % sysfs_path)
        time.sleep(60)

except KeyboardInterrupt:
    print('SIGINT, exiting')