djangoproject.com | python.org | nginx.org
version seven.
  http://demongin.org
demongin.org - Check Laptop Battery State on Ubuntu Server

Check Laptop Battery State on Ubuntu Server

A short "how to" describing how to write a script that emails when the primary laptop battery is discharging.


Saturday, 2009-11-14 | Programming

What about WRITING it first and rationalizing it afterwards?

Larry Wall

Here's the sitch: I've got an old laptop running Ubuntu Server (Karmic). Now, this old laptop, being old, has a messed up AC adapter plug: it's not terrible, but you've got to jiggle it until it works. The problem, then, is that I don't want the thing to get jiggled loose and run its battery down.

Now, normally, I would probably just jiggle it until it was right and then tape it into place. But a.) I've got dogs and b.) I like automating simple tasks with shell scripting (instead of tape) lately, so what I'm going to do is write a script that checks the battery status periodically and hollers at me if it becomes unplugged.

In order to do this, the First thing to do is figure out which battery you're using:

root@matilda:~# for INFO in `ls /proc/acpi/battery/*/info`; do echo $INFO && cat $INFO; done
/proc/acpi/battery/BAT0/info
present:                 yes
design capacity:         52170 mWh
last full capacity:      52170 mWh
battery technology:      rechargeable
design voltage:          11100 mV
design capacity warning: 3000 mWh
design capacity low:     1000 mWh
capacity granularity 1:  200 mWh
capacity granularity 2:  200 mWh
model number:            DELL 4P8946
serial number:           1185
battery type:            LION
OEM info:                Panasonic
/proc/acpi/battery/BAT1/info
present:                 no
In my case, I've got a battery in BAT0 and no battery in BAT1.

Now, part of my project is that I need to know when the battery is unplugged (i.e. not charging, so I'm going to write a little PERL script that fires off an email from my Ubuntu Server when the battery's "state" file contains the string "discharging". Here's how the "state" file is supposed to look:
root@matilda:/opt# cat /proc/acpi/battery/BAT0/state 
present:                 yes
capacity state:          ok
charging state:          charged
present rate:            unknown
remaining capacity:      52170 mWh
present voltage:         12576 mV
When something is amiss, then, the "charging state" is going to be "discharging", which is going to be our fail condition: if that file contains the string "discharging", then it'll be time for the server to phone home and ask for assistance.

Before we get to the scripting, however, I should mention that one of the funny idiosyncrasies of Ubuntu Karmic is that it doesn't come with good, old fashioned /usr/bin/mail installed. So I'm going to need to snatch that up, real quick, by installing the "mailutils" package:
root@matilda:~# aptitude install mailutils
Now, I've been finding lately (i.e. since I started working in a PERL shop) that PERL is really good when you want something that lets you work with strings in a manner that is more nuanced than BASH, but which has almost no overhead (i.e. can be written "quick and dirty" without a bunch of fancy crap). What follows, then, is basically a glorified BASH script (and, it should go without saying, really nasty PERL):
#!/usr/bin/perl

$host = uc(`hostname`);
$c = discharging;
$file = `cat /proc/acpi/battery/BAT0/state`;

if ($file =~ $c){
    `echo "$file" |mail -s "[$host] unplugged!" toconnell\@tyrannybelle.com`;
};
Now that I've got my script and my mail program, I'm going to schedule a cron task that runs the script every 30 minutes (because I figure that my old battery is good for about an hour and a half at least before she drops the laptop):
root@matilda:~# echo "*/30 * * * *	/opt/batt_check.pl" > /etc/cron.d/batt_check
root@matilda:~# chmod +x /opt/batt_check.pl
And that's it. Every 30 minutes the check runs and, if the battery is discharging, I get an email.