Ether-brewed Coffee: Iot & Blockchain

Joan Miro, Still Life With Coffee Mill, 1918
Joan Miro, Still Life With Coffee Mill, 1918

In a previous article we have stressed how IoT and blockchain were a good match. Specifically the blockchain brings protections against various IoT attacks and a built-in payment system. It allows for secure interactions, public deterministic execution and auditability. Since we missed a coffee machine in the Lab we decided to make it a blockchain project with a graphic interface for a coffee machine allowing our colleague to pay in Ether and enhancing the user experience with the smartphone wallet Leth.

coffee first

We had to do a longer than expected benchmark to find a suitable coffee machine. We wanted a machine where we could connect easily to the wires as the wireless versions seemed complex to hack. We selected the Philips-HD8827 who had a front panel we could remove. The IoT will be brought by a Raspberry Pi 3 running the Jessie 4.9 OS and a GPIO card.

The blockchain of choice will be Ethereum Ropsten in order to have an easy access to ether and smartphone wallet. The latter will be Inzhoop’s Leth that exists both on IOS and Android. At first we wanted to use Parity Technology’s Kovan for the short blocktime but this chain was not available on Leth or any other smartphone app we known about.

Step 1: screw-driving our way to the wires

coffee 2nd

The coffee machine buttons will be wired and activated via the Raspberry through the GPIO card.

Step 2: setting up the Raspberry Pi

We burned the SD Card with Jessie 4.9, installed the Ethereum client Parity, the GPIO libraries , and QTcreator to build a quick graphic interface.

Step 3: testing the buttons 

The tests revealed that a LED and a resistance were needed to deliver the proper signal.

coffee 3nd

Step 4: setting up smartcontracts

Our first approach was to right a smartcontract with a function per buttons but little did we know that the generation of QR codes for a smartcontract function to be called was not stable yet. This had an influence on our smartcontract architecture choice. On deployment the contract Coffeth will create 3 Option contracts that will be refered as “espresso”, “lungo” and “coffee”. Sending ether to one of the latter will send the ether minus the eventual change to the Coffeth contract and trigger an event with the option of choice:

pragma solidity ^0.4.11;
// initial price: 100000000000000000
contract Ownable {
address public owner;
modifier only_owner() {
require(msg.sender == owner);
_;
}
function new_owner(address newowner) only_owner {
require(newowner != address(0));
owner = newowner;
}

}
contract Coffeth is Ownable {
address public espresso;
address public lungo;
address public coffee;
event Order(address indexed option);
function Coffeth(uint _price) {
owner = msg.sender;
init(_price);
}
function () payable {
Order(msg.sender);
}
function init(uint _price) internal {
espresso = new Option("espresso", _price);
lungo = new Option("lungo", _price);
coffee = new Option("coffee", _price);
}
function setprice(address _option, uint _price) only_owner {
require(_price > 0);
Option(_option).updateprice(_price);
}
function getprice(address _option) constant returns(uint256) {
return Option(_option).price();
}
function withdraw() only_owner {
owner.transfer(this.balance);
}
}

contract Option {
string public label;
uint256 public price;
address public coffeth;
modifier only_coffeth {
require(msg.sender == coffeth);
_;
}
function Option(string _label, uint256 _price) {
coffeth = msg.sender;
label = _label;
price = _price;
}
function () payable {
uint256 change;
// make sure that money sent is greater or equal to price
require(msg.value >= price);
// if greater, calculate change. Send change back to sender,
//send the rest to the coffeth contract.
if(msg.value > price) {
change = changecalc(msg.value);
msg.sender.transfer(change);
coffeth.transfer(price);
} else {
if(msg.value == price) {
coffeth.transfer(price);
} else {
revert();
}
}
}
function updateprice(uint256 _price) only_coffeth returns (bool) {
price = _price;
}
function changecalc(uint256 _given) internal constant returns(uint256) {
return safesub(_given, price);
}
function safesub(uint256 _a, uint256 _b) internal constant returns (uint256) {
assert(_b <= _a);
return _a - _b;
}
}

Step 5: connecting the machine and the blockchain

The smartcontracts generate events when the right payment is sent, those events will trigger a Python script sending a signal to the right button. Listening to events can be done easily in Javascript with the Web3 library.

STEP 6 : PROFIT !!

Scanning the QR code will display the address of the selected Option contract in the smartphone wallet.

full coffee

As you can see on ropsten.etherscan the Option sub contract are sending ether change back to the caffeine deprived customer:

coffen change titled

The Coffee Machine served 49 coffees so far!