I've been trying to make a script for battery notifications for 15%, 10% and 5%. When the battery reaches those levels, it displays a notification saying to change my laptop. I made a variable called runOnce to state whether or not the script has already executed the if-statements once. If runOnce is false, run the if-statements inside a while-loop and if one of them is true, execute the commands and then set runOnce to true, stopping the while-loop. However, since I need the whole code to loop, so it also resets runOnce back to false. So, if the battery level is still the same, it repeatedly executes those commands. I've tried different solutions, but I can't figure out how not to let the script reset the variable back to false.
while true; do
battery=$(cat /sys/class/power_supply/BAT0/capacity)
batteryStatus=$(cat /sys/class/power_supply/BAT0/status)
runOnce=false
if [ $batteryStatus != "Charging" ]; then
while [ "$runOnce" = false ]; do
runOnce=false
if [ $battery -eq 15 ]; then
notify-send --urgency=critical "Low Battery! (15%)" "Charge your laptop quickly."
espeak "Low battery. Please charge."
runOnce=true
elif [ $battery -eq 10 ]; then
notify-send --urgency=critical "Critical Battery! (10%)" "Charge your laptop now. Before you lose your data. Seriously."
espeak "Critical battery. Please charge."
runOnce=true
elif [ $battery -eq 5 ]; then
notify-send --urgency=critical "REALLY Critical Battery! (5%)" "Dude, your battery is going to go to the landfill soon."
espeak "Critical battery. Charge immediately."
runOnce=true
fi
done
fi
sleep 5
done
CodePudding user response:
You have to "remember state". You have to "remember" what battery was in what state between runs kind-of "above" the loop. Display message only when state changes - when changes from normal voltage to low, or changes from low to critical. Let's do some refactoring:
display_low() {
notify-send --urgency=critical "Low Battery! (15%)" "Charge your laptop quickly."
espeak "Low battery. Please charge."
}
display_crit() {
notify-send --urgency=critical "Critical Battery! (10%)" "Charge your laptop now. Before you lose your data. Seriously."
espeak "Critical battery. Please charge."
}
display_really_crit() {
notify-send --urgency=critical "REALLY Critical Battery! (5%)" "Dude, your battery is going to go to the landfill soon."
espeak "Critical battery. Charge immediately."
}
battery_to_state() {
battery=$1
# lets use bash syntax
if (( battery <= 5 )); then
echo really_crit
elif (( battery <= 10 )); then
echo crit
elif (( battery <= 15 )); then
echo low
fi
# if greater than 15, state is empty
}
laststate=
while true; do
batteryStatus=$(cat /sys/class/power_supply/BAT0/status)
battery=$(cat /sys/class/power_supply/BAT0/capacity)
curstate=$(battery_to_state "$battery")
if
# Only display when not charging
[[ "$batteryStatus" != "Charging" ]] &&
# Only display if the state is not empty (below 15!)
[[ -n "$curstate" ]] &&
# Only display if the state __changed__!
[[ "$laststate" != "$curstate" ]]
then
# jump to one of display_* functions, depending on state
"display_$curstate"
fi
laststate=$curstate
#
sleep 5
done