You are not logged in.

#1 2012-08-27 12:00:14

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Auto hibernate on low battery W/O laptop-mode or pm-utils

Is there a way to make laptop hibernate automatically when battery falls under, say, 3% capacity WITHOUT laptop-mode or pm-utils?

So, basically, I need to run 'hibernate' command with root privileges when battery state is X or lower. 

How would I go about it?

Offline

#2 2012-08-27 12:08:28

tomk
Forum Fellow
From: Ireland
Registered: 2004-07-21
Posts: 9,839

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Assuming you have a 'hibernate' command installed, you could use acpid to do that.

Offline

#3 2012-08-27 13:41:23

alienated_humour
Member
From: NYC
Registered: 2011-07-28
Posts: 23

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

There's a handy tool found here that could be what you're looking for (though you'll have to change the command used to hibernate).

Offline

#4 2012-08-27 14:25:30

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

@alienated_humour,
So, this creates a python daemon regularly checking on battery status? This could work but I would like to avoid running extra processes if possible.

@tomk,
Can you elaborate on how exactly could it be done? I checked acpid wiki, but it mentions nothing about battery.

Offline

#5 2012-08-27 14:36:32

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

I found a solution here: http://archive09.linux.com/feature/114220.html

/etc/acpi/actions/battery.sh
#!/bin/sh
if grep -q on-line /proc/acpi/ac_adapter/AC/state; then
  exit 0
fi

BAT_DIR=/proc/acpi/battery/BAT0
FULL_BAT=`grep 'last full capacity' ${BAT_DIR}/info | awk '{ print $4 }'`
CUR_BAT=`grep 'remaining capacity' ${BAT_DIR}/state | awk '{ print $3 }'`
AVG=`expr $(expr ${CUR_BAT} \* 100) / ${FULL_BAT}`

if [ "$AVG" -le "4" ]; then
  /usr/local/sbin/suspend.sh hibernate
fi

The problem is the article is quite old and the only things I have in /proc/acpi/ are:

$ ls -R
.:
button  ibm  wakeup

./button:
lid

./button/lid:
LID

./button/lid/LID:
state

./ibm:
beep  bluetooth  cmos  driver  fan  hotkey  led  light  thermal  video  volume

Offline

#6 2012-08-27 15:07:47

WonderWoofy
Member
From: Los Gatos, CA
Registered: 2012-05-19
Posts: 8,414

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

So you have to modify it to use they /sys directory.  So start perusing /sys and find the relevant info.  I think (not certain, from memory only) it can be foudn at /sys/class/power_supply/BAT0.  You could also simply use the acpi command (not acpid) with some piping to cut to determine the remaining percentage.

$ acpi | cut -d, -f2

then use that info to rework the script.   I am unsure how you think that running a cron job with that script is any better than having a service intermittently poll for the same info.  Seems to me that either way would be a more or less equal draw on power and system resources.

Offline

#7 2012-08-27 15:20:40

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

I need acpid for other things, too, so I think I will go the daemon way.

Anyway, I found the missing files and I modified the script, but it does not work and I am not sure why. Here it is:

#!/bin/sh
if grep -q 1 /sys/class/power_supply/AC/online; then
  exit 0
fi

AVG=`cat /sys/devices/platform/smapi/BAT0/remaining_percent`

if [ "$AVG" -le "92" ]; then
  hibernate
fi

I put % at 92 so that I don't have to wait to test it.

Offline

#8 2012-08-27 23:42:13

WonderWoofy
Member
From: Los Gatos, CA
Registered: 2012-05-19
Posts: 8,414

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

I wasn't saying to do away with acpid, but if you just throw an acpi into your command prompt it gives you battery info.  The pipe to cut give you just the percentage.  But you figured it out with /sys, so good job.

Offline

#9 2012-08-28 06:50:01

punkeroso
Member
From: Rome, Italy
Registered: 2007-01-19
Posts: 105

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

I'm using this in my handler.sh:

#!/bin/sh

STATE=`cat /sys/class/power_supply/BAT0/status`
NOW=`cat /sys/class/power_supply/BAT0/energy_now`
FULL=`cat /sys/class/power_supply/BAT0/energy_full`
FLOAT=`awk "BEGIN { print $NOW/$FULL*100 }" ;`
INT=${FLOAT/\.*}

set $*

case "$1" in

        battery)
                if [ "$STATE" = "Discharging" ] && [ $INT -le 3 ]; then
                        #dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Hibernate
                        systemctl hibernate
                fi
        ;;

It works because my laptop periodically, when on battery, sends an event that is used to check if the battery is below 3%.

Offline

#10 2012-08-28 11:27:11

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

I tried putting it in /etc/acpi/actions/battery.sh but it does not work.

#!/bin/sh

STATE=`cat /sys/class/power_supply/AC/online`
FULL_BAT=`cat /sys/devices/platform/smapi/BAT0/energy_full`
CUR_BAT=`cat /sys/devices/platform/smapi/BAT0/energy_now`
AVG=`expr $(expr ${CUR_BAT} \* 100) / ${FULL_BAT}`

      if [ "$STATE" = "0" ] && [ $AVG -le 97 ]; then
         #dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Hibernate
         hibernate
      fi

I don't think I need to reboot before it can take action, right?

My handler.sh is already full with some stuff so I am not sure how to modify it without screwing it up:

#!/bin/sh
# Default acpi script that takes an entry for all actions

minspeed=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`
maxspeed=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`
setspeed="/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"

set $*

case "$1" in
    button/power)
        case "$2" in
            PBTN|PWRF)
                logger "PowerButton pressed: $2"
                poweroff
                ;;
            *)
                logger "ACPI action undefined: $2"
                ;;
        esac
        ;;
    button/sleep)
        case "$2" in
            SLPB|SBTN)
                echo -n mem >/sys/power/state
                ;;
            *)
                logger "ACPI action undefined: $2"
                ;;
        esac
        ;;
    ac_adapter)
        case "$2" in
            AC|ACAD|ADP0)
                case "$4" in
                    00000000)
                        echo -n $minspeed >$setspeed
                        #/etc/laptop-mode/laptop-mode start
                        ;;
                    00000001)
                        echo -n $maxspeed >$setspeed
                        #/etc/laptop-mode/laptop-mode stop
                        ;;
                esac
                ;;
            *)
                logger "ACPI action undefined: $2"
                ;;
        esac
        ;;
    battery)
        case "$2" in
            BAT0)
                case "$4" in
                    00000000)
                        logger 'Battery online'
                        ;;
                    00000001)
                        logger 'Battery offline'
                        ;;
                esac
                ;;
            CPU0)
                ;;
            *)  logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/lid)
        case "$3" in
            close)
                logger 'LID closed'
                ;;
            open)
                logger 'LID opened'
                ;;
            *)
                logger "ACPI action undefined: $3"
                ;;
    esac
    ;;
    *)
        logger "ACPI group/action undefined: $1 / $2"
        ;;
esac

# vim:set ts=4 sw=4 ft=sh et:

Offline

#11 2012-08-29 13:07:19

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

I'm lost. I put that in my handler.sh, but it still doesn't work:

#!/bin/sh
# Default acpi script that takes an entry for all actions

#minspeed=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`
#maxspeed=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`
#setspeed="/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
STATE=`cat /sys/class/power_supply/AC/online`
FULL_BAT=`cat /sys/devices/platform/smapi/BAT0/energy_full`
CUR_BAT=`cat /sys/devices/platform/smapi/BAT0/energy_now`
AVG=`expr $(expr ${CUR_BAT} \* 100) / ${FULL_BAT}`

set $*

case "$1" in
	battery)
      if [ "$STATE" = "0" ] && [ $AVG -le 75 ]; then
         dbus-send --system --print-reply --dest="org.freedesktop.UPower" /org/freedesktop/UPower org.freedesktop.UPower.Suspend
      fi
      ;;
    button/power)
        case "$2" in
            PBTN|PWRF)
                logger "PowerButton pressed: $2"
                poweroff
                ;;
            *)
                logger "ACPI action undefined: $2"
                ;;
        esac
        ;;
    button/sleep)
        case "$2" in
            SLPB|SBTN)
                echo -n mem >/sys/power/state
                ;;
            *)
                logger "ACPI action undefined: $2"
                ;;
        esac
        ;;
    ac_adapter)
        case "$2" in
            AC|ACAD|ADP0)
                case "$4" in
                    00000000)
                        echo -n $minspeed >$setspeed
                        #/etc/laptop-mode/laptop-mode start
                        ;;
                    00000001)
                        echo -n $maxspeed >$setspeed
                        #/etc/laptop-mode/laptop-mode stop
                        ;;
                esac
                ;;
            *)
                logger "ACPI action undefined: $2"
                ;;
        esac
        ;;
    battery)
        case "$2" in
            BAT0)
                case "$4" in
                    00000000)
                        logger 'Battery online'
                        ;;
                    00000001)
                        logger 'Battery offline'
                        ;;
                esac
                ;;
            CPU0)
                ;;
            *)  logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/lid)
        case "$3" in
            close)
                logger 'LID closed'
                ;;
            open)
                logger 'LID opened'
                ;;
            *)
                logger "ACPI action undefined: $3"
                ;;
    esac
    ;;
    *)
        logger "ACPI group/action undefined: $1 / $2"
        ;;
esac

# vim:set ts=4 sw=4 ft=sh et:

Offline

#12 2012-08-29 14:30:47

punkeroso
Member
From: Rome, Italy
Registered: 2007-01-19
Posts: 105

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Lockheed wrote:

I'm lost. I put that in my handler.sh, but it still doesn't work:

It doesn't work because there is no event that triggers it.
Launch acpi_listen when on battery for 5 minutes and then paste the output here.

Offline

#13 2012-08-29 15:30:13

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

$ acpi_listen
ac_adapter ACPI0003:00 00000080 00000000
processor LNXCPU:00 00000081 00000000
processor LNXCPU:01 00000081 00000000
thermal_zone LNXTHERM:00 00000081 00000000
battery PNP0C0A:00 00000080 00000001
video/brightnessup BRTUP 00000086 00000000 K
video/brightnessup BRTUP 00000086 00000000
processor LNXCPU:00 00000080 00000004
processor LNXCPU:01 00000080 00000004
video/brightnessup BRTUP 00000086 00000000
video/brightnessup BRTUP 00000086 00000000 K
video/brightnessup BRTUP 00000086 00000000
video/brightnessup BRTUP 00000086 00000000 K
video/brightnessup BRTUP 00000086 00000000 K

Offline

#14 2012-08-29 15:36:49

punkeroso
Member
From: Rome, Italy
Registered: 2007-01-19
Posts: 105

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Lockheed wrote:
$ acpi_listen
ac_adapter ACPI0003:00 00000080 00000000
processor LNXCPU:00 00000081 00000000
processor LNXCPU:01 00000081 00000000
thermal_zone LNXTHERM:00 00000081 00000000
battery PNP0C0A:00 00000080 00000001
video/brightnessup BRTUP 00000086 00000000 K
video/brightnessup BRTUP 00000086 00000000
processor LNXCPU:00 00000080 00000004
processor LNXCPU:01 00000080 00000004
video/brightnessup BRTUP 00000086 00000000
video/brightnessup BRTUP 00000086 00000000 K
video/brightnessup BRTUP 00000086 00000000
video/brightnessup BRTUP 00000086 00000000 K
video/brightnessup BRTUP 00000086 00000000 K

You launched acpi_listen and then remove the ac adapter right? As far as I can read, your laptop doesn't trigger any "periodical" event.
Try pasting the output of at least 10 minutes of acpi_listen.

Offline

#15 2012-08-29 16:48:08

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Here's the log started immidiatelly before disconnecting AC. It run about 10 minutes:

$ acpi_listen
ac_adapter ACPI0003:00 00000080 00000000
processor LNXCPU:00 00000081 00000000
processor LNXCPU:01 00000081 00000000
thermal_zone LNXTHERM:00 00000081 00000000
battery PNP0C0A:00 00000080 00000001
battery PNP0C0A:00 00000080 00000001
processor LNXCPU:00 00000080 00000004
processor LNXCPU:01 00000080 00000004
processor LNXCPU:00 00000080 00000000
processor LNXCPU:01 00000080 00000000

Last edited by Lockheed (2012-08-29 16:48:34)

Offline

#16 2012-08-29 17:05:56

punkeroso
Member
From: Rome, Italy
Registered: 2007-01-19
Posts: 105

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Lockheed wrote:

Here's the log started immidiatelly before disconnecting AC. It run about 10 minutes:

$ acpi_listen
ac_adapter ACPI0003:00 00000080 00000000
processor LNXCPU:00 00000081 00000000
processor LNXCPU:01 00000081 00000000
thermal_zone LNXTHERM:00 00000081 00000000
battery PNP0C0A:00 00000080 00000001
battery PNP0C0A:00 00000080 00000001
processor LNXCPU:00 00000080 00000004
processor LNXCPU:01 00000080 00000004
processor LNXCPU:00 00000080 00000000
processor LNXCPU:01 00000080 00000000

It's like I said before: there no way to let acpid hibernate your system when battery is low.
Your laptop doesn't trigger any "useful" event.
You need a daemon that checks every n seconds (minute) the battery status and, in case, hibernate your system.
This daemon could simply be written in bash, for example.

Offline

#17 2012-08-29 17:59:40

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Ha, bummer then.

But I tried this, and it works:

#!/bin/sh
if grep -q 1 /sys/class/power_supply/AC/online; then
  exit 0
fi

AVG=`cat /sys/devices/platform/smapi/BAT0/remaining_percent`

if [ "$AVG" -le "92" ]; then
  hibernate
fi

But how to I make a daemon out of it?

Offline

#18 2012-08-29 18:11:14

punkeroso
Member
From: Rome, Italy
Registered: 2007-01-19
Posts: 105

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Lockheed wrote:

Ha, bummer then.

But I tried this, and it works:

#!/bin/sh
if grep -q 1 /sys/class/power_supply/AC/online; then
  exit 0
fi

AVG=`cat /sys/devices/platform/smapi/BAT0/remaining_percent`

if [ "$AVG" -le "92" ]; then
  hibernate
fi

But how to I make a daemon out of it?

Here is the first result looking for "bash daemon" on google http://blog.apokalyptik.com/2008/05/09/ … ripts-get/

Offline

#19 2012-08-29 18:27:21

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

I haven't found that myself. Looks promissing, but am I supposed to replace "checkforterm" with the script for my battery?

Offline

#20 2012-08-29 18:35:44

punkeroso
Member
From: Rome, Italy
Registered: 2007-01-19
Posts: 105

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Lockheed wrote:

I haven't found that myself. Looks promissing, but am I supposed to replace "checkforterm" with the script for my battery?

Exactly and, if you want, how frequent the daemon should check the battery (sleep 1).

Offline

#21 2012-08-29 18:46:48

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

sleep 1 = 1 second, right?

So, the final result should be something like that?

#!/bin/sh
function payload() {
while [ true ]; do
if grep -q 1 /sys/class/power_supply/AC/online; then
  exit 0
fi

AVG=`cat /sys/devices/platform/smapi/BAT0/remaining_percent`

if [ "$AVG" -le "92" ]; then
  hibernate
fi
date
sleep 1
done
}
source path/to/daemon-functions.sh

Where should I place the finished daemon file? I imagine it supposed to be in some specific location if it's to be run from rc.conf

Offline

#22 2012-11-25 12:48:54

eruditorum
Member
Registered: 2012-11-12
Posts: 130

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

How complicated all this is.
You could just install "acpi" package and then add this to /etc/acpi/handler.sh:

battery)
  if [[ $(acpi|grep "Discharging, 1%") ]]; then
    systemctl hibernate
  fi
;;

This works perfectly for me. You can replace 1% for any remaining charge level you like.

Offline

#23 2012-11-25 14:00:11

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

You are lucky enough to have a laptop which reports battery level to acpi. I am not that lucky.

Offline

#24 2013-02-13 11:21:57

eruditorum
Member
Registered: 2012-11-12
Posts: 130

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Find power supplies in /sys/class/power_supply, inspect their parameters with udevadm info --attribute-walk and write udev rule then.

This for example:

## SLEEP IF BATTERY IS LOW
SUBSYSTEM=="power_supply", ATTR{type}=="Battery", ATTR{status}=="Discharging", ATTR{capacity}=="1", RUN+="/usr/bin/systemctl hibernate"

That way you even don't need acpid at all.

Last edited by eruditorum (2013-02-13 11:26:59)

Offline

#25 2013-02-13 12:18:30

Lockheed
Member
Registered: 2010-03-16
Posts: 1,512

Re: Auto hibernate on low battery W/O laptop-mode or pm-utils

Right, so these are the attributes for /sys/class/power_supply/AC

  looking at device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC':
    KERNEL=="AC"
    SUBSYSTEM=="power_supply"
    DRIVER==""
    ATTR{type}=="Mains"
    ATTR{online}=="1"

  looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00':
    KERNELS=="ACPI0003:00"
    SUBSYSTEMS=="acpi"
    DRIVERS=="ac"
    ATTRS{hid}=="ACPI0003"
    ATTRS{path}=="\_SB_.PCI0.LPC_.EC__.AC__"

  looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00':
    KERNELS=="PNP0C09:00"
    SUBSYSTEMS=="acpi"
    DRIVERS=="ec"
    ATTRS{hid}=="PNP0C09"
    ATTRS{path}=="\_SB_.PCI0.LPC_.EC__"

  looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00':
    KERNELS=="device:00"
    SUBSYSTEMS=="acpi"
    DRIVERS==""
    ATTRS{path}=="\_SB_.PCI0.LPC_"

  looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00':
    KERNELS=="PNP0A08:00"
    SUBSYSTEMS=="acpi"
    DRIVERS=="pci_root"
    ATTRS{hid}=="PNP0A08"
    ATTRS{path}=="\_SB_.PCI0"

  looking at parent device '/devices/LNXSYSTM:00/LNXSYBUS:00':
    KERNELS=="LNXSYBUS:00"
    SUBSYSTEMS=="acpi"
    DRIVERS==""
    ATTRS{hid}=="LNXSYBUS"
    ATTRS{path}=="\_SB_"

  looking at parent device '/devices/LNXSYSTM:00':
    KERNELS=="LNXSYSTM:00"
    SUBSYSTEMS=="acpi"
    DRIVERS==""
    ATTRS{hid}=="LNXSYSTM"
    ATTRS{path}=="\"

The thing is that "ATTR{type}=="Mains" stays as "Mains even on battery, only  ATTR{online}=="1" changes to "0".

How would a dev rule look in this case?

Also, I noticed your rule would kick in only if the battery is at 1%, so if I change it to 3%, it will kick in only if the battery value is at 3, but not below.

Last edited by Lockheed (2013-02-13 12:20:35)

Offline

Board footer

Powered by FluxBB