Posted on 13 July 2012
While @ouroffice, the place I currently reside, already had a twitter account for a long time, up until now it was operated exclusively by humans. But no more! A few weeks ago, I decided to put my brand-new raspberry pi to good use and write a small notification daemon that constantly checks who is at the office and lets the world know about that, over Twitter.
So, as a nice friday-afternoon project, I set out to do just that: writing a service that keeps track of who of the @ouroffice residents come in, and send out a tweet accordingly. Since the program would be a daemon, I decided to use Erlang for it. (and also, of course, because Erlang is the coolest language out there, well suited for writing rock-solid servers.)
Basically I have a mapping from ethernet hardware address to user name, stored in a configuration file, like a dictionary. The server constantly pings its subnet to see which computers are online, using an nmap ping scan: nmap -sP 192.168.10.0/24. That gives me a list of IP addresses, each of which I query using arp to get the actual hardware address connected to the ip address. And using the mapping, I know which hardware address belongs to whom of my co-workers. If the server spots a user that it has not seen before, it will pick a random tweet message (based on the time of the day) and tweet it to the @ouroffice account.
(reality is actually a bit more complicated than this, because a ping does not always arrive reliably, so I keep a timer for each user and give them some time to show up again, before I mark somebody as “offline”, but hey, those are implementation details).
With Erlang and its OTP design principle, the idea is that you structure your code in an application, consisting of supervised worker threads (called processes) each of which performs its own, dedicated function, unhindered by and isolated from other things happening in parallel.
So my application is called ouroffice, and consists of three worker processes, ouroffice_scanner, ouroffice_logic, and ouroffice_notifier. Like you see in the image, these three are supervised by the ouroffice_sup process, which makes sure that whenever one of them fails, for whatever reason, it will be neatly restarted.
The ouroffice_scanner process does the hard work: periodically calling nmap and arp to update its dictionary of timer structures. When a new entry is added to the dictionary, it means somebody has gone online, so it tells this to the ouroffice_logic process, which decides what to do with that information. The logic process basically passes this information forward to the ouroffice_notifier process, (except for the case when it was the first time it would receive such info; because otherwise our twitter account would go nuts during debugging). The ouroffice_notifier process contains the code to randomly select a tweet and post it to Twitter with an OAuth-signed request.
Oh, and of course, the code is online: https://github.com/arjan/ouroffice (in the public domain)
So, that's it! The code has been running now for a week or so and seems pretty stable (it's only a few lines anyway...); the only thing is that the Raspberry Pi it runs on sometimes overheats, or draws too much power, because every now and then it freezes and the whole machine becomes unresponsive.