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]




Reply via email to