Roland's homepage

My random knot in the Web

Playing a sound when the battery is low

Although I have a battery indicator on the bottom of my laptop screen I don’t alway check that often enough. That’s why I wanted to add an extra warning in the form of an audio signal. So even if I’m turned away from the laptop, it should still catch my attention.

Playing a sound

There are many methods to generate and play sounds;

  • sndfile-play
  • espeak
  • out123

Note

Music generation is probably a huge magnet for nerds. Going down this path may be a huge time-sink. You have been warned. ;-)

After downloading and playing with some sound themes, I settled on simply using out123 as installed by the mpg123 package.

For a low battery warning, this sounds OK:

out123 --wave-freq 400 --wave-sweep 800 --sweep-count 5 --wave-pat square

This generated sound is pretty loud, so I set the sound volume to an acceptable volume first.

Warning

You do not want to play this at full volume!

So we need to select a reasonable volume before starting the sound. To do that well, we need to save and restore the previous mixer settings. In a shell-script:

#!/bin/sh
VOL=`mixer vol | sed -e 's/^.*://'`
mixer vol 50
out123 --wave-freq 400 --wave-sweep 800 --sweep-count 5 --wave-pat square
mixer vol $VOL

Another method is to use the --preamp option with a negative number, e.g:

out123 --wave-freq 400 --wave-sweep 800 --sweep-count 5 \
--wave-pat square --preamp -20

While this reduces the volume, the final output volume is dependant on the current system mixer settings. Use whatever method suits you best.

Monitoring the battery status

At first, I thought about using devd to monitor the battery. But according to acpi_battery(4) that only signals:

  • 0x80 Battery status was changed.
  • 0x81 Battery information was changed.

So I think I’ll just use cron instead. The sysctl hw.acpi.battery.life reports the remaining charge in the battery in %, while hw.acpi.battery.time reports the projected remaining time in minutes.

Since the time is an estimate, I will use hw.acpi.battery.life and sound the alert when this goes down to 10%.

The latest version of this script can be found in my scripts repo on github.

#!/bin/sh
# file: warn-battery.sh
# Script to sound a warning when the battery becomes low. To be run from cron.
# Requires the audio/mpg123 package.
#
# vim:fileencoding=utf-8:fdm=marker:ft=sh
#
# Copyright © 2020 R.F. Smith <rsmith@xs4all.nl>
# SPDX-License-Identifier: MIT
# Created: 2020-07-12T13:53:59+0200
# Last modified: 2020-07-25T16:54:26+0200

# Locations of binaries.
MIXER=/usr/sbin/mixer
OUT=/usr/local/bin/out123

# Get the battery percentage and state
BAT=`sysctl -n hw.acpi.battery.life`
STATE=`sysctl -n hw.acpi.battery.state`
# Get current sound volume
VOL=`mixer vol | sed -e 's/^.*://'`
if [ $STATE -eq 1 -a $BAT -le 10 ]; then
    # Set sound level and play sound
    $MIXER vol 50 >/dev/null
    $OUT --wave-freq 400 --wave-sweep 800 --sweep-count 5 --wave-pat square
    # Restore sound volume.
    $MIXER vol $VOL >/dev/null
fi

This file is installed in /usr/local/libexec, and by the cron daemon crontab every minute. Below are the lineis in /etc/crontab:

# Warn if battery is low.
*       *       *       *       *       root    /usr/local/libexec/warn-battery

←  Roll back a FreeBSD port with svnlite Writing speed on FreeBSD 12.1-STABLE amd64  →