btw/btw

229 lines
5.9 KiB
Bash
Executable File

#!/bin/sh
#
# * Battery Watchdog (see help text below).
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# For more information, please refer to <http://unlicense.org/>
# ---
# Dependencies:
# acpi <https://sourceforge.net/projects/acpiclient/>
# libnotify <https://salsa.debian.org/gnome-team/libnotify>
#
# Installation:
# # on Arch Linux:
# pacman -S acpi # (commynity repo)
# pacman -S libnotyfy # (extra repo)
# # on Debian/Ubuntu:
# apt-get install acpi
# apt-get install libnotify
print_help() {
printf \
"btw - battery watchdog. Send notification when critical battery level reached.
Usage:
btw [-c|--crit \033[4mvalue\033[0m] [-p|--preriod \033[4mseconds\033[0m] \
[-l|--log \033[4mfile\033[0m]
[-j|--syslog] [-s|--summary t\033[4mext\033[0m] \
[-b|--body t\033[4mext\033[0m] [-w|--watch]
btw --help
btw --version
Options:
-v, --version
Print version and exit.
-h, --help
Print this help message and exit.
-c, --crit \033[4mvalue\033[0m
Battery critical value in percents [default: 10]
-p, --preriod \033[4mseconds\033[0m
Battery check out period in seconds [default: 30]
-l, --log \033[4mfile\033[0m
Log file [default: ~/.cache/btw.log]
-j, --syslog
Use logger instead of log file.
-s, --summary \033[4mtext\033[0m
Custom notification title text.
-b, --body \033[4mtext\033[0m
Custom notification body text.
-w, --watch
Follow to the log file (tail -f).
See \033[1mbtw\033[0m(1) for full help.
"
}
send_notify() {
notify-send --urgency=critical --icon=battery-empty --category=System \
"$(eval echo "$1")" "$(eval echo "$2")"
}
is_int() {
if [ -n "$1" ] && [ "$1" -eq "$1" ] 2>/dev/null; then
return 0
else
echo 'Value is not integer' >&2; exit 1
fi
}
# Transform long options to short ones
for ARG in "$@"; do
shift
case "$ARG" in
--crit)
set -- "$@" "-c"
;;
--period)
set -- "$@" "-p"
;;
--log)
set -- "$@" "-l"
;;
--syslog)
set -- "$@" "-j"
;;
--summary)
set -- "$@" "-s"
;;
--body)
set -- "$@" "-b"
;;
--watch)
set -- "$@" "-w"
;;
--help)
set -- "$@" "-h"
;;
--version)
set -- "$@" "-v"
;;
*)
set -- "$@" "$ARG"
esac
done
# Parse short opts
while getopts c:p:l:js:b:whv OPT; do
case "$OPT" in
c)
is_int "$OPTARG"
critical="$OPTARG"
;;
p)
is_int "$OPTARG"
period="$OPTARG"
;;
l)
log="$OPTARG"
;;
j)
syslog=1
;;
s)
summary="$OPTARG"
;;
b)
body="$OPTARG"
;;
w)
watch=1
;;
h)
print_help
exit 0
;;
v)
echo 1.0
exit 0
;;
*)
echo Unknown option: "$OPT" >&2
exit 1
esac
done
# Default values
period="${period:-30}" # check battery every `period` seconds
critical="${critical:-10}" # battery limit (in %)
clevel="${clevel:-100}" # current battery value (in %, temporary variable)
summary="${summary:-Extremely low battery: \$level%}"
body="${body:-Check the charger, battery currently is \$state}"
lock=/tmp/btw.lock # lock file
log="${log:-"$HOME"/.cache/btw.log}"
mkdir -p "$HOME"/.cache
if [ -n "$watch" ]; then
if [ -n "$syslog" ]; then
journalctl -t btw -f
else
tail -f "$log"
fi
exit "$?"
fi
printf 'crit: %s%%; period: %ss; log: %s\n' "$critical" "$period" "$log" >&2
while true; do
battery="$(acpi -b | awk '{print $3 " " $4}' |
sed -E 's/,|%//g;' | tr '[:upper:]' '[:lower:]')"
level="${battery##* }" # e.g. "49" (in percents)
state="${battery%% *}" # e.g. "charging"
if [ "$level" -le "$critical" ]; then
if [ ! -f "$lock" ]; then
send_notify "$summary" "$body"
touch "$lock"
fi
# Warn in every percent less
if [ "$level" -le "$clevel" ]; then
send_notify "$summary" "$body"
touch "$lock"
clevel="$level"
fi
else
[ -f "$lock" ] && rm "$lock"
fi
log_message="$(printf '%s %s %s%%' \
"$(date +'%Y-%m-%d %H:%M:%S')" "$state" "$level")"
if [ -n "$syslog" ]; then
echo "$log_message"
logger -i "$$" -t btw -- "$log_message"
else
echo "$log_message" | tee -a "$log"
fi
sleep "$period"
done