LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   Execute a command when power source changes (https://www.linuxquestions.org/questions/linux-general-1/execute-a-command-when-power-source-changes-809028/)

Virchanza 05-20-2010 03:24 AM

Execute a command when power source changes
 
My laptop has a dead battery. Even when it's fully charged, if the power cable is pulled out it only lasts for about 4 minutes before it dies.

I'm running Ubuntu Lucid Lynx 32-Bit.

What I want to do is create some sort of script or program that will immediately set my computer to go into hibernation once it detects that the power cable has gone dead.

I'm willing to look into all ways of doing this. I can program in C, but I'm not familiar with the API used to manage Power Management in Linux.

I wonder if I could write a simple program something like the following:

Code:

int main(void)
{
    for (;;)
    {
        if ( !IsMainsPowerConnected() )
        {
            CommenceImmediateHibernation();
            sleep(200);
        }

        sleep(30);
    }
}


ozanbaba 05-20-2010 06:59 AM

Code:

#echo disk > /sys/power/state
this will cause the computer to hybernate.

David the H. 05-20-2010 07:51 AM

You can probably use halevt. It's a daemon that monitors hal for system events and lets you configure commands for them.

http://www.nongnu.org/halevt/

I couldn't tell you for sure how to configure it for power supply changes, but you can probably find out by monitoring hal's output with "lshal -m". See their configuration page for more details.

ozanbaba 05-20-2010 11:38 AM

using hal or udev, you should able to run a command in specific conditions. i'm not sure much about how as it's been a while since i did anything with hal or udev.

Virchanza 05-21-2010 08:20 AM

I found a way of figuring out whether the mains cable is plugged in:

Code:

lshal | grep ac.adapter.present
I'm gonna check this value every 30 seconds.

If it's true, I'll do nothing.

If it's false, I'll check it again in another 30 seconds' time. If it's still false, then I'll set the machine to hibernate.

Here's the C code I've got so far:

Code:

#include <stdio.h> /* popen, pclose, fgets */
#include <string.h> /* strchr */
#include <unistd.h> /* sleep */

int Is_AC_Unplugged(void)
{
        char line[200];

        /* Run the command, take one line from it, then close the opened stream */
        FILE *pfile = popen("lshal | grep ac.adapter.present", "r");
        fgets(line, sizeof line, pfile);
        pclose(pfile);

        /* Find the position of the '=' sign in the line of text */
        char const *p = strchr(line,'=');

        if (!p)
        {
            /* Dodgy reading, there's no '=' sign */
            return 0;
        }

        /* Now check for the first 't' or 'f' after the '=' sign */
        for (;;)
        {
            ++p;

            if (!*p)
            {
                /* We've already reached the null terminator, must be a dodgy reading! */
                return 0;
            }

            if (  (*p == 't') || (*p == 'T')  )
            {
                /* The power adapter is plugged in, no need to do anything */
                return 0;
            }
            else if (  (*p == 'f') || (*p == 'F')  )
            {
                /* Oh shit the power adapter is unplugged */
                return 1;
            }
        }
}

void Deal_With_Unplugged_AC_Adapter(void)
{
    puts("We've lost AC power. Now we wait 30 seconds to see if it's still gone.");

    sleep(30);

    if (!Is_AC_Unplugged())
    {
        /* The power must be back, abort the Hibernation */
        puts("Wahey the power's back, no need to hibernate!");
        return;
    }

    /* OK so the power is still gone, let's Hibernate */

    puts("HIBERNATING. . . ");

    /* Insert code here to make computer hibernate */
}

int main(void)
{
    for ( ; ; sleep(30))
    {
        if (Is_AC_Unplugged())
        {
            Deal_With_Unplugged_AC_Adapter();
        }
        else
            puts("We still have AC. . .");
    }
}


David the H. 05-21-2010 09:43 AM

I'm going to repeat my suggestion for halevt again, since you've clearly found the hal event that you need for the trigger. Why go to all the trouble to write your own program when someone has already done it for you?

Besides, I don't believe halevt has to continuously poll your system in order to do it's job; it simply registers and reacts to whatever events hal reports. Plus you have the ability to add more rules to it in the future to do other things if you find the need. I use it to reset my trackball configuration when I hotplug it, for example.


All times are GMT -5. The time now is 03:04 AM.