Copy this, then paste it into Chrome's address bar:
Once it's open in Chrome: menu (⋮) → Add to Home screen. That icon always launches in Chrome, full screen, no address bar, and your bar setup travels with it. A web page can't pick its own browser on its own.
Open any drink and tap the heart to keep it here.
Six canisters, A to F. Pick what's loaded and say how many ounces went in; the machine reports what its scale measured after every pour, so the counts stay honest. Empty clears a canister here without sending anything. Flush runs water through: fill the canister with water, put a container under the spout and say how many ounces.
Which loadout unlocks the most drinks from what you've got to hand. Nothing changes until you say so.
Juice, soda, dairy, garnish — whatever you'd rather pour fresh than leave in a canister.
Reconnecting after a dropped link works as is.
Connecting on launch, with no tap at all, needs a Chrome feature that is still
switched off by default on Android. To turn it on: open
chrome://flags in Chrome, set both Experimental Web Platform
features and Web Bluetooth new permissions backend to
Enabled, and relaunch Chrome. Then connect once from
the app — after that it finds the machine by itself, and if the machine is
off it waits and connects when you power it on.
Wipes the canisters, mixer list, custom drinks and every recipe tweak on this device. The drink library comes back untouched.
Straight to the serial pipe. Hex like A5 01 00, or text.
Sends a run of common command shapes — plain text lines, then binary framings — and watches which one makes the machine answer. Safe: none of these are pour commands.
The map lists every service and characteristic the machine exposes, and reads anything readable. If there's a second write channel, or a firmware string, it shows up there.
Sends the same pour — station A, 30 — in several encodings and stops at the first one the machine answers. The full frame is 32 bytes, which only fits in one packet if the MTU negotiated above 23; the short forms fit regardless. Put a glass under the spout — if one works, it pours.
We only ever captured one command, the pour. Everything else the machine can do is unknown. This walks an opcode range, sends each one on its own, and writes down exactly what comes back — opcodes it knows tend to answer, opcodes it doesn’t stay silent. Take the canisters out first, or empty them, and put a jug under the spout: an unknown command may well dispense. 200 is skipped, since that is the pour.
We never captured the official app halting a pour, so the stop command is unknown — the Stop button has only ever been a guess. This finds the real one: it runs a long flush, sends one candidate command at a time, then reads the machine’s own report. If a pour that asked for 4 oz delivers far less, that candidate stopped it. Put water in the station and a jug under the spout.
Tap Run ½ oz on a row, watch which canister actually moves, then tap that letter when asked. If it was the wrong one the map fixes itself — no working out required. Do this once per canister and everything else follows.
The capture shows 200,1,30,0,… for one ingredient
from station A. The leading 1 is either the station number or an
on-flag in station A's slot — one ingredient can't tell them apart. If a
multi-ingredient pour fires the wrong pump, switch this.
Same frame, one byte counting up — the quickest way to find which
byte picks the station. Put {i} where the counter goes.
It will really dispense if you guess right. Glass underneath, or empty canisters.
Amber out, green back. The number after the clock is milliseconds since the line above.
Nordic UART — a plain serial pipe, so commands are short byte frames. The stock app shows 2.03 oz and 1.52 oz for pours, which are exactly 60 ml and 45 ml, and a full canister reads 25.36 oz = 750.0 ml. So volumes go over the wire in millilitres. Still unknown: the frame layout, and whether the machine needs unlocking before it pours.