An interesting part of working on the Building Management and Control (BMaC) project – as previously covered on this site – was the reverse-engineering and ultimately the gaining of full control over the coffee machines at the office. Not the boring filter coffee machines, mind you, but the fully automatic espresso machine type that grinds beans, makes coffee, adds milk, and much more. Depending on one’s budget, naturally.
These little marvels of engineering contain meters of tubing, dozens of sensors, valves, ceramic grinders, and heating elements. The complexity of this machinery made us think that maybe there was more that we could do with these machines beyond what their existing programming and predefined products would allow. Naturally, there was.
Meet the TOP-tronic Hardware
The espresso machines at the office are all from Jura, a Swiss company. Specifically we had the Impressa XS90 and an older version of it, along with an X3 and XJ9. Initially we were just interested in reading out the counters in its EEPROM that gave us this overview of our colleagues’ coffee use:
Believe it or not, these counters could be read out over TTL-level serial port on the back of these machines, a serial port on which the internal microcontroller speaks a simple binary protocol. A similar project, covered by Hackaday a few years ago, featured similar functionality in terms of reading out these coffee usage counters.
The protocol is essentially plain ASCII commands and responses, with each byte turned into four bytes. Only bits 2 and 5 of carry data from the original byte, and the rest of the carrier bytes are 1s except for bit 0. This encoding and matching decode routine were implemented in the BMaC project’s ‘Jura‘ and ‘JuraTerm‘ firmware modules.
Inside these machines, you’ll find a controller board made by TOP-tronics. Most of them feature what we have come to call the ‘generation 5’ type of boards, since the triple-digit model number starts with a ‘5’ for those boards. They all feature a simple processor and have their programming inside a section of masked ROM, meaning that they do not support firmware updates, but only allow for small configuration changes in an EEPROM on the same PCB. Product counters are also stored in this EEPROM.
All of these boards communicate via their serial ports, presumably using the same padded serial protocol to receive instructions from the small LED or LCD-based front-panel interface PCB. The XS9, XS90, and XJ9 all have similar generation-5 hardware inside, but the XJ9 is the only one which has the color TFT LCD and much larger product selection out of these three. The X3 and its siblings (X3c, W3), on the other hand, feature ‘generation 7’ hardware. And instead of the masked ROM and simple microprocessor, they have an ARM MCU (STM32F103ZE) and no longer use the EEPROM (93LC86) to record counters. Attempts to use the simple ‘TOP-tronics’ protocol to read the EEPROM results in the machine returning rows of zeroes. These machines also feature a Bluetooth dongle which plugs into the user-accessible third UART (‘extension port’) so that it can be used with the Jura app on smartphone or tablet.
With our X3 machine mostly unresponsive to the usual protocol and commands, we decided to sniff the UART lines between this dongle and the machine while operating the app on a tablet, electing to use the first UART (‘service port’) because it has a chunky DE-9 (RS-232C-style) D-subminiature connector and creating an adapter was much easier. Functionally both UARTs are identical as far as we could determine.
Unfortunately the first sniffing attempts already showed why we were having such a hard time communicating with the machine: instead of sticking with the plain-text protocol, the dongle and machine performed what appeared to be a handshake using the old protocol before switching over to an encrypted connection.
Similarly, the Bluetooth connection between the dongle and tablet-based app seems to be fully encrypted as well. Initial attempts at reverse-engineering, decrypting, or even simple replay attacks proved to be fruitless and we had to give up on this machine for the time being. We didn’t want to break thousands of Euros worth of machinery and a crucial part of the office’s (coffee) infrastructure, so we were kind of stuck when it came to these newer machines.
Making the Machine Dance for Us
That left three machines that we could communicate with. When my employer organized a hackathon event, that was the perfect time to see what we could do with them. We started off connecting them to the local WiFi network. These little black boxes contain an ESP8266 and a level shifter, running the BMaC firmware containing the two Jura modules which I referred to earlier in this article.
While looking through the list of possible commands, it became clear that with it one can address every single part of the machinery that is involved in making the final product, from the grinders to the valves to the entire brewing groups. Instead of using the ‘make product X’ commands that read the product presets from the ROM, we could instead send our own string of commands to the machine to make our own, custom product.
The machine is essentially a series of pre-heaters (d), heaters (e), pumps (c), flow sensors (b), valves (f, i), all serving the brewing unit (g), which is the core of the machine. This is where the grinder (not pictured) after grinding a certain amount of coffee beans drops the powder into, which is then flooded with the hot water from the valves and heating elements. Depending on the type of product one can also use steam during the brewing, and add milk from an external unit if so desired to the final product. The fun question was in which order one was supposed to use them, and for how long. Figuring this out was the goal of this one day long hackathon.
The Struggle, and Kilograms of Beans
With no real guidance beyond a vague idea of how all of these parts of an automatic coffee machine were supposed to work together, we started off with the assumption that we’d need to grind some beans for a few seconds or so, then add hot water and wait for the fresh coffee to appear in the mug we had put underneath the output side in anticipation. Unfortunately that just got us some hot water in the mug and dry coffee grounds in the waste water container. Clearly something had gone terribly wrong. Going back to the drawing board, we began to carefully attempt various approaches and series of commands.
By the end of that day, we had worked our way through two kilogram bags of fresh beans, managing to produce something that appeared to be at least at first whiff to be coffee, so we first had those in the team who drank coffee try it until they started rebelling and we had to get people from the other teams to try our creations when they popped by to see what in the world was happening in this one room that smelled very strongly of coffee for some odd reason.
In the end we figured out that the right sequence of events for the XS90 was:
- Grind coffee (1 second).
- Move the brewing unit into the brewing position.
- Heat water (2 seconds).
- Pump hot water into the brewing unit (>10 seconds).
- Drain the coffee.
- Flush the brewing unit with fresh water.
- Discard the used coffee grounds.
- Move the brewing group back into the grinding position.
- Close the drain valve.
This sequence allowed us to produce something that reasonably approximated what someone might call ‘decent coffee’, according to my colleagues who do drink coffee. There were still many details we had to figure out to perfect things, but we felt that we had come tantalizingly close to doing so. Not surprisingly, our team won that hackathon.
Frustratingly, the list of TOP-tronic commands we had started with turned out to be incomplete. At some point, one of my colleagues figured that they should try unlisted commands that were in sequence, just to see what the machine would do. We had the whole machine screwed open, so we could get a good view of its internals.
Here one can see the serial cable plugged into the logic board of the machine with most of the tubing, pump, and some of the valves visible. This usually worked fine, allowing us to deduce what worked and what didn’t, barring one incident involving a command that apparently set the multi-valve into a wrong state, so that the coffee would come out on the right output instead of the left one.
Since the hackathon, we haven’t had time to convert this proof of concept into a full-blown product that would allow us to command the coffee machines to produce the exact coffee or espresso we desire, much less calibrate the amount of fluid added to the nearest millilitre. This is definitely something that should be done, though.
A somewhat unpleasant note here is that apparently Jura and TOP-tronic have decided to move away from an easily used protocol as that found on the generation 5 boards. At some point I even toyed with the thought of replacing the TOP-tronic board in the X3 and other machines with generation 7 hardware, using a custom ARM-based board that would simply drive the components according to the input obtained via a WiFi or Ethernet link.
Unfortunately, that would mean decisively voiding the warranty, which is the last thing which one would wish to do with a coffee machine that costs more than a used car. Still, the hacking potential with these automatic coffee machines seems to be almost infinite. If you can get your hands on a (used) XS90 or XS9, it could make for a whole lot of fun, and possibly even the best coffee in your life.