
Grounds for innovation
Here at MailChimp, we're always trying to listen hard and change fast. Turns out, this requires a good bit of coffee. Each department has its own take on how to keep the stuff flowing, mostly with the standard Bunn-O-Matic commercial machines. A few folks regularly avail themselves of our espresso setup. The developers fill two airpots—one with regular, the other double strength.
And then there's the marketing team and our precious Chemex.
We make a pour-over pot once every hour or so, all day long, 5 days a week, 50-something weeks a year. Last December, when we were gathering data for our annual report, we got curious about how many Fresh Pots that might amount to. We tried to count it up, but begrudgingly had to accept the fact we didn't have a good measure beyond pounds consumed. We even tried to keep track with a bean counter, but that didn't last long.
For a while, the exact nature of our coffee consumption seemed like it would remain just another mystery of the universe. But then one day, talking to Mark while waiting on yet another Fresh Pot, I said, "Hey, I bet we could track the temperature with a Raspberry Pi and post to the group chat when there's a fresh one."
I wasn't too serious, but Mark's response was one often heard around MailChimp when ridiculous projects are proposed: "Sounds great, just let me know what you need to get it done."
A few days later, I had a materials list drawn up from Adafruit's thermometer tutorial, and we were off to the races.

A fresh Pi
With a Raspberry Pi in hand, the first thing I did was add a script to the boot process that sent an email using Mandrill with its IP so I could find it on our network without trouble.
Then, I had to tackle the problem of detecting pot states with only a single datapoint: current temperature. I hoped that comparing the running averages of different time spans would be enough to determine the pot's status. (The average Chemex temperature over the course of a few minutes, for instance, would tell us something different than the average temperate over the course of an hour.)
Since this was a greenfield project, I wanted to work with an unfamiliar language. I felt like the more functional nature of Clojure would be a great fit for passing along a single piece of state. This turned out to be a great decision, and I'll explain why in a minute.
Graph it home
I hacked together a quick program that would spit out the current temperature, minute's running average, hour's running average, and the running average's rate of change to a log file so I could analyze them.
...
{"current":32.062, "minute":24.8747, "hour":23.5391, "running-rate":0.039508}
{"current":32.437, "minute":25.0008, "hour":23.5635, "running-rate":0.0423943}
{"current":32.875, "minute":25.1322, "hour":23.5897, "running-rate":0.045361}
{"current":33.625, "minute":25.2738, "hour":23.6177, "running-rate":0.048569}
{"current":33.625, "minute":25.413, "hour":23.6476, "running-rate":0.05159}
{"current":33.625, "minute":25.55, "hour":23.6793, "running-rate":0.054437}
...
Log files in hand, I temporarily turned back to Ruby using the wonderful Gruff charting library to visualize things and make patterns easier to spot.
A few batches of hot water gave me a decent idea what things should look like, so I moved our coffee equipment to my desk to get some live data. This let me check in with the actual running state of the program and compare it with the status of the pot (and led to some coworker laughs and a wonderful smell at my workspace all day).

A brewing or fresh pot is easy to recognize, but figuring out when the pot is empty turned out to be a little tricky. It takes a while for the Chemex to completely cool off, which means it could be empty and still warm, which I'm sure would lead to more than a few disappointing trips to the kitchen. Luckily, the rate a pot cools tells us if it is empty or not—for instance, a half-full pot stays warm longer than an empty one simply because of the coffee still in it. Always nice to have physics on your side.
Watchers for the win
Armed with the collection of datapoints (running averages, rate of change, etc.) for each of the pot's states, I moved on to figuring out how to notify our department's group chat room when a pot was brewing, ready, empty, or stale. This is where some of the built-in features of Clojure came in handy.
I already had a program that logged the current state of itself every second. By switching the actual state to an agent, I could apply watchers to it. These watchers get called whenever the agent changes, which is perfect for analyzing changes in state.
Another agent added was the pot itself. The watcher for the temperature would look for the above mentioned boundaries, and update the pot's state, leaving another watcher to track the pot and notify our chat room. When it came time to pick an alias to deliver the notifications, Dave Grohl was the natural choice.
Here's a simple example of the pot watcher looking for a brewing pot:
(def pot-status
(agent {:status "empty"}))
(defn pot-watcher [watcher status old_status new_status]
(if (= (:status new_status) "brewing")
(notify/is_brewing)))
(add-watch pot-status :pot-watcher pot-watcher)
The great thing is the watcher only gets called when the status changes, not on each tick of the temperature. Using agents felt great to me in this case as they provided a clean way to watch state (without callbacks or a ton of boilerplate) and maintain separation of concern between different parts of the program.
Watchers in place, it was time for the Fresh Pi to be personified as our personal hero Dave Grohl. We wrote up a few different messages and let Dave start notifying our chatroom.

Freshness into the future
I'm still working out a few kinks, tuning in the bounds, and keeping a log of pots. It's been a fun experience and I learned a ton. Something tells me this won't be the last time we work with Raspberry Pi on a project. What's next, Fresh Pots in space? Luckily, we've got plenty of coffee to propel us.

John J. Wall
09.08.2014 -
This is awesome, I’ll add it to the show notes for the next Marketing Over Coffee!
Suyog Mody
09.08.2014 -
This is awesome!
Side note – the OXO box to store beans may not be the best idea. AFAIK, it’s meant to be airtight whereas beans (especially freshly roasted ones) need to let out CO2 to degas properly. Good coffee bags usually have a one-way valve to let out CO2 and not let anything in.
Mike Keiter
09.10.2014 -
You guys are insane…and witty…and nerdy…I love it!
Christoph
09.16.2014 -
Fantastic project!
You could add a sensor to measure the weight of the coffee pot. Another way to count your pots of coffee. But more important you could send some sort of shout-out to the colleagues if the coffee is starting to cool down but there is still a cup or two left (based on the weight). Or a live counter of cups left in the pot at what temperature.
Steven Sloan
09.16.2014 -
Thanks Christoph, glad that you’d hate to waste a cup of coffee as much as we do :). Currently our “stale” notification goes out when the pot hits 48°C so it’s still warm enough for those dedicated to not wasting a drop.
I like the idea of keeping a live counter. Our assumptions about “rate of cooling” would definitely be tested.
Jenna Compton
09.18.2014 -
I love how you embrace and encourage the creativity in your company. The result is obvious: a great product. Viva MailChimp!
Jay Stephens
09.18.2014 -
Nice project, nicely implemented… and a respectful nod towards the world’s first webcam http://en.wikipedia.org/wiki/Trojan_Room_coffee_pot
Daniel Dewar
09.22.2014 -
We’ve looked at implementing something similar for a long time at our office. Thanks for the inspiration!