Monitoring coffee: Tales from Hosted Graphite’s secret lab

It has been said that software engineers are organisms that convert caffeine into code. Not all software engineers need coffee to get by, but it’s popular enough that it’d be silly for us not to have an office coffee machine…

…it’d also be sort of silly for a monitoring company not to monitor that coffee machine, which is so crucial that we could make a reasonable argument for it being part of the production infrastructure.

This blog describes how we craftily added some electronics to our office coffee machine to measure coffee production, with lots of technical details and pictures. It’s probably worth pointing out here that this is not, and never will be, any type of corporate penny-pinching surveillance nonsense — we do this for fun! To wet your whistle, here’s a pretty coffee-themed dashboard with our coffee data from the last year:

Coffee brewed by day

The data from this coffee machine is displayed prominently in the centre of the office, and has been working reliably for almost a year:

Read on to see how we did it.


Nespresso XN 3005

We started with a fairly basic Nespresso XN 3005, sometimes known as the “Pixie” model. The first step is cracking the case open, which is sort of tricky because of all the hidden latches that you need to frob.

After removing the accessories and the two side plates, (held in with large Torx screws), you can start frobbing the little latches carefully. You might need a spudger to avoid damaging the plastic.

Water pump, thermoblock, and control unit (at top).
Cracking open the controller unit.

After quite a bit of faffing, disassembly, and digging, we had the controller PCB out of the housing:

Controller PCB

At this point, we can make some instrumentation decisions.

Moulded button cover

Under the moulded button cover, there’s a small PCB with the actual buttons, and it is connected via some ribbon cable to the main controller PCB. That seemed like an easy and obvious spot to “listen” to the electrical signals from the button presses, so some tiny wires were soldered here, with some strain relief in the form of a dab of hot glue:

Tiny wires and hot glue

The signals instrumented here are: big coffee button, small coffee button, and logic GND, to use as a reference for comparing the button signals against. Next up, we need a way of getting the data out of the machine and into, oh, I don’t know, a handy hosted monitoring service that we happen to run.

Adding to the Internet of (Shitty) Things (IoST)

The well known ESP8266 platform is ideal for a job like this. The hardware is physically very small, it supports WiFi, is easy to program from the Arduino interface (though we actually used PlatformIO as the toolchain/build environment, which is *awesome*) and very cheap at ~$2 each. The specific variant we used is an ESP-07:


The drawback of using an ESP8266 is that it takes a lot of power – ~70mA when running with WiFi enabled, and it consumes a ridiculous peak of hundreds of milliamps at startup. The voltage regulator on the coffee machine logic board is well specced for its purpose and has a safe amount of overhead for what it has to do, but not much more. It might just about handle an additional 70mA, but it’s too close for comfort and the startup current is definitely a bad idea, so we had to add a new DC supply just for the ESP8266.

Power for the ESP8266’s AC-DC converter is drawn from the same AC supply that is on when the coffee machine is on, and so the two units turn on and off together. (Though that causes problems itself, see below for a description of an amusing bug).

Finally, the tiny instrumentation wires from the coffee machine buttons are snaked out of the control board housing and into some resistors to limit the current flow into the ESP8266’s GPIO pins.

That’s it, there aren’t any other connections or parts. All that’s missing now is some software!

Adding some intelligence

The software on the ESP8266 module is written in C++, using the Arduino ESP8266 framework because it’s dead simple and is great for rapid development on smaller projects.

When the coffee machine is turned on, the ESP-07 module is also powered up and it starts watching for button press signals from the Nespresso machine. After a couple of seconds, it connects to our WiFi network, and either forwards any recently stored button presses, or waits for new button press events.

These button press events are, predictably enough for Hosted Graphite, sent in the Graphite format to our own service. Here are some snippets of the code we use to send a Graphite-formatted UDP packet to Hosted Graphite from the C++ running on the ESP8266:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

WiFiUDP graphitesock;

#define CARBON_HOST ""
#define CARBON_PORT 2003
#define PREFIX "your-hosted-graphite-api-key-here"

// Place this inside 'main'
//    graphitesock.begin(random(40000, 60000));

bool graphiteudp(char *host, int port, char *format, ...)
    char *buf = (char *) malloc(MAX_PACKET_SIZE);
    va_list args;
    va_start(args, format);
    vsnprintf(buf, MAX_PACKET_SIZE, format, args);

    graphitesock.beginPacket(host, port);
    int retval = graphitesock.endPacket();

    return retval == 1;

And later, after one of the coffee buttons are pressed:

graphiteudp(CARBON_HOST, CARBON_PORT, " 1", PREFIX, ESP.getChipId());

At this point, Hosted Graphite receives the UDP packet, records the “1” against the right metric, and enables us to build a pretty coffee consumption dashboard:

Spike in coffee consumption the day after our team day out on the 10/27 (there *ahem* may have been drinks).
Upward trend in large coffee after hardcore coffee drinker Bébhinn joined the team 05/30.
Storm Ophelia 10/16: most of the office stayed at home but one trooper made it in (and drank 6 coffees). One of the lowest consumptions for a Monday all year.
10/31 Drop in consumption after the Halloween bank holiday (coincides with a coffee fiend developer’s time off).
Unusual spike in July coincides with two events: we got iced coffee capsules and decaf capsules. Both were a hit.

Some other cool features:


An oversight at the hardware “design” stage means that it’s not possible for the ESP8266 to differentiate between when a button is pressed and when the coffee machine has just been turned off. The ESP8266 stays on for a second or so longer than the coffee machine because of the power stored in a filtering capacitor, so the workaround is to simply defer sending any datapoints about button press events for a couple of seconds.

If the system is still up a couple of seconds later, it was probably a real button press, and if the system is not up by then… well, it’s already off, so problem solved, right? Hacky, but it has proved reliable enough for our purposes.

Things on the TO-DO list