29

Just yesterday I migrated from Ubuntu 18.04 to Ubuntu 20.04. In 18.04 there was a software called "Battery Monitor" that monitors your battery percentage and notifies you when your battery percentage as reached low level.

I tried to install it in 20.04 but it seems it was not made compatible for it or maybe I am doing something wrong...

Can anyone please help me with this or find me an alternative?

My most important need is to be notified when my battery percentage goes below a certain number.

Thank you

6 Answers6

31

I have Ubuntu Budgie 20.04 and this worked for me:

cd /etc/UPower
sudo nano UPower.conf

If you set UsePercentageForPolicy=true then edit the percentage lines to your liking, such as:

PercentageLow=50
PercentageCritical=35

If you prefer a time based approach then set UsePercentageForPolicy to false and set the time notification options to your liking, such as:

TimeLow=1200
TimeCritical=300

Hit ctrl+X to save the UPower.conf file and close out of nano editor.
Reboot computer or sudo systemctl restart upower for changes to take effect.

By doing this I was able to get the low and critical battery notifications. The pop-up notification only displays for about 2 seconds. Here is what it looks like: enter image description here

Tuna
  • 195
hoatzin
  • 568
  • it works!!!!!!! – Abdullah Omar Jul 28 '20 at 10:27
  • Works for me too on Ubuntu 20.04. – Rich Dougherty Jan 15 '21 at 03:03
  • it works on Ubuntu 18.04 too – Tuna Jul 27 '21 at 07:53
  • 1
    May I know the command for Battery full notification at 95% ? Thanks. – user227495 Sep 04 '21 at 18:18
  • 1
    A battery critical notification which only displays for two seconds is not very useful. Can it be made persistent? – Kjell Jun 07 '22 at 11:27
  • @kjell I totally agree that a two second notification is hardly useful. I never found a way to adjust it's persistability. Have you tried the solution offered by @ ensei_tankado ? He claims his notifications are persistent. – hoatzin Jun 12 '22 at 10:18
  • @hoatzin Sorry to hijack, what are you using to get the info in the toolbar... I.e public ip etc? :) – Brian Aug 09 '22 at 09:38
  • @brian I used Indicator-sysmonitor. 1. sudo apt-get install python3-psutil curl git gir1.2-appindicator3-0.1 2. git clone https://github.com/fossfreedom/indicator-sysmonitor.git 3. cd indicator-sysmonitor 4. sudo make install 5. nohup indicator-sysmonitor & 6. Click on the indicator at top of screen and select Preferences 7. Confirm that RUN ON STARTUP is selected, then go to ADVANCED tab 8. Set command line to: cpu {cpu} {cputemp} | mem {mem} | publicIP {publicip} | battery {bat0} – hoatzin Aug 13 '22 at 22:45
  • Works for me on Ubuntu 22.04 LTS – jovian May 15 '23 at 05:28
6

After a lot of research, here's a script that works perfectly - and gives persistent notifications for both high and low battery ;)

Procedure

  1. Store the script (written below) in some folder (like a folder named scripts in the home directory)
  2. Open terminal and type: crontab -e
  3. Add this line to run the script automatically every 2 minutes: (Note: I've kept the script's name as battery notifications)

*/2 * * * * bash /home/garmadon/scripts/battery-notifications.sh

  1. Press Ctrl + x and then enter to exit and save the crontab.
  2. Log out and log into the system (or restart) to see the effect.

The script

#!/bin/bash

export XDG_RUNTIME_DIR=/run/user/$(id -u)

V1="Charging"

V2=$(grep -w "Charging" /sys/class/power_supply/BAT0/status)

V3=$(grep -Eo '[0-9]{1,}' /sys/class/power_supply/BAT0/capacity)

if [ "$V1" = "$V2" ] && [ "$V3" -ge 85 ]; then notify-send -u critical "Remove Charger!" fi

U1="Discharging"

U2=$(grep -w "Discharging" /sys/class/power_supply/BAT0/status)

if [ "$U1" = "$U2" ] && [ "$V3" -le 45 ]; then notify-send -u critical "Plug in Charger!" fi

Note:

  1. I'm on ubuntu 20.04
  2. I've kept 85% and 45% as the notification level, you can modify them according to your needs.
  3. This script gives persistent notifications that won't go away until you click on them. This comes in handy if you are away from your laptop and hence prevents you from missing the reminder.

Learn more about cron here:

  1. https://www.geeksforgeeks.org/crontab-in-linux-with-examples/
  2. https://crontab.guru
  • 1
    Thanks for these instructions! On Ubuntu 22.04, crontab didn't accept /2... so might need to use */2... instead (or just *... for every minute). – tyknkd Feb 13 '23 at 03:39
6

A slight variation on Ensei_Tankado's answer that doesn't result in multiple notifications piling-up.

Same Procedure, different Script:

#!/bin/bash

export XDG_RUNTIME_DIR=/run/user/$(id -u)

V1="Charging"

V2=$(grep -w "Charging" /sys/class/power_supply/BAT0/status)

V3=$(grep -Eo '[0-9]{1,}' /sys/class/power_supply/BAT0/capacity)

if [ "$V1" = "$V2" ]; then rm -f "/tmp/battery-notification-low" if [ "$V3" -ge 80 ] && [[ ! -f "/tmp/battery-notification-high" ]]; then touch "/tmp/battery-notification-high" notify-send -u critical "Battery High" "Remove Charger" fi fi

U1="Discharging"

U2=$(grep -w "Discharging" /sys/class/power_supply/BAT0/status)

if [ "$U1" = "$U2" ]; then rm -f "/tmp/battery-notification-high" if [ "$V3" -le 40 ] && [[ ! -f "/tmp/battery-notification-low" ]]; then touch "/tmp/battery-notification-low" notify-send -u critical "Battery Low" "Plug in Charger" fi fi

  • but the tmp file will remain after shutdown and restart, no? – Bachi Dec 30 '23 at 12:54
  • That apparently depends on your distro, see this answer

    I will note that with how the script above is written, if the low/high temp file persists after restart, then it will suppress that same state's notification from being recreated. This could be addressed with a "good state" check that removes the temp files, ie: If charging but not over high threshold, remove high temp. If discharging but not under low threshold, remove low temp

    – Nick Clark Dec 31 '23 at 18:37
1

Could be very related as i ended up looking into how to restore battery indicator

$ sudo systemctl restart upower

Job for upower.service failed because a fatal signal was delivered to the control process. See "systemctl status upower.service" and "journalctl -xe" for details.

$ systemctl --failed

UNIT LOAD ACTIVE SUB DESCRIPTION
● upower.service loaded failed failed Daemon for power management

so i had to install

$ sudo apt install systemd:amd64 systemd-timesyncd:amd64

and now service started and battery indicator is back

$ sudo systemctl start upower
Tim
  • 11
0

I came to this workaround:

Works in ubuntu 20

Dependencies

sudo apt install gir1.2-appindicator3-0.1 acpi libappindicator3-1
sudo apt install libnotify4 libgirepository1.0-dev libcairo2

python3 -m pip install pycairo

1. Download source

cd ~/Downloads/
wget https://github.com/maateen/battery-monitor/archive/master.zip
unzip master.zip
cd battery-monitor-master/

2. Modification of Makefile

nano Makefile (3 changes)

1. change sh in first line to bash

2. change from:

PREFIX ?= /usr

to:

PREFIX ?= /home/USERNAME/.local

3 change python version in two! lines

from:

python setup.py clean/install

to:

python3 setup.py clean/install

3. Install as root

sudo su
export PYTHONPATH=/home/USERNAME/.local/lib/python3.8/site-packages/
make install
exit

4. Run as non-root

nohup battery-monitor &

5. A fix in Notification.py for the proper working of upper warning

I know it is odd but, I had to fix this:
#                                     ↓↓↓ your python version of install             ↓↓↓ your python version
sudo nano /home/USERNAME/.local/lib/python3.8/site-packages/battery_monitor-0.0.0-py3.8.egg/battery_monitor/Notification.py
# change the old lines with the new ones
         elif state == 'charging':
NEW            if (percentage >= self.upper_threshold_warning and
OLD            if (percentage != self.last_percentage and
                 remaining != "discharging at zero rate - will never fully discharge" and
                 self.last_notification != "upper_threshold_warning"):
                     self.last_percentage = percentage
NEW                  self.last_notification = "upper_threshold_warning"
OLD                  self.last_notification!="upper_threshold_warning"
                     self.show_notification(type="upper_threshold_warning",
                                            battery_percentage=percentage,
                                            remaining_time=remaining)

Related: https://www.linuxquestions.org/questions/slackware-14/help-to-build-libindicator-libappindicator-for-battery-monitor-4175668385/

Ferroao
  • 850
0

Sometimes while working on my laptop, when not connected to the AC power source, I get notified when power is critically low. I wrote this script which notifies me for every steps of 10% change in power level (for more details, please refer to the script code). For notification I preferred using zenity to notify-send as I frequently miss out to check such toast notifications while busy.

Script name: /home/username/bin/notification_battery_discharge.sh ;

Contents:

#!/bin/bash

notification_battery_discharge.sh (v0.1)

Configuration options:

declare -i __DISPLAY_CHARGING_NOTIFICATIONS=1 ## where, 1=true, 0=false declare __FILENAME="/sys/class/power_supply/BAT1/uevent"

declare -ri __TIME_SLEEP_SECONDS=60 declare __CURR_POWER_SUPPLY_STATUS="" declare -i __CURR_BATTERY_PERCENTAGE_LEVEL=0 declare -i __LOWER_LEVEL=0 declare -i __UPPER_LEVEL=0

declare -A __LEVEL __LEVEL["90-100"]=0 ## where, 1=true; 0=false __LEVEL["80-90"]=0 __LEVEL["70-80"]=0 __LEVEL["60-70"]=0 __LEVEL["50-60"]=0 __LEVEL["40-50"]=0 __LEVEL["30-40"]=0 __LEVEL["20-30"]=0 __LEVEL["10-20"]=0 __LEVEL["0-10"]=0 declare -A __LEVEL_MSG_DISPLAYED __LEVEL_MSG_DISPLAYED["90-100"]=0 ## where, 1=true; 0=false __LEVEL_MSG_DISPLAYED["80-90"]=0 __LEVEL_MSG_DISPLAYED["70-80"]=0 __LEVEL_MSG_DISPLAYED["60-70"]=0 __LEVEL_MSG_DISPLAYED["50-60"]=0 __LEVEL_MSG_DISPLAYED["40-50"]=0 __LEVEL_MSG_DISPLAYED["30-40"]=0 __LEVEL_MSG_DISPLAYED["20-30"]=0 __LEVEL_MSG_DISPLAYED["10-20"]=0 __LEVEL_MSG_DISPLAYED["0-10"]=0

function checkLevel() { declare myLevel="${1}" ## $1 is required to be level string e.g. "80-90"

if [[ ${__LEVEL[${myLevel}]} -eq 1 && ${__LEVEL_MSG_DISPLAYED[${myLevel}]} -eq 0 ]] ; then
    if [[ "${__CURR_POWER_SUPPLY_STATUS}" != "Discharging" ]] ; then
        if [[ ${__DISPLAY_CHARGING_NOTIFICATIONS} -eq 1 ]] ; then
            zenity --info --title="Battery Status: ${__CURR_POWER_SUPPLY_STATUS} ($(date +%Y-%m-%d' '%H:%M))" --text="The power supply is currently ${__CURR_POWER_SUPPLY_STATUS} at level ${__CURR_BATTERY_PERCENTAGE_LEVEL}%." &
        fi
    else
        zenity --error --title="Battery Status: ${__CURR_POWER_SUPPLY_STATUS} ($(date +%Y-%m-%d' '%H:%M))" --text="The power supply is currently ${__CURR_POWER_SUPPLY_STATUS} at level ${__CURR_BATTERY_PERCENTAGE_LEVEL}%." &
    fi
    __LEVEL_MSG_DISPLAYED[${myLevel}]=1
fi
if [[ ${__LEVEL[${myLevel}]} -eq 0 && ${__LEVEL_MSG_DISPLAYED[${myLevel}]} -eq 1 ]] ; then
    __LEVEL_MSG_DISPLAYED[${myLevel}]=0
fi

}

while : ; do while read ; do if [[ "${REPLY}" =~ ^POWER_SUPPLY_STATUS=(.*)$ ]] ; then __CURR_POWER_SUPPLY_STATUS=${BASH_REMATCH[1]} fi if [[ "${REPLY}" =~ ^POWER_SUPPLY_CAPACITY=(.*)$ ]] ; then __CURR_BATTERY_PERCENTAGE_LEVEL=${BASH_REMATCH[1]} fi done < "${__FILENAME}"

__LOWER_LEVEL=90
__UPPER_LEVEL=100
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=80
__UPPER_LEVEL=90
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=70
__UPPER_LEVEL=80
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=60
__UPPER_LEVEL=70
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=50
__UPPER_LEVEL=60
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=40
__UPPER_LEVEL=50
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=30
__UPPER_LEVEL=40
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=20
__UPPER_LEVEL=30
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=10
__UPPER_LEVEL=20
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

__LOWER_LEVEL=0
__UPPER_LEVEL=10
if [[ ${__CURR_BATTERY_PERCENTAGE_LEVEL} -ge ${__LOWER_LEVEL} &amp;&amp; ${__CURR_BATTERY_PERCENTAGE_LEVEL} -lt ${__UPPER_LEVEL} ]] ; then
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=1
else
    __LEVEL[&quot;${__LOWER_LEVEL}-${__UPPER_LEVEL}&quot;]=0
fi

checkLevel &quot;90-100&quot;
checkLevel &quot;80-90&quot;
checkLevel &quot;70-80&quot;
checkLevel &quot;60-70&quot;
checkLevel &quot;50-60&quot;
checkLevel &quot;40-50&quot;
checkLevel &quot;30-40&quot;
checkLevel &quot;20-30&quot;
checkLevel &quot;10-20&quot;
checkLevel &quot;0-10&quot;

sleep ${__TIME_SLEEP_SECONDS}s

done

End of script.

Configuration: Appropriately fix the __FILENAME variable to point to /sys/class/power_supply/BAT0/uevent or /sys/class/power_supply/BAT1/uevent or something else as needed. If you don't want the notification during charging use __DISPLAY_CHARGING_NOTIFICATIONS=0 .

The script can be started manually by running bash /home/username/bin/notification_battery_discharge.sh .

Setup:

For automatic startup, create a .desktop file in $HOME/.config/autostart e.g. /home/username/.config/autostart/notification_battery_discharge.desktop with the following content:

[Desktop Entry]
Name=Notification of Battery Discharge
Exec="/home/username/bin/notification_battery_discharge.sh"
Type=Application

If required run chmod +x /home/username/.config/autostart/notification_battery_discharge.desktop . Then log out, and log back in, the script should start its notification process.

Alternatively, for automatic start up using systemd, create a .service file in $HOME/.config/systemd/user/ directory e.g. $HOME/.config/systemd/user/notification_battery_discharge.service with the following content:

[Unit]
Description=Display notification at different levels of battery discharging/charging.
After=graphical-session.target

[Service] Type=oneshot ExecStart=-/bin/bash -c '/home/username/bin/notification_battery_discharge.sh'

[Install] WantedBy=graphical-session.target

Then use the command systemctl --user enable notification_battery_discharge.service then log out, and log back in. The notification process should start.

rusty
  • 16,327