Write your own alarm clock

I finally got fed up with my store bought alarm clock. It just wasn’t smart enough. It didn’t understand the difference between weekdays and week nights, and every time I forgot to turn it off before going to bed on a Friday yielded a most unpleasant experience when it started blaring on Saturday morning. Likewise, there were bad ramifications for forgetting to turn it back on on Sunday night. And the sound it made when it went off was terribly annoying and not at all a good way to start the day. So I realized I could do better, and did.

One of my servers is within earshot of where I sleep. It has an internal PC speaker. So I made a simple shell script to output beeps in an aesthetically pleasing (for an alarm clock, anyway) manner and set up a cronjob so that it would run every weekday at 9:00am. No more having to worry about setting my alarm!

The entry in crontab is easy enough to understand. Let’s have a look at it:

0 9 * * Mon-Fri cyde sh /home/cyde/scripts/alarm.sh

As you can see, this runs on the zeroth minute of the ninth hour of every weekday. I’m running Ubuntu 7.04 on this server, and the way to make crontab entries in Ubuntu is to put the line in a text file inside of /etc/cron.d/. I named the file /etc/cron.d/alarm, naturally. The version of crond I’m running supports a field (set to cyde) to specify which user account to run the command under; if your cron daemon doesn’t support this field, simply take it out. And of course, /home/cyde/scripts/alarm.sh is the location of the following script:

#!/bin/sh
#    This program "alarm.sh" is Copyright 2007 Ben "Cyde Weys" McIlwain.
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Configuration
INDNUM=2
MAXFREQ=8000
MINFREQ=1000
STEP=500
LENGTH=25
DELAY=0
REPS=3

LOOP=0
while [ "$LOOP" -lt "$REPS" ]
  do
  I=$MAXFREQ
  while [ "$I" -gt "$MINFREQ" ]
    do
    beep -r $INDNUM -f $I -l $LENGTH -d $DELAY
    I=`expr "$I" - "$STEP"`
  done
  I=$MINFREQ
  while [ "$I" -lt "$MAXFREQ" ]
    do
    beep -r $INDNUM -f $I -l $LENGTH -d $DELAY
    I=`expr "$I" + "$STEP"`
  done
  LOOP=`expr "$LOOP" + 1`
  beep -r 5 -f 2000 -d 200
  beep -r 5 -f 2100 -d 200
  beep -r 5 -f 2000 -d 200
  beep -r 5 -f 2100 -d 200
  sleep 10
done

The loops and such are basic shell script control structures, and I won’t bother covering them here. Check out a general Shell Script Tutorial if you need help with them. What is of interest here is the beep command. I’m using four different command-line parameters to beep in this script. Let’s examine them in turn:

  • -r is the number of repetitions. So -r 5 would mean five beeps.
  • -f is the frequency of the beep to be emitted, in Hertz (Hz). I will admit, I’m not really a music person. All I know is that each octave is a range of frequencies such that the highest note in the octave has twice the frequency of the lowest note. There are twelve notes in an octave. I primarily use the range 2000 – 2200 Hz because my computer’s internal speaker seems to be optimized to output at that frequency range. All of the other notes come out at much lower volume.
  • -d is the delay between beeps, in milliseconds. This only matters if you are using the -r parameter to sound more than one beep.
  • -l is the length of each beep, in milliseconds. Pretty self-explanatory.

There are other parameters you may be interested in: for example, -D creates a delay after each note, not merely between notes, and -n allows you to string multiple different sets of notes and frequencies into a single call to beep. Consult the man page for details.

So that’s my alarm script. If you want to know what it sounds like, well, you’ll have to run it and find out! Try experimenting with the variables defined at the top of the program to mess around with the sound. And if you’re more musically ambitious than I am, you could program up an entire song as an alarm.

8 Responses to “Write your own alarm clock”

  1. arensb Says:

    This suggests all sorts of improvements. This is definitely a project with hack value.

    If you’re going to write a smart alarm clock, I’d say one thing that’s missing is holidays. This year, Christmas falls on a Tuesday, which means you run the risk of forgetting to turn it off on the 24th and not get to sleep in.

    One way of dealing with this might be to have a table of holidays, and have the script consult it. Another might be to have a .noalarm file in your home directory whose presence says not to run the alarm clock (kind of the way /etc/nologin says not to allow logins).

    Another possibility might be to have different alarm times for different days, e.g., 9:00 for weekdays, and noon for weekends. The obvious way to do it is to run the script every 15 minutes, and have it check its config to see whether it’s time to beep or not.

    An easier improvement might be to play a sound file instead of beeping, if you prefer waking up to music. If you wanted to get ultra-fancy, you could use Audacity to generate some fancy alarm tones.

    Or instead of music, you could download the latest news podcast from your favorite news source, and play that.

  2. Cyde Weys Says:

    You’re right, there are all sorts of possible improvements to this script. I would only seriously start working on them if nobody else had already written such an app, and I find it hard to believe that nobody’s written a simple alarm clock daemon for GNU/Linux. So many people live with computers now, it just seems obvious. I’ll have to look around and see if there is anything worthwhile.

    The first obvious change would be to switch to using a proper soundsystem rather than the internal PC speaker. That would allow the use of all sorts of nice-sounding ogg alarms, as well as, as you pointed out, podcasts. It would definitely work better on laptops too. My laptop doesn’t have an internal PC speaker. That output is routed, through hardware, to the standard external speakers, but it only uses a single tone no matter what frequency I tell beep to output at. So the script I’ve published here sounds hideous.

  3. Cyde Weys Says:

    Okay, so upon very preliminary searching, I found a program called KAlarm for KDE. There’s lots of other stuff like it for X11 in general and other window managers in particular. The problem is that it runs as a KDE app. What we really need is something that runs as a system daemon and can even run on a headless server. All it would need is speakers attached to it (or an internal PC speaker for primitive mode). It shouldn’t stop working simply because you aren’t logged into X11.

  4. arensb Says:

    Of course, what it really needs, from my perspective, is a snooze button, one that can be groped for and slapped hard. Not sure how to implement that.

  5. Cyde Weys Says:

    Yeah, I don’t know how a snooze button would work either. My current script used to have ten iterations, rather than three, and I’d turn it off in the morning by logging in, running a ps, and killing the process. Obviously not the best way, but hey, at least you know you’re awake. A better way would be to log the pid of the alarm process in a text file and have a script aliased to “off” that sends a signal to shut down to that process. That way, you’d just have to type “off” at the command line to kill the alarm. But I just took the lazy route and set the number of iterations to three; I always seem to get up on the first few notes anyway, and it’s easier to just let it run out.

    Having a real snooze button would be nice though. I’d bet we can buy a USB button somewhere out there for less than $10. It could just be a simple mushroom cap design (you know, like those emergency off switches). Even if it didn’t have Linux drivers for it, I bet they couldn’t be too hard to write; after all, the button does only have two possible states. It definitely sounds doable.

  6. arensb Says:

    I’d bet we can buy a USB button somewhere out there for less than $10.

    I’ve seen big red buttons on sale at some office store that say “easy”. I wonder how hard it would be to retrofit one of those with, say, a serial cable that drops (or raises) carrier when the button is pressed. Or something.

    Another feature that I’d like to see in an alarm clock is the ability to say “Yeah, I know you’re supposed to go off in 15 minutes, but I’m already up, so don’t bother.”

    As for not making it too easy to turn off the alarm clock: I remember reading about some guy who did essentially the same thing as you. But his alarm clock ran as a daemon, and had the time hardcoded in, so that he couldn’t just edit a config file and go back to sleep. But by and by, it got to the point where he would get up, kill the beeping alarm, edit the source, change the wake-up time, recompile, relaunch, and go back to sleep.

  7. Cyde Weys Says:

    Here’s a suitable button. It launches an application when pushed, but I’m sure it’d be pretty easy to write up some free software drivers that would merely detect a button push (might as simple as sniffing for any IO activity at all).

    The feature to turn the alarm clock off before it goes off is definitely something I find lacking in real alarm clocks. It’s like alarm clocks assume that it’s not possible the person will wake up ahead of hte time it’s set for.

    And, yeah, we definitely need a config file in /etc/alarm.conf or something (in addition to the button that turns the alarm off). Things could go pretty wrong if you had to edit, recompile, and restart a program in a sleep-addled state of mind.

  8. Rudie Says:

    To build a USB or serial button would be easy, mail me I will send schematics and code 4 all who would like to build it. It will probly cost to much for me to fedex it from South Africa, but will do it if needed.

    Regards
    Rudie