
CHAPTER 6 ■ DATA SOURCES
208
If you’d prefer for them to go into your traditional Linux mail box, then you can change the path to
the following:
path = /var/mail/steev
You can then retrieve them like this and watch the system download the e-mails:
getmail -r getmail.gmail
Some services, notably Google Mail, do not allow you to download all your e-mails at once if there
are a lot of them. Therefore, you need to reinvoke the command. This helps support the bandwidth of
both machines.
■ Tip If you have only one external mail account, then calling your configuration file getmailrc allows you to omit
the filename arguments.
You can then view these mails in the client of your choice. Here’s an example:
mutt -f ~/externalmail/gmail.mbox
Make sure you let getmail finish retrieving the e-mails; otherwise, you will get two copies of each
mail in your inbox.
If you are intending to process these e-mails with procmail, as you saw in Chapter 5, then you need
to write the incoming e-mail not to the inbox but to procmail itself. This is done by configuring the
destination thusly:
[destination]
type = MDA_external
path = /usr/bin/procmail
unixfrom = True
Twitter
The phenomenon that is Twitter has allowed the general public to morph into self-styled
microcelebrities as they embrace a mechanism of simple broadcast communication from one individual
to a set of many “followers.” Although communications generally remain public, it is possible to create a
list of users so that members of the same family can follow each other in private.
One thing that Twitter has succeeded in doing better than most social sites is that it has not deviated
from its original microblogging ideals, meaning that the APIs to query and control the feeds have
remained consistent. This makes it easy for you (or your house) to tweet information to your feeds or for
the house to process them and take some sort of action based upon it. In all cases, however, you will
have to manually sign up for an account on behalf of your house.

CHAPTER 6 ■ DATA SOURCES
209
Posting Tweets with cURL
The Twitter API uses an HTTP request to upload a new tweet, with the most efficient implementation
being through cURL, the transfer library for most Internet-based protocols, including HTTP.
$host = "http://twitter.com/statuses/update.xml?status=";
$host .= urlencode(stripslashes(urldecode($message)));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $host);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
curl_setopt($ch, CURLOPT_POST, 1);
$result = curl_exec($ch);
curl_close($ch);
This example uses PHP (with php5-curl), but any language with a binding for libcurl works in the
same way. You need only to fill in your login credentials, and you can tweet from the command line.
Reading Tweets with cURL
In the same way that tweets can be written with a simple HTTP request, so can they be read. For
example:
$host = "http://twitter.com/statuses/friends_timeline.xml?count=5";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $host);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
$result = curl_exec($ch);
curl_close($ch);
This returns all the information available regarding the most recent tweets (including your own)
with full information on the user (such as their name, image, and followers count), message, and the in-
reply data (featuring status, user, and screen name). This is more than you’ll generally need, but it’s a
good idea in API design to never lose information if possible—it’s easier to filter out than it is to add back
in. You can use this code to follow tweets when offline by using the computer to intercept suitably
formatted tweets and sending them on with SMS transmit code.

CHAPTER 6 ■ DATA SOURCES
210
Reading Tweets with RSS
The very nature of Twitter lends itself to existing RSS technology, making customized parsers
unnecessary. The URL for the user 1234 would be as follows:
http://twitter.com/statuses/user_timeline/1234.rss
which could be retrieved and processed with XSLT or combined with the feeds from each family
member into one for display on a house notice board. The results here are less verbose than their cURL
counterparts, making it easier to process, at the expense of less contextual information.
Facebook
Although Twitter has adopted a broadcast mechanism, Facebook has continued to focus on the
facilitation of a personal network with whom you share data. For HA, you are probably more interested
in sharing information with friends than strangers, so this can be the better solution. However, writing
an app that uses Facebook has a higher barrier to entry with comparatively little gain. It does, by way of
compensation, provide a preexisting login mechanism and is a web site that many people check more
often than their e-mail, so information can be disseminated faster. However, Facebook does change its
API periodically, so what works one day might not work the next, and you have to keep on top of it. If you
are using Facebook as a means of allowing several people to control or view the status of your home, it is
probably easier to use your own home page, with a set of access rights, as you saw in Chapter 5.
If you’re still sold on the idea of a Facebook, then you should install the Developer application and
create your own app key with it. This will enable your application to authenticate the users who will use
it, either from within Facebook or on sites other than Facebook through Facebook Connect. (A good
basic tutorial is available at www.scribd.com/doc/22257416/Building-with-Facebook-Social-Dev-Camp-
Chicago-2009.) To keep it private amongst your family, simply add their ID as developers. If you want to
share information with your children, getting them to accept you as a Facebook friend can be more
difficult, however! In this case, you might have to convince them to create a second account, used solely
for your benefit. Facebook doesn’t allow you to send messages to users who haven’t installed the app (or
are included in the list of developers), so this requires careful management.
The technical component is much simpler, by comparison, because Facebook provides standard
code that can be copied to a directory on your web server and used whenever your app is invoked from
within Facebook. It is then up to you to check the ID of the user working with your app to determine
what functionality they are entitled to and generate web pages accordingly. You can find a lot of useful
beginning information on Facebook’s own page at http://developers.facebook.com/get_started.php.
Automation
With this information, you have to consider how it will be used by the house. This requires development
of a most personal nature. After all, if you are working shifts, then my code to control the lights according
to the times of sunrise and sunset will be of little use to you. Instead, I will present various possibilities
and let you decide on how best to combine them.

CHAPTER 6 ■ DATA SOURCES
211
Timed Events
Life is controlled by time. So, having a mechanism to affect the house at certain times is very desirable.
Since a computer’s life is also controlled by time, there are procedures already in place to make this task
trivial for us.
Periodic Control with Cron Jobs
These take their name from the chronological job scheduler of Unix-like operating systems, which
automatically executes a command at given times throughout the year. There is a file, known as the
crontab, which has a fine level of granular control regarding these jobs, and separate files exist for each
user. You can edit this file belonging to the current user (calling export EDITOR=vi first if necessary) with
the following:
crontab -e
There is also a –u option that allows root to edit the crontab of other users. A typical file might begin
with the following:
# m h dom mon dow command
00 7 * * 1-5 /usr/local/minerva/etc/alarm 1
10,15 7 * * 1-5 /usr/local/minerva/etc/alarm 2
*/5 * * * * /usr/local/bin/getmail --quiet
The # line is a comment and acts as a reminder of the columns; minutes, hours, day of month (from
1 to 31), month (1 to 12, or named by abbreviation), day of week (0 to 7, with Sunday being both 0 and 7),
and the command to be executed. Each column supports the use of wildcards (* means any), inclusive
ranges (1–5), comma-delimited sequences (occurring at 10 and 15 only), and periodic (*/5 indicates
every five minutes in this example). The cron program will invoke the command if, and only if, all
conditions can be met.
Typical uses might be as follows:
• An alarm clock, triggering messages, weather reports, or news when waking up
• Retrieving e-mail for one or more accounts, at different rates
• Initiating backups of local data, e-mail, or projects
• Controlling lights while on holiday
• Controlling lights to switch on, gradually, when waking up
• Real-life reminders for birthdays, anniversaries, Mother’s Day, and so on
Since these occur under the auspices of the user (that is, owner) of the crontab, suitably permissions
must exist for the commands in question.

CHAPTER 6 ■ DATA SOURCES
212
■ Note Many users try to avoid running anything as root, if it is at all possible. Therefore, when adding timed
tasks to your home, it is recommended you add them to the crontab for a special myhouse user and assign it only
the specific rights it needs.
The crontab, as provided, is accurate to within one minute. If you’re one of the very few people who
need per-second accuracy, then there are two ways of doing it. Both involve triggering the event on the
preceding minute and waiting for the required number of seconds. The first variation involves changing
the crontab to read as follows:
00 7 * * 1-5 sleep 30; /usr/local/minerva/etc/alarm 1
The second involves adding the same sleep instruction to the command that’s run. This can be
useful when controlling light switches in a humanistic way, since it is rare to take exactly 60 seconds to
climb the stairs before turning the upstairs light on.
For randomized timing, you can sleep for a random amount of time (sleep `echo
$((RANDOM%60))s`) before continuing with the command, as you saw in Chapter 1.
There will also be occasions where you want to ignore the cron jobs for a short while, such as
disabling the alarm clock while we’re on holiday. You can always comment out the lines in the crontab
to do this or change the command from this:
/usr/local/minerva/etc/alarm 1
to the following:
[ -f ~/i_am_on_holiday ] || /usr/local/minerva/etc/alarm 1
The first expression checks for the existence of the given file and skips the alarm call if it exists. Since
this can be any file, located anywhere, it doesn’t need to belong to the crontab owner for it to affect the
task. One possible scenario would be to use Bluetooth to watch for approaching mobile devices, creating
a file in a specific directory for each user (and deleting it again, when they go out of range, that is, have
left the house). Once everyone was home, a cron job set to check this directory every minute could send
an e-mail reminding you to leave the computer and be socialable!
For more complex timing scenarios, you can use cron to periodically run a separate script, say every
minute. If you return to the “next train” script from earlier, you could gain every last possible minute at
home by retrieving the first suitable train from here:
NEXT_TRAIN=`whattrain.pl 30 35 | head -n 1`
In this scenario, a suitable train is one that leaves in 30 to 35 minutes, which gives you time to get
ready. If this command produces an output, then you can use the speech synthesizer to report it:
if [ `echo $NEXT_TRAIN | wc -l` -ne 0 ]; then
say default $NEXT_TRAIN
fi
The same script could be used to automatically vary the wake-up time of your alarm clock!

