i3-battery-popup 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. #! /bin/bash
  2. ################################################################################
  3. # A script that shows a battery warning on i3wm #
  4. # #
  5. # It supports multiple batteries #
  6. # (like my thinkpad T450s has) #
  7. # #
  8. # When tcl/tk (wish) is installed, it shows a nice popup #
  9. # Which you can configure to show on all workspaces #
  10. # by adding the following to your i3 config: #
  11. # "for_window [title="Battery Warning"] sticky enable" #
  12. # #
  13. # By default, the script will show two messages: #
  14. # One at 10% and one at 5% battery #
  15. # #
  16. # The script takes the following options: #
  17. # -L : The percentage at which the first popup shows (default: 10) #
  18. # #
  19. # -l : The percentage at which the second popup shows #
  20. # Default: half of the percentage given by -L #
  21. # #
  22. # -m : The message to show to the User #
  23. # #
  24. # -t : The time interval the script waits before checking the battery again. #
  25. # Give this a value in seconds: 5s, 10s, or in minutes: 5m #
  26. # Default: 5m #
  27. # #
  28. # -n : Don't use Tcl/Tk dialog. Use i3-nagbar. #
  29. # #
  30. # By R-J Ekker, 2016 #
  31. ################################################################################
  32. error () {
  33. echo $1 >&2
  34. echo "Exiting" >&2
  35. exit $2
  36. }
  37. while getopts 'L:l:m:t:F:n' opt; do
  38. case $opt in
  39. L)
  40. [[ $OPTARG =~ ^[0-9]+$ ]] || error "${opt}: ${OPTARG} is not a number" 2
  41. UPPER_LIMIT="${OPTARG}"
  42. ;;
  43. l)
  44. [[ $OPTARG =~ ^[0-9]+$ ]] || error "${opt}: ${OPTARG} is not a number" 2
  45. LOWER_LIMIT="${OPTARG}"
  46. ;;
  47. m)
  48. MESSAGE="${OPTARG}"
  49. ;;
  50. n)
  51. DONT_USE_WISH="-n"
  52. ;;
  53. t)
  54. [[ $OPTARG =~ ^[0-9]+[ms]?$ ]] || error "${opt}: ${OPTARG} is not a valid period" 2
  55. SLEEP_TIME="${OPTARG}"
  56. ;;
  57. F)
  58. LOGFILE="${OPTARG}"
  59. ;;
  60. :)
  61. error "Option -$OPTARG requires an argument." 2
  62. ;;
  63. \?)
  64. exit 2
  65. ;;
  66. esac
  67. done
  68. # This function returns an awk script
  69. # Which prints the battery percentage
  70. # It's an ugly way to include a nicely indented awk script here
  71. get_awk_source() {
  72. cat <<EOF
  73. BEGIN {
  74. FS="=";
  75. }
  76. \$1 ~ /ENERGY_FULL_DESIGN$/ {
  77. f += \$2;
  78. }
  79. \$1 ~ /ENERGY_NOW\$/ {
  80. n += \$2;
  81. }
  82. END {
  83. print int(100*n/f);
  84. }
  85. EOF
  86. }
  87. is_battery_discharging() {
  88. cat $BATTERIES | grep Charging && return 1
  89. return 0
  90. } >/dev/null
  91. get_battery_perc() {
  92. cat $BATTERIES | awk -f <(get_awk_source)
  93. }
  94. show_popup() {
  95. # WISH_SCRIPT="wm state . withdrawn; tk_messageBox -icon warning -title \"Battery Warning\" -message \"${MESSAGE}\"; exit"
  96. # echo "$WISH_SCRIPT" | wish
  97. notify-send --urgency=critical --icon=warning "Battery Warning" "${MESSAGE}"
  98. }
  99. show_nagbar(){
  100. /usr/bin/i3-nagbar -m "${MESSAGE}"
  101. }
  102. show_message(){
  103. echo "showing warning" >&2
  104. # if [[ -z $DONT_USE_WISH ]] && which wish; then
  105. show_popup
  106. # else
  107. # show_nagbar
  108. # fi
  109. }
  110. main (){
  111. # Setting defaults
  112. UPPER_LIMIT="${UPPER_LIMIT:-10}"
  113. UPPER_HALF=$(( $UPPER_LIMIT / 2 ))
  114. LOWER_LIMIT=${LOWER_LIMIT:-$UPPER_HALF}
  115. MESSAGE="${MESSAGE:-Warning: Battery is getting low}"
  116. SLEEP_TIME="${SLEEP_TIME:-5m}"
  117. BATTERIES=/sys/class/power_supply/BAT*/uevent
  118. echo "Upper ${UPPER_LIMIT}; Lower ${LOWER_LIMIT}; sleep ${SLEEP_TIME}"
  119. echo "Current: $(get_battery_perc)%"
  120. LIMIT="${UPPER_LIMIT}"
  121. # This will be set to "y" after first click
  122. # So we know when to stop nagging
  123. POPUP_CLICKED=""
  124. while true; do
  125. echo -n "Checking.. "
  126. PERC=$(get_battery_perc)
  127. echo "got ${PERC}%"
  128. if is_battery_discharging; then
  129. if [[ $PERC -lt $LIMIT ]]; then
  130. show_message
  131. if [[ -z $POPUP_CLICKED ]]; then
  132. # first click; set limit lower
  133. POPUP_CLICKED="y"
  134. LIMIT=${LOWER_LIMIT}
  135. else
  136. # We clicked twice; No more popups
  137. LIMIT=0
  138. fi
  139. fi
  140. else
  141. echo "Battery Charging"
  142. # restart messages, reset limits
  143. POPUP_CLICKED=""
  144. if [[ $PERC -gt $UPPER_LIMIT ]]; then
  145. LIMIT=${UPPER_LIMIT}
  146. else
  147. LIMIT=${LOWER_LIMIT}
  148. fi
  149. fi
  150. echo "sleeping ${SLEEP_TIME}; current limit ${LIMIT}%; ${POPUP_CLICKED:+Popup was clicked}"
  151. sleep "${SLEEP_TIME}"
  152. done
  153. } >&2
  154. LOCK_FILE="${HOME}/.battery_state.lock"
  155. (
  156. if [[ -n $LOGFILE ]]; then
  157. exec >>$LOGFILE 2>&1
  158. fi
  159. flock -xn 200 || error "Cannot acquire lock ${LOCK_FILE}" 3
  160. main
  161. ) 200>"${LOCK_FILE}"