185 lines
4.9 KiB
Bash
Executable File
185 lines
4.9 KiB
Bash
Executable File
#!/bin/sh
|
||
#!/usr/bin/env nix-shell
|
||
#!nix-shell -i bash
|
||
|
||
usage() {
|
||
echo "usage: battery_estimate [options...]"
|
||
echo
|
||
echo "pretty-prints a battery estimate (icon to indicate state, and a duration estimate)"
|
||
echo
|
||
echo "options:"
|
||
echo " --debug: output additional information, to stderr"
|
||
echo " --minute-suffix <string>: use the provided string as a minutes suffix"
|
||
echo " --hour-suffix <string>: use the provided string as an hours suffix"
|
||
echo " --icon-suffix <string>: use the provided string as an icon suffix"
|
||
echo " --percent-suffix <string>: use the provided string when displaying percents"
|
||
}
|
||
|
||
# these icons come from sxmo; they only render in nerdfonts
|
||
icon_bat_chg=("" "" "" "")
|
||
icon_bat_dis=("" "" "" "")
|
||
suffix_icon=" " # thin space
|
||
suffix_percent="%"
|
||
# suffix_icon=" "
|
||
|
||
# render time like: 2ʰ08ᵐ
|
||
# unicode sub/super-scripts: <https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts>
|
||
# symbol_hr="ʰ"
|
||
# symbol_min="ᵐ"
|
||
|
||
# render time like: 2ₕ08ₘ
|
||
# symbol_hr="ₕ"
|
||
# symbol_min="ₘ"
|
||
|
||
# render time like: 2h08m
|
||
# symbol_hr="h"
|
||
# symbol_min="m"
|
||
|
||
# render time like: 2:08
|
||
# symbol_hr=":"
|
||
# symbol_min=
|
||
|
||
# render time like: 2꞉08⧗
|
||
symbol_hr="꞉"
|
||
symbol_min="⧗"
|
||
# variants:
|
||
# symbol_hr=":"
|
||
# symbol_min="⧖"
|
||
# symbol_min="⌛"
|
||
|
||
# render time like: 2'08"
|
||
# symbol_hr="'"
|
||
# symbol_min='"'
|
||
|
||
log() {
|
||
if [ "$BATTERY_ESTIMATE_DEBUG" = "1" ]; then
|
||
printf "$@" >&2
|
||
echo >&2
|
||
fi
|
||
}
|
||
|
||
render_icon() {
|
||
# args:
|
||
# 1: "chg" or "dis"
|
||
# 2: current battery percentage
|
||
level=$(($2 / 25))
|
||
level=$(($level > 3 ? 3 : $level))
|
||
level=$(($level < 0 ? 0 : $level))
|
||
log "icon: %s %d" "$1" "$level"
|
||
if [ "$1" = "dis" ]; then
|
||
printf "%s" "${icon_bat_dis[$level]}"
|
||
elif [ "$1" = "chg" ]; then
|
||
printf "%s" "${icon_bat_chg[$level]}"
|
||
fi
|
||
}
|
||
|
||
try_path() {
|
||
# assigns output variables:
|
||
# - perc, perc_from_full (0-100)
|
||
# - full, rate (pos means charging)
|
||
if [ -f "$1/capacity" ]; then
|
||
log "perc, perc_from_full from %s" "$1/capacity"
|
||
perc=$(cat "$1/capacity")
|
||
perc_from_full=$((100 - $perc))
|
||
fi
|
||
|
||
if [ -f "$1/charge_full_design" ] && [ -f "$1/current_now" ]; then
|
||
log "full, rate from %s and %s" "$1/charge_full_design" "$1/current_now"
|
||
# current is positive when charging
|
||
full=$(cat "$1/charge_full_design")
|
||
rate=$(cat "$1/current_now")
|
||
elif [ -f "$1/energy_full" ] && [ -f "$1/power_now" ]; then
|
||
log "full, rate from %s and %s" "$1/energy_full" "$1/power_now"
|
||
# power_now is positive when discharging
|
||
full=$(cat "$1/energy_full")
|
||
rate=-$(cat "$1/power_now")
|
||
elif [ -f "$1/energy_full" ] && [ -f "$1/energy_now" ]; then
|
||
log "full, rate from %s and %s" "$1/energy_full" "$1/energy_now"
|
||
log " this is a compatibility path for legacy Thinkpad batteries which do not populate the 'power_now' field, and incorrectly populate 'energy_now' with power info"
|
||
# energy_now is positive when discharging
|
||
full=$(cat "$1/energy_full")
|
||
rate=-$(cat "$1/energy_now")
|
||
fi
|
||
}
|
||
|
||
try_all_paths() {
|
||
try_path "/sys/class/power_supply/axp20x-battery" # Pinephone
|
||
try_path "/sys/class/power_supply/BAT0" # Thinkpad
|
||
log "perc: %d, perc_from_full: %d" "$perc" "$perc_from_full"
|
||
log "full: %f, rate: %f" "$full" "$rate"
|
||
log " rate > 0 means charging, else discharging"
|
||
}
|
||
|
||
fmt_minutes() {
|
||
# args:
|
||
# 1: icon to render
|
||
# 2: string to show if charge/discharge time is indefinite
|
||
# 3: minutes to stable state (i.e. to full charge or full discharge)
|
||
# - we work in minutes instead of hours for precision: bash math is integer-only
|
||
log "charge/discharge time: %f min" "$3"
|
||
# args: <battery symbol> <text if ludicrous estimate> <estimated minutes to full/empty>
|
||
if [ -n "$3" ] && [ "$3" -lt 1440 ]; then
|
||
hr=$(($3 / 60))
|
||
hr_in_min=$(($hr * 60))
|
||
min=$(($3 - $hr_in_min))
|
||
printf "%s%s%d%s%02d%s" "$1" "$suffix_icon" "$hr" "$symbol_hr" "$min" "$symbol_min"
|
||
else
|
||
log "charge/discharge duration > 1d"
|
||
printf "%s%s%s" "$1" "$suffix_icon" "$2" # more than 1d
|
||
fi
|
||
}
|
||
|
||
pretty_output() {
|
||
if [ -n "$perc" ]; then
|
||
duration=""
|
||
if [ "$rate" -gt 0 ]; then
|
||
log "charging"
|
||
icon="$(render_icon chg $perc)"
|
||
duration="$(($full * 60 * $perc_from_full / (100 * $rate)))"
|
||
else
|
||
log "discharging"
|
||
icon="$(render_icon dis $perc)"
|
||
if [ "$rate" -lt 0 ]; then
|
||
duration="$(($full * 60 * $perc / (-100 * $rate)))"
|
||
fi
|
||
fi
|
||
fmt_minutes "$icon" "$perc$suffix_percent" "$duration"
|
||
fi
|
||
}
|
||
|
||
while [ "$#" -gt 0 ]; do
|
||
case "$1" in
|
||
"--debug")
|
||
shift
|
||
BATTERY_ESTIMATE_DEBUG=1
|
||
;;
|
||
"--icon-suffix")
|
||
shift
|
||
suffix_icon="$1"
|
||
shift
|
||
;;
|
||
"--hour-suffix")
|
||
shift
|
||
symbol_hr="$1"
|
||
shift
|
||
;;
|
||
"--minute-suffix")
|
||
shift
|
||
symbol_min="$1"
|
||
shift
|
||
;;
|
||
"--percent-suffix")
|
||
shift
|
||
suffix_percent="$1"
|
||
shift
|
||
;;
|
||
*)
|
||
usage
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
try_all_paths
|
||
pretty_output
|