Wednesday, February 11, 2009

Nerd alarmclock

I bought an Asus Eee 901 recently. One of the first things I thought of having it do was to wake me up in the mornings with an Internet radio station. In principle, this is a really trivial problem:
  1. set an alarm
  2. go to sleep
  3. make a loud noise
The first step is the stumbling block. I'd no idea whether PCs could be woken by their hardware clock. (I had heard of wake-on-LAN: boot on reception of an Ethernet packet.) So I parked the idea pending further information.

Another common use of Linux boxes is as media centres, so it should have come as no surprise when I discovered that a similar problem had been solved by MythTV for an eco-friendly PVR function. (See here.)

The simplest thing that could possibly work began to look a bit like this:
wake=$(date --date="$1" +%s)
sudo sh -c "echo $wake > /sys/class/rtc/rtc0/wakealarm"
sudo /etc/acpi/sleepbtn.sh
/usr/bin/realplay rtsp://live1.rte.ie/redundant/1516.ra
Slightly noteworthy here is:
  1. The rtc driver's wake-up parameter is "seconds since the epoch".
  2. sleepbtn.sh is a Debian-ism; you may have an equivalent.
  3. GNU date has an awesome parser.
  4. (Don't you love that "redundant" in RTE's URL? What are they trying to say, exactly?)
Naturally it wasn't as simple as all that: "in theory there's no difference between theory and practice."

The first problem is that networking is disabled when the machine wakes up which upsets Real Player. (It doesn't fail, it pops up a dialog box, which isn't of very much use to a sleeping user.) A simple sleep works around this one.

A more insidious problem arises from Ubuntu's default ALSA configuration. If a program has the default audio device open when the machine goes to sleep, Real Player will fail to open it when it wakes up. Again it doesn't return a failure status, just prints an error on the console:
ALSA lib pcm_dmix.c:996:(snd_pcm_dmix_open) unable to open slave
ALSA snd_pcm_open error: Device or resource busy

The solution, described here, is to configure a software mixer sitting over the real device. (This also allows you to hear incoming Skype calls while listening to the radio, which is nice.)

So with the addition of some error-checking and a configuration file, setting an alarm clock is now as simple as:
$ /usr/local/bin/wakeup "tomorrow 07:00" radio4
(Admittedly the UI could use some work. Feel free to contribute!)

$ cat ~/.wakeuprc
radio4=http://www.bbc.co.uk/radio4/realplayer/media/fmg2.ram
newstalk=http://newstalk.fmstreams.com:8080
rte1=rtsp://live1.rte.ie/redundant/1516.ra

$ cat /usr/local/bin/wakeup
#!/bin/bash

RC=${HOME}/.wakeuprc

[ $# -ne 2 ] && echo "Usage: " && exit -1
[ ! -f $RC ] && echo "$RC: Not found" && exit -1

. $RC
name=$2
[ "${!name}" == "" ] && echo "Failed to find $name in $RC" && exit 1

wake=$(date --date="$1 +1" +%s)
wake_str=$(date -d @$wake)
now=$(date +%s)
[ $now -gt $wake ] && echo "$wake_str is past!" && exit 1

echo "Will wake at $wake_str"
sudo sh -c "echo > /sys/class/rtc/rtc0/wakealarm"
sudo sh -c "echo $wake > /sys/class/rtc/rtc0/wakealarm"
sudo /etc/acpi/sleepbtn.sh

sleep 45
/usr/bin/realplay ${!name}

1 comment:

Niall Smart said...

Steve, you know they have dedicated hardware for this kind of thing now?