Sound for battery charged/decharged

39 replies [Last post]
Matsetes

I am a translator!

Offline
Joined: 12/04/2011

Is there a possibility to execute a sound when the battery of the notebook is fully charged or it's critical? When I'm not looking at the monitor it's difficult to control everytime the charge of the battery.,,

lembas
Offline
Joined: 05/13/2010

There could be some more integrated way of doing it but you could write a bash script to check it for you via sysfs every now and then, e.g.

echo "`cat /sys/bus/acpi/drivers/battery/PNP0C0A:00/power_supply/BAT1/status` battery at $((100*`cat /sys/class/power_supply/BAT1/charge_now`/\
`cat /sys/class/power_supply/BAT1/charge_full`))%"

would produce an output like "Discharging battery at 96%" at the terminal. Then you'd need a loop for the repetition and then to figure out how you'd like to play out the sound exactly. (The exact paths could vary for your hardware.)

Bash scripting is "programming for the non-programmer" and can yet be fairly powerful.

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

You do not need a loop. You only need to set a crontab calling the script every minute. To do so, you execute 'crontab -e' and add a line to the opened file. This line would be "* * * * * ~/bin/bat.sh" if the path to the script is ~/bin/bat.sh.

Then the script you propose can easily be modified to play a sound once a certain threshold is exceeded:
#!/bin/sh
DISCHARGE_THRES=.1
DISCHARGE_ALERT=/usr/share/sounds/gnome/default/alerts/bark.ogg
CHARGE_THRES=.9
CHARGE_ALERT=/usr/share/sounds/gnome/default/alerts/drip.ogg
PLAYER=mplayer
now=`cat /sys/class/power_supply/BAT1/charge_now`
full=`cat /sys/class/power_supply/BAT1/charge_full`
if [ `cat /sys/bus/acpi/drivers/battery/PNP0C0A:00/power_supply/BAT1/status` = Discharging ]
then
if [ `echo "$now / $full < $DISCHARGE_THRES" | bc -l` = 1 ]
then
$PLAYER $DISCHARGE_ALERT
fi
else
if [ `echo "$now / $full > $CHARGE_THRES" | bc -l` = 1 ]
then
$PLAYER $CHARGE_ALERT
fi
fi

I have not tested it but you see the idea. Of course, you will want to change the content of the variables in capital letters so that it corresponds to what you wish.

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

You do not need a loop. You only need to set a crontab calling the script
every minute. To do so, you execute 'crontab -e' and add a line to the opened
file. This line would be "* * * * * ~/bin/bat.sh" if the path to the script
is ~/bin/bat.sh.

Then the script you propose can easily be modified to play a sound once a
certain threshold is exceeded:
#!/bin/sh
DISCHARGE_THRES=.1
DISCHARGE_ALERT=/usr/share/sounds/gnome/default/alerts/bark.ogg
CHARGE_THRES=.9
CHARGE_ALERT=/usr/share/sounds/gnome/default/alerts/drip.ogg
PLAYER=mplayer
now=`cat /sys/class/power_supply/BAT1/charge_now`
full=`cat /sys/class/power_supply/BAT1/charge_full`
if [ `cat /sys/bus/acpi/drivers/battery/PNP0C0A:00/power_supply/BAT1/status`
= Discharging ]
then
if [ `echo "$now / $full < $DISCHARGE_THRES" | bc -l` = 1 ]
then
$PLAYER $DISCHARGE_ALERT
fi
else
if [ `echo "$now / $full > $CHARGE_THRES" | bc -l` = 1 ]
then
$PLAYER $CHARGE_ALERT
fi
fi

I have not tested it but you see the idea. Of course, you will want to change
the content of the variables in capital letters so that it corresponds to
what you wish.

lembas
Offline
Joined: 05/13/2010

Hey Banana!

Removing the loop part sounds good!

I'm not familiar with cron but decided to give it a spin. However, it didn't
seem to work and so I checked the logs. It keeps saying for me

error (grandchild #18551 failed with exit status 1)

The test script in question was
#!/bin/sh
/bin/date +%R|/usr/bin/osd_cat -d 2 -A right -i 60 -f "-*-bitstream
charter-*-*-*-*-44-*-*-*-*-*-*-*"

It works when I run it from the terminal. You wouldn't happen to know what's
wrong?

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

Thanks a lot! I'm waiting for the fixing of the code and I will test it =)

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

Something that was wrong for sure was the use of Shell tests with floating-point numbers. The Shell does not handle such numbers. I changed the script above so that it calls 'bc -l'... but I still have not tested it!

EDIT: working with percentages, like lembas proposed in the first, placed works as well.

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

Thanks, I hope you'll can reach a solution =)

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

That is no fun if I do the whole work (but maybe it is already all done). You can finish the work and learn on the way. :-) Here is a good material to write Bash scripts: http://tldp.org/LDP/abs/html/

At least you can try to run the script and report the problems you encounter. Moreover, it seems like different batteries have different interfaces to access their states. Or maybe it is due to differences in the kernel versions. lembas accesses the relevant values by taking a look at /sys/class/power_supply/BAT1/charge_now and /sys/class/power_supply/BAT1/charge_full, whereas I need to access /sys/class/power_supply/BAT1/energy_now and /sys/class/power_supply/BAT1/energy_full (and, after making this change, the script seems to work for me).

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

I'm not good at all with programming, I've tried to insert the code you
posted. The first one. Now I'm trying to control it...

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

You need to copy/paste it in a file (using a text editor such as GEdit) and make this file executable. This latter part can be done via the file browser ("accessing" the permissions through the "properties" of the file) but that is easier to explain it with a command line:
$ chmod +x PATH_TO_FILE
You obviously need to replace PATH_TO_FILE by the path to the file. For instance, if the code was copied into a file is named "bat.sh" that is in a "bin" directory of your home folder; then PATH_TO_FILE is ~/bin/bat.sh (although you can simply use the so-called "relative path" bin/bat.sh since you are in ~ when the terminal has just been opened). Then, executing the file is simply writing its path.

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

I tried all the day, now the script is ok, but when i put the command on the
crontab it does not execute it automatically... Manually it works, with the
crontab no.
* * * * * /bin/bat
Is the code that I inserted. I've effaced the .sh extention, cause #bash they
said me that...
The code in bat is pretty the same of the one posted here.,,

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

On POSIX systems, the file extensions only are a convenience (some high-level applications use it). Contrary to Windows, they do not play any fundamental role. In other words, you can remove the ".sh" but you can keep it as well.

Have you placed the file (without the extension) into /bin? This means in the bin directory at the root of the file hierarchy. This is a place where are located the essentials binaries and you should not mess with it. I believe you actually put the script in a bin directory under your home folder. If I am right, its path is ~/bin/bat and not /bin/bat and it is only about adding one character in the crontab.

Something else to be careful about: there must be an empty line at the end of the crontab.

lembas
Offline
Joined: 05/13/2010

Have you checked your syslog?

(/var/log/syslog)

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

mplayer: Symbol `ff_codec_bmp_tags' has different size in shared object,
consider re-linking
MPlayer 1.0rc4-4.5.2 (C) 2000-2010 MPlayer Team
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.

Playing /usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg.
libavformat file format detected.
[lavf] stream 0: audio (vorbis), -aid 0
==========================================================================
Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders
AUDIO: 44100 Hz, 2 ch, s16le, 112.0 kbit/7.94% (ratio: 14000->176400)
Selected audio codec: [ffvorbis] afm: ffmpeg (FFmpeg Vorbis)
==========================================================================
AO: [pulse] Init failed: Too large
Failed to initialize audio driver 'pulse'
[AO_ALSA] alsa-lib: pcm_pulse.c:734:(pulse_prepare) PulseAudio: Unable to
create stream: Too large

[AO_ALSA] Unable to set hw-parameters: Input/output error
Failed to initialize audio driver 'alsa'
[AO SDL] Samplerate: 44100Hz Channels: Stereo Format s16le
[AO SDL] using aalib audio driver.
[AO SDL] Unable to open audio: No available audio device
Failed to initialize audio driver 'sdl:aalib'
Could not open/initialize audio device -> no sound.
Audio: no sound
Video: no video

Exiting... (End of file)

The script I made was:

#!/bin/sh
DISCHARGE_THRES=0.1
CHARGE_THRES=1.0
now=`cat /sys/class/power_supply/BAT0/charge_now`
full=`cat /sys/class/power_supply/BAT0/charge_full`
if [ `echo "$now / $full < $DISCHARGE_THRES" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/ubuntu/stereo/desktop-login.ogg
else
if [ `echo "$now / $full == $CHARGE_THRES" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg
fi
fi

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

As far as I understand this log of mplayer, no sound is played (missing codec?)... but since you wrote, in another post, that everything is OK, I believe you fixed this issue.

As for the charge threshold, I am not sure the ratio 1 (that is to say, the battery is full) is always reached because, along its life, the battery looses capacity. However, I may be wrong. Have you tested? If it works, the second "if" could simply be "if [ $now = $full ]" (but, obviously, it does not allow you to simply change your mind about the charge threshold).

Because you remove the test "if [ `cat /sys/bus/acpi/drivers/battery/PNP0C0A:00/power_supply/BAT1/status` = Discharging ]", a sound will be played if the battery is charging but is still below 10% (or if it is discharging but is still full).

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

No, codec are ok...
The battery loses capacity, but the "charge_full" file keep traks of that.
The full charge that whas in origin is in "charge_full_design" file.
I don't know what I have to fix... I cannot understand the problem that gave
me mplayer...

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

I solved it!!!! Wow!
The problem was with the crontab... The "bat" file was not marked as
executable and so the crontab wasn't able to execute it. Now the file is:

#!/bin/sh
DISCHARGE_THRES=.1
now=`cat /sys/class/power_supply/BAT0/charge_now`
full=`cat /sys/class/power_supply/BAT0/charge_full`
if [ `echo "$now / $full < $DISCHARGE_THRES" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/matsetes/hello.wav
else
if [ `echo "$now == $full" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/matsetes/mario.mp3
fi
fi

I tried it one time (both cases: charged and discharged) and it works, I have
only to insert the control of the discharging status, now also when it's
charging, if it's under 10% it continue making the sound every minute. =)

lembas
Offline
Joined: 05/13/2010

Hey Banana!

Removing the loop part sounds good!

I'm not familiar with cron but decided to give it a spin. However, it didn't seem to work and so I checked the logs. It keeps saying for me

error (grandchild #18551 failed with exit status 1)

The test script in question was
#!/bin/sh
/bin/date +%R|/usr/bin/osd_cat -d 2 -A right -i 60 -f "-*-bitstream charter-*-*-*-*-44-*-*-*-*-*-*-*"

It works when I run it from the terminal. You wouldn't happen to know what's wrong?

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

Well, I do not even know "osd_cat"!

lembas
Offline
Joined: 05/13/2010

osd_cat is a program for displaying text or a very simple progress bar on top of X. (on screen display cat) Kinda like notify-send or aosd_cat, xmessage and what not. It's from the package xosd-bin. I realize this is off topic however.

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

Well, I would try something simpler to first check whether the crontab works. For instance... playing a sound (since that is part of the solution you are searching for). That could be a line like that:
* * * * * aplay /usr/share/sounds/card_shuffle.wav

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

Well, I would try something simpler to first check whether the crontab works.
For instance... playing a sound (since that is part of the solution you are
searching for). That could be a line like that:
* * * * * aplay /usr/share/sounds/card_shuffle.wav

lembas
Offline
Joined: 05/13/2010

osd_cat is a program for displaying text or a very simple progress bar on top
of X. (on screen display cat) Kinda like notify-send or aosd_cat, xmessage
and what not. It's from the package xosd-bin. I realize this is off topic
however.

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

Well, I do not even know "osd_cat"!

lembas
Offline
Joined: 05/13/2010

I found out what was wrong with my test script, actually 2 things. I had to

1) escape % (add a lovely little \ right before it)
2) define the DISPLAY variable (cron has different environment)

So, the working scripts is
#!/bin/sh
export DISPLAY=:0
/bin/date +\%R|/usr/bin/osd_cat -d 2 -A right -i 60 -f "-*-bitstream charter-*-*-*-*-44-*-*-*-*-*-*-*"

Just in case I wasn't the only one bugged by this. Glad to hear Matsetes got the original issue sorted.

lembas
Offline
Joined: 05/13/2010

I found out what was wrong with my test script, actually 2 things. I had to

1) escape % (add a lovely little \ right before it)
2) define the DISPLAY variable (cron has different environment)

So, the working scripts is
#!/bin/sh
export DISPLAY=:0
/bin/date +\%R|/usr/bin/osd_cat -d 2 -A right -i 60 -f "-*-bitstream
charter-*-*-*-*-44-*-*-*-*-*-*-*"

Just in case I wasn't the only one bugged by this. Glad to hear Matsetes got
the original issue sorted.

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

Thanks a lot! I'm waiting for the fixing of the code and I will test it =)

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

Something that was wrong for sure was the use of Shell tests with floating-point numbers. The Shell does not handle such numbers. I changed the script above so that it calls 'bc -l'... but I still have not tested it!

EDIT: working with percentages, like lembas proposed in the first, placed works as well.

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

Thanks, I hope you'll can reach a solution =)

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

That is no fun if I do the whole work (but maybe it is already all done). You
can finish the work and learn on the way. :-) Here is a good material to
write Bash scripts: http://tldp.org/LDP/abs/html/

At least you can try to run the script and report the problems you encounter.
Moreover, it seems like different batteries have different interfaces to
access their states. lembas' requires to take a look at
/sys/class/power_supply/BAT1/charge_now and
/sys/class/power_supply/BAT1/charge_full while mine is to accessed through
/sys/class/power_supply/BAT1/energy_now and
/sys/class/power_supply/BAT1/energy_full (and, after making this change, the
script seems to work for me).

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

I'm not good at all with programming, I've tried to insert the code you posted. The first one. Now I'm trying to control it...

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

You need to copy/paste it in a file (using a text editor such as GEdit) and
make this file executable. This latter part can be done via the file browser
("accessing" the permissions through the "properties" of the file) but that
is easier to explain it with a command line:
$ chmod +x PATH_TO_FILE
You obviously need to replace PATH_TO_FILE by the path to the file. For
instance, if the code was copied into a file is named "bat.sh" that is in a
"bin" directory of your home folder; then PATH_TO_FILE is ~/bin/bat.sh
(although you can simply use the so-called "relative path" bin/bat.sh since
you are in ~ when the terminal has just been opened). Then, executing the
file is simply writing its path.

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

I tried all the day, now the script is ok, but when i put the command on the crontab it does not execute it automatically... Manually it works, with the crontab no.
* * * * * /bin/bat
Is the code that I inserted. I've effaced the .sh extention, cause #bash they said me that...
The code in bat is pretty the same of the one posted here.,,

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

On POSIX systems, the file extensions only are a convenience (some high-level
applications use it). Contrary to Windows, they do not play any fundamental
role. In other words, you can remove the ".sh" but you can keep it as well.

Have you placed the file (without the extension) into /bin? This means in the
bin directory at the root of the file hierarchy. This is a place where are
located the essentials binaries and you should not mess with it. I believe
you actually put the script in a bin directory under your home folder. If I
am right, its path is ~/bin/bat and not /bin/bat and it is only about adding
one character in the crontab.

Something else to be careful about: there must be an empty line at the end of
the crontab.

lembas
Offline
Joined: 05/13/2010

Have you checked your syslog?

(/var/log/syslog)

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

Edit: the script now is not running, it says to me

mplayer: Symbol `ff_codec_bmp_tags' has different size in shared object, consider re-linking
MPlayer 1.0rc4-4.5.2 (C) 2000-2010 MPlayer Team
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.

Playing /usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg.
libavformat file format detected.
[lavf] stream 0: audio (vorbis), -aid 0
==========================================================================
Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders
AUDIO: 44100 Hz, 2 ch, s16le, 112.0 kbit/7.94% (ratio: 14000->176400)
Selected audio codec: [ffvorbis] afm: ffmpeg (FFmpeg Vorbis)
==========================================================================
AO: [pulse] Init failed: Too large
Failed to initialize audio driver 'pulse'
[AO_ALSA] alsa-lib: pcm_pulse.c:734:(pulse_prepare) PulseAudio: Unable to create stream: Too large

[AO_ALSA] Unable to set hw-parameters: Input/output error
Failed to initialize audio driver 'alsa'
[AO SDL] Samplerate: 44100Hz Channels: Stereo Format s16le
[AO SDL] using aalib audio driver.
[AO SDL] Unable to open audio: No available audio device
Failed to initialize audio driver 'sdl:aalib'
Could not open/initialize audio device -> no sound.
Audio: no sound
Video: no video

Exiting... (End of file)

The script I made was:

#!/bin/sh
DISCHARGE_THRES=0.1
CHARGE_THRES=1.0
now=`cat /sys/class/power_supply/BAT0/charge_now`
full=`cat /sys/class/power_supply/BAT0/charge_full`
if [ `echo "$now / $full < $DISCHARGE_THRES" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/ubuntu/stereo/desktop-login.ogg
else
if [ `echo "$now / $full == $CHARGE_THRES" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg
fi
fi

Magic Banana

I am a member!

I am a translator!

Offline
Joined: 07/24/2010

As far as I understand this log of mplayer, no sound is played (missing
codec?)... but since you wrote, in another post, that everything is OK, I
believe you fixed this issue.

As for the charge threshold, I am not sure the ratio 1 (that is to say, the
battery is full) is always reached because, along its life, the battery
looses capacity. However, I may be wrong. Have you tested? If it works, the
second "if" could simply be "if [ $now = $full ]" (but, obviously, it does
not allow you to simply change your mind about the charge threshold).

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

No, codec are ok...
The battery loses capacity, but the "charge_full" file keep traks of that. The full charge that whas in origin is in "charge_full_design" file.
I don't know what I have to fix... I cannot understand the problem that gave me mplayer...

Matsetes

I am a translator!

Offline
Joined: 12/04/2011

I solved it!!!! Wow!
The problem was with the crontab... The "bat" file was not marked as executable and so the crontab wasn't able to execute it. Now the file is:

#!/bin/sh
DISCHARGE_THRES=.1
now=`cat /sys/class/power_supply/BAT0/charge_now`
full=`cat /sys/class/power_supply/BAT0/charge_full`
if [ `echo "$now / $full < $DISCHARGE_THRES" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/matsetes/hello.wav
else
if [ `echo "$now == $full" | bc -l` = 1 ]
then
mplayer /usr/share/sounds/matsetes/mario.mp3
fi
fi

I tried it one time (both cases: charged and discharged) and it works, I have only to insert the control of the discharging status, now also when it's charging, if it's under 10% it continue making the sound every minute. =)