ACPI low battery warning

This page describes a couple of methods for checking the battery state and alerting you when it's running low. You will need ACPI set up and running on your system. If you can determine information about your battery by checking the ACPI files, as described in How to check which battery you're using, then you shouldn't have a problem. If not, check out the ACPI resources at the end of this document.

In order do keep an eye on the battery, you'll need some kind of event that periodically calls an action script to read the battery status and do something if it's low. You can do this using the ACPI event mechanism or by using a cron job. I have provided a couple of action scripts, one a lot simpler than the other, either of which can be used. Both scripts are ripped off from the gentoo forums. See the references below.

Index

Events | Go to top

There are two ways you can monitor the battery - using the ACPI event mechanism or using a cron job.

ACPI event

ACPI should receive battery events when the battery is running low. The events are associated with actions, themselves bash scripts, meaning that you can do pretty much anything when the battery is running low.

The advantages of using the ACPI event mechanism is that it's already in place, and you probably already have scripts in place to monitor various things. When ACPI generates an event, such as a low battery event, it will process all of the ACPI event scripts to see if there are any actions that need to be carried out. The event scripts are kept in /etc/acpi/events/ and the actions in /etc/acpi/actions/. The event script below will call the /etc/acpi/actions/low_battery_warning.sh action when there is a battery event. Put it in a file called /etc/acpi/events/low_battery_warning, then restart acpid.

event=battery.*
action=/etc/acpi/actions/low_battery_warning.sh %e

The low_battery_warning.sh script will be one of the two provided below in the actions section.

Note that my Acer Travelmate 8104 laptop doesn't generate these events until the battery has only 5 minutes or so of power left. That's not as much warning as I'd want, but it's ok if I'm sitting in front of the computer with the power lead next to me (I normally am) and for those cases I'm not, it can still automatically shut down the computer to prevent data loss.

Cron

A cron job will allow you to run a script at periodic intervals. There is a nice guide for gentoo users here: Gentoo Linux Cron Guide, otherwise check out Crontab at Wikipedia.

To edit cron jobs, use the command crontab -e. If you'd like to check the battery every minute, use the following:

# Run every minute.
*   *   *   *   *   /path/to/low_battery_warning.sh

If you'd like to run it every 10 minutes:

# Run every 10 minutes.
0,10,20,30,40,50   *   *   *   *   /path/to/low_battery_warning.sh

The low_battery_warning.sh script will be one of the two provided below in the actions section.

Actions | Go to top

I have provided two actions, both bash scripts, that will check the battery status and issue a warning if it's running low. If you are using the ACPI event code provided above, call the script /etc/acpi/actions/low_battery_warning.sh, otherwise call it whatever you want (but note that I referred to it above as /path/to/low_battery_warning.sh).

To alert the user I used a GTK dialog program called zenity. You could substitute a call to dialog, kdialog if you use kde, fsetbg to change the background, or any other command you wish. One complication of using an X application to alert the user is that the Xorg display manager did not allow it without first setting the DISPLAY environment variable.

Simple script

This bash script simply reads the state and info files in /proc/acpi/battery/BAT1/ to determine the last full capacity and the remaining capacity. The battery state calculated is the remaining capacity as a percentage. If the remaining capacity is less than 5%, a warning is issued. If you'd like to change the percentage capacity at which the warning is issued, change the if [[ $state < 05 ]] line.

If your battery is not to BAT1, change the path in the scripts to reference BAT0 or BAT2 or whatever is correct for your system. See How to check which battery you're using.

#!/bin/bash
                                                                               
# Location of acpi files.
path="/proc/acpi/battery/BAT1"
 
full=`cat $path/info|grep 'last full capacity'|awk -F: '{print $2}'|awk -Fm '{print $1}'`
current=`cat $path/state|grep 'remaining capacity'|awk -F: '{print $2}'|awk -Fm '{print $1}'`
state=$(( current * 100 / $full))

export DISPLAY=:0 # This is needed so that the script can post to the display (using the zenity command, running through su as steph).

if 
then
       zenity --warning --title "Battery" --text "Low battery. (state = $state)"
fi 

Advanced script

This bash script will check the remaining capacity, the discharge rate and the in-built 'warning' and 'low' capacities. It will issue a warning if the remaining battery time falls below the value specified in the script by the BAT_ALERT_TIME variable. Additionally, if the capacity falls below the 'warning' level it will issue a warning dialog and if it falls below the 'low' level it will shut down the computer to prevent data loss.

Note that my Acer Travelmate 8104 laptop doesn't generate these events until the battery has only 5 minutes or so of power left, so for me it makes no difference if I set BAT_ALERT_TIME to anything greater than 5. That's not as much warning as I'd want, but it's ok if I'm sitting in front of the computer with the power lead next to me (I normally am) and for those cases I'm not, it can still automatically shut down the computer to prevent data loss.

In order to allow zenity to post to the current display, I've had to hard code the XAUTHORITY and DISPLAY environment variables, set to the location of the current X user's .Xauthority file and their display. This means that this script will only be able to pop up warnings to steph's display. In other words, it will only work for a single user. I am working on getting around this limitation. For the time being you'll just have to change the value of these variables to match your environment.

If your battery is not to BAT1, change the path in the scripts to reference BAT0 or BAT2 or whatever is correct for your system. See How to check which battery you're using.

Note that this script will pop up the zenity dialog box a number of times, which can be a little annoying, though nothing compared to having the suddenly computer power off.

#!/bin/bash

# Location of acpi files.
BAT_STATE="/proc/acpi/battery/BAT1/state"
BAT_INFO="/proc/acpi/battery/BAT1/info"

# Minutes from the in-built warning level that measures should be taken to prevent loosing data.
BAT_ALERT_TIME=15

# Log to syslog & /var/log/acpid 
LOGGER="/usr/bin/logger -t ACPID"

if grep -q discharging $BAT_STATE
then
   BAT_REMAIN=`awk '/remaining/ { print $3 }' $BAT_STATE` # Remaining mAh.
   BAT_DISCHARGE=`awk '/rate/ { print $3 }' $BAT_STATE` # Discharge rate in mA.
   BAT_WARN=`awk '/warning/ { print $4 }' $BAT_INFO` # Warning level in mAh.
   BAT_LOW=`awk '/low/ { print $4 }' $BAT_INFO` # Low level in mAh.

   BAT_ALERT=$(( ( ( $BAT_DISCHARGE / 60 ) * $BAT_ALERT_TIME ) )) #+ $BAT_WARN  )) # Work out the charge that will have been used in $BAT_ALERT_TIME minues (and add the warning level charge as a buffer zone).

   #echo "BAT_REMAIN = $BAT_REMAIN"
   #echo "BAT_ALERT = $BAT_ALERT"

   # These environment variables are needed so that the script can post to the current display (using the zenity command). Change mention of steph to whatever your username is.
   export XAUTHORITY=/home/steph/.Xauthority
   export DISPLAY=:0

   if 
   then
       # Log the fact that the (critically) low level has been reached.
       $LOGGER -p daemon.warn "Battery capacity is critically low, shutting down the system."

       # Pop up critical warning.
       zenity --warning --title "Battery Critically Low" --text "Battery capacity is critically low, shutting down the system. (remain = $BAT_REMAIN)" &
       
       # This is probably a good place to shut down the computer to make sure all data is written to disk. It may even be too late by now, in which case shut down the computer when it reaches the in-built warning level.
       shutdown now -h
       
   elif 
   then
       # Log the fact that the warning level has been reached.
       $LOGGER -p daemon.warn "Battery capacity is low."

       # Pop up warning.
       zenity --warning --title "Battery Low" --text "Battery capacity is low. (remain = $BAT_REMAIN)" &
              
   elif 
   then
       # Log this to let the system know that there's only a few minutes left of battery before it hit the warning level of the battery pack
       $LOGGER -p daemon.info "Battery capacity alert."

       # Pop up info.
       zenity --info --title "Battery Alert" --text "Battery capacity alert. (remain = $BAT_REMAIN)" &
       
   fi

fi

How to check which battery you're using | Go to top

You can which battery you're using by issuing the following command to get information about battery [n].

cat /proc/acpit/battery/BAT[n]/info

For example, if I issue the commands for [n] values of 0, 1 and 2, I get the following:

localhost steph # cat /proc/acpi/battery/BAT0/info
cat: /proc/acpi/battery/BAT0/info: No such file or directory
localhost steph # cat /proc/acpi/battery/BAT1/info
present:                 yes
design capacity:         4800 mAh
last full capacity:      3787 mAh
battery technology:      rechargeable
design voltage:          14800 mV
design capacity warning: 300 mAh
design capacity low:     132 mAh
capacity granularity 1:  32 mAh
capacity granularity 2:  32 mAh
model number:            ZF01
serial number:           32187
battery type:            LION
OEM info:                SANYO
localhost steph # cat /proc/acpi/battery/BAT2/info
present:                 no

This shows that I don't have a battery slot for BAT0, I am using BAT1 and I have a second battery slot at BAT2 but it doesn't have a battery in it.

References | Go to top

ACPI resources | Go to top

Last modified: 24/09/2008 Tags: (none)

This website is a personal resource. Nothing here is guaranteed correct or complete, so use at your own risk and try not to delete the Internet. -Stephan

Site Info

Privacy policy

Go to top