Hacking the coffee machine
Dear reader. We at Q42 have a confession to make.
It’s bad. Real bad.
You know that awesome coffee counter on our website?
It’s fake.
Well, it’s not live, let’s put it that way. It’s based on real consumption amounts at our office (someone actually measured over the course of a day!) but not realtime, not real.
Until now, that is. When Guido and I found out it was fake we decided this couldn’t last. In our Amsterdam office, there’s a Jura coffee machine. It makes nice coffee. Good enough that even smug home baristas like Mark and myself will accept it as being actual coffee. Now, we decided we were going to get it connected and have it tell us how many cups of coffee it made.
Sounds easy, except it’s not. Like every other coffee machine maker on the planet, Jura does not provide a nice API for us to talk to our machine. (We secretly expect these guys to break that industry habit). In fact, even though their machines have serial and USB ports to interface with them, Jura actively tries to shield you from using those — no documentation, purposely miswired serial ports, encryption, etc.
Hacking the hardware
So we decided to put on our hacker hats and break in. We found some information on the encryption protocol on a now-defunct website (thanks Gisbert!) to get us started. We turned this into a bunch of python scripts on a raspberry pi, which in turn was connected via software serial using GPIO pins as RX/TX to a bare serial connector into the Jura’s maintenance port. We needed this bare connector because the serial port on the machine has some evil miswiring, meaning it looks like a standard serial port but is wired differently so it’ll either not work, or blow up your computer’s serial port. We rewired it to have GND, TX, RX on pin 1, 2 and 3 respectively (normally 5, 3, 2). Once that was done, serial was a basic 9600/8/N/1 connection.
Next up: protocol encryption. The encryption on the Jura means you take one byte of data and spread it over four bytes, each of those four using only bitpositions 2 and 5 which get OR’ed into 0x5B. So for example, an uppercase A is hex 41, which is 10000010 in binary (LSB), which gets encrypted to 01011111 01011011 01011011 01011111 (LSB again). Reading the response is the same process in reverse.
Now to get an idea of where the coffee machines stores its internal coffee state or counter, we discovered we could send an RE command to machine to read its EEPROM. The format is RE:xxxx with xxxx being the hex offset into the EEPROM. We used a series of RE commands (actually RT, which gets a whole 16 byte line instead of a single value) to do a full EEPROM dump, then pull an espresso shot, then dump the EEPROM again, then simply compare the two. Do this a few times and you can eliminate the variables you don’t need, to find ones you do. Same basic process as cheating a game, like how really old people used to do on a Commodore Amiga using an Action Replay.
Turns out that wasn’t even needed: the machine’s diagnostics screen showed us total amounts per coffee type in its lifetime. We could just find those values in the EEPROM dump and from there, track changes to them as long as our hack device is plugged in and running.
To get the actual values, we pull EEPROM values every 10 seconds for the following offsets:
- 0x280: espresso
- 0x281: ristretto
- 0x282: coffee
- 0x284: cappuccino
- 0x285: latte macchiato (yes, people actually drink this)
- 0x286: macchiato
If any counter changes, the script triggers a call out to our Q42 IOT API.
For daily use, we threw the Raspberry Pi aside and settled on a much smaller, simpler microcontroller: a Particle Photon. It has wifi built-in and has a micro VM in the cloud to give it web hooks. It is very suited for this kind of thing: simple, low-performance processing, used to triggering things on the web. It doesn’t run OSes and stuff that needs updating, it doesn’t run out of memory or disk space, etc. Which means it’ll actually still work a year from now. IF our office wifi hasn’t completely crapped out by that point, which is a possibility given it’s wifi and we all know wifi really sucks.
This is the rear of the machine with the Photon in its super fancy 1-minute-breadboard-velcro-mount. The wiring is simple, same as the Pi, just hooked up GND, TX, and RX, they’re marked on the Photon.
The API
The photon firmware calls Spark.Publish which is set up by a JSON file to generate a preset HTTP call from the Particle cloud to our own IOT API. The JSON file couples an event name to a specific call to make — including REST method, HTTP headers, variables in URL or body, etc.
Our API server is a simple Meteor app that exposes a REST endpoint to dump events to, which get stored in a meteor collection. Then the website (and any other client for that matter) simply opens a DDP connection to the Meteor app and gets live updates. Doesn’t scale, certainly not to the extent we’ve achieved for our Q42 customer IoT infrastructures, but it’s elegant and maintainable through its extreme simplicity.
Throwing down the gauntlet
At Q42, we have multiple offices but we work as one and we don’t have separate office revenues like many agencies have. That doesn’t mean we don’t sometimes have a healthy little bit of competition going on though. In this case, now that the coffee counter on our site is only partly real, the Amsterdam office challenged the office in The Hague to un-fake their coffee machine. It may be even harder to hack the coffee machine in that office, which of course only means ‘even more fun’. Current attempts focus on machine recognition of the sound of the grinder. Which looks surprisingly promising :) We’ll keep you posted!
What machine around you would you like to have hacked and connected? Tell us in the comments!
Code: https://github.com/Q42/coffeehack
Check out our Engineering Blog for more in depth articles on pragmatic code for happy users!