Hello List.
I'm following the tradition of answering my own questions. I found no
answer about how the laptop behaves on a low battery, so I ran a test. I
let the battery drain out, and watched carefully what happens. Here are
the answers:
(1) Does a low battery generate an "event"?
Yes, it does. And more: Every time the battery voltage changes (and the
charging estimation accordingly), I get an event as follows:
battery BAT1 00000080 00000001
Note that I got this event when the battery was *charging* as well. To
make things even worse, this event is triggered off whenever the AC
power is connected or disconnected, so this is really messy. Solution:
Write a script that makes a checkup (attached).
(2) Does anyone know how to use ACPI to shut down a laptop gracefully?
Now I know. ;)
(3) In case I'll write an application of my own, that polls
/proc/acpi/battery/(something): What behaviour can I expect from my
laptop?
By default (ACPI in kernel activated, acpid running but has no config
files), the computer ignored the state of low battery, even when it was
below 200 mAh, which is marked as the "capacity low" level. I didn't run
the battery to total drain. Some things are better untried.
What should trigger off a graceful shutdown?
A config file and a script that handles battery events. The drawback of
this method is that the script is executed every time the batteries
capacity is noted to change, which is something like once in 30 seconds.
Ideally, I would like an event only when a critical battery event
happens, but it seems there is no such thing.
It may be better to just poll the battery status every 10 seconds or so
with a regular script. This will waste some resources when the system is
on constant AC power, but will spare the recurring process generation
when the battery is charging, or more importantly, when it's
discharging. I'll leave it as is for now.
Even more interesting would be to write a small kernel patch that
detects low battery state, and calls some executable. Anyone in for some
kernel hacking?
I wrote a script in Perl. It would be more economic to write it in
assembly language (or C), but I had better things to do. Note that it
uses "wall" generously to inform the user whenever something looks
fishy, so I don't think you'd like to try this on a computer other than
your personal laptop...
I hope this will help someone. Config file and script follow.
Eli
/etc/acpi/events/lowbat.conf: (it should be two rows)
event=battery.*
action=/usr/local/bin/checkbattery || wall "Warning: failed to run
/usr/local/bin/checkbattery as needed by acpid"
/usr/local/bin/checkbattery:
#!/usr/bin/perl -w
eval {
open INFO, "/proc/acpi/battery/BAT1/info" ||
die("Failed to open /proc/acpi/battery/BAT1/info\n");
$info = join "",<INFO>;
close INFO;
open STATE, "/proc/acpi/battery/BAT1/state" ||
die("Failed to open /proc/acpi/battery/BAT1/state\n");
$state = join "",<STATE>;
close STATE;
($warnlevel) = ($info =~ /^design capacity warning:\s*(\d+)\s*mAh/im);
die "Failed to resolve Design Capacity Warning from
/proc/acpi/battery/BAT1/info\n"
unless (defined $warnlevel);
($level) = ($state =~ /^remaining capacity:\s*(\d+)\s*mAh/im);
die "Failed to resolve Remaining Capacity from
/proc/acpi/battery/BAT1/state\n"
unless (defined $level);
($ac) = ($state =~ /^charging state:\s*(\w+)/im);
die "Failed to resolve Charging State from
/proc/acpi/battery/BAT1/state\n"
unless (defined $ac);
die "Unknown Charging State extracted from
/proc/acpi/battery/BAT1/state: $ac\n"
unless (($ac eq 'discharging') || ($ac eq 'charging') || ($ac eq
'unknown'));
# If we got here, we have the data. We're shutting down if the battery
level
# is below the warning level, unless the battery happens to be charging.
exit 0 if ($ac eq 'charging');
exit 0 if ($level > $warnlevel);
# We got here? We need a shutdown NOW!
open F, "|wall";
print F <<"LOWEND";
******************************************************************************
L O W B A T T E R Y S H U T D O W N
Battery charge is $level mAh <= $warnlevel mAh and mode is $ac
******************************************************************************
LOWEND
exec '/sbin/shutdown','-h','now'; # Bye-bye system
};
if ($@) {
open F, "|wall";
print F <<"END";
This is $0, which is run from acpid talking
A battery event was triggered, but it couldn't be handled.
The reason for a battery event is a change in the battery's charge capacity
or AC cord plugged in or out. In other words, the event in itself may be
harmless.
On the other hand, the failure of this script means that your computer
may not
shut down when the battery is low. You should check this up.
The reason for the failure:
$@
END
close F;
}
--
Web: http://www.billauer.co.il
--------------------------------------------------------------------------
Haifa Linux Club Mailing List (http://www.haifux.org)
To unsub send an empty message to [EMAIL PROTECTED]