Friday, September 03, 2010

Shell Scripting for MacOS X: Laundry Timer with Text To Speech Synthesis

I occasionally forget things. Yes, I admit it. In high school, a friend of mine once said that I'd probably forget at home a certain, rear-facing body part if it weren't attached to my body. He was probably right.

In my apartment building, there is a small set of laundry machines: one washer and two dryers. These three machines are to be split between the twelve apartments in the building. It's not a bad amount of machines, except for when people leave things in the machine for extended periods of time. Yes, I have been one of these people. Many apologies to my building mates!

I had a small minute timer that I used to remind me to move the finished laundry. It was nice, super-cheap, portable device that worked very well, at least until it died. Yes, it was ever so slightly tragic, and involved some amount of leaky battery goo. This really shouldn't have been much of a problem, at least in relation to my bad retrieval-of-laundry habits. I could have used one of the other timers in my house, such as the one on the microwave. For a while, that's what I did, except I occasionally missed hearing it, either from being in the wrong room at the wrong time, having headphones on, etc.

This morning, I started trying a slightly different solution. I wrote a simple shell script to tell me when to move my laundry. It started by using the sleep command to wait the proper number of seconds needed for whatever cycle I'd be on (1500 seconds for a wash cycle in my building, 3600 for a dryer load). When the laundry is done, it would use MacOS X's text-to-speech synthesis libraries (via the 'say' command) to verbally announce the machine's completion.

About half an hour of hacking and documentation-searching resulted in the 'laundry' command, along with a better understanding of bash's numeric 'for' loops and math capabilities, among other things.

The 'laundry' command, as it currently exists, takes in a number of minutes as input and then does the following, in order:

  1. prints the current/start time and the amount of time input.
  2. counts down the minutes, waiting as necessary and printing the remaining time along the way.
  3. prints the end time.
  4. over the computer's audio output, it says the word, "Laundry". This is repeated every ten seconds until Ctrl-C is pressed.


For example, given my building's dryers run time of about an hour, I can run the following:

laundry 60


This is roughly what I would see in the terminal (using a smaller wait time of five minutes):


Start Time: Fri Sep 3 20:33:53 EDT 2010
Waiting for 5 minutes (300 seconds).
Press Ctrl-C to exit.
4 minutes left
3 minutes left
2 minutes left
1 minutes left
Done!
End Time: Fri Sep 3 20:33:53 EDT 2010


The complete code is posted below. You can also download it here (use a right-click to save the file). To install it, be sure to mark it as an executable program (via 'chmod +x ~/Downloads/laundry', assuming it's in the common, MacOS X 'Downloads' folder), and also to copy it somewhere in your PATH, such as /usr/local/bin ('sudo mv ~/Downloads/laundry /usr/local/bin'). To note, the last step is purely optional. Not doing so just means you'll have to type in a longer command to run it.


#!/bin/bash
#
# Super-Simple Laundry Timer
# by David Ludwig
#

if [ "$1" == "" ]; then
echo
echo "Usage:"
echo " laundry <time in minutes>"
echo
exit 0
fi

MINUTES=$1
SECONDS=$[$MINUTES * 60]
START_TIME=`date`

echo "Start Time: $START_TIME"
echo "Waiting for $MINUTES minutes ($SECONDS seconds)."
echo "Press Ctrl-C to exit."

for (( i=1; i<=$MINUTES; i++ )); do
sleep 60
MINUTES_LEFT=$[MINUTES - $i]
if [ $MINUTES_LEFT -ne 0 ]; then
echo "$MINUTES_LEFT minutes left"
fi
done

END_TIME=`date`
echo "Done!"
echo "End Time: $END_TIME"

while true; do
say Laundry
sleep 10
done