BOOKOO Themis Ultra Bluetooth Protocol
With my recent espresso obsession, I needed a new scale and decided to get the BOOKOO Themis Ultra which has bluetooth connectivity.
BOOKOO publishes most of the BLE protocol on GitHub. The scale uses service 0x0FFE, with commands written to 0xFF12 and live weight data sent over 0xFF11.
But the public protocol is missing a few things the BOOKOO N app can do — most importantly changing modes and putting the scale into its automatic “Ready” state.
By partially decompiling the app and testing commands against the scale, I was able to fill in those gaps.
One interesting wrinkle: the behavior changed between firmware versions. Older firmware has a standalone Auto mode. On 4.0.x, Auto is instead a submode of Flow or Ratio. To start an automatic brew, the mode has to be configured for Auto and then explicitly put into Ready.
Commands are six bytes:
03 0A COMMAND DATA1 DATA2 XOR
The last byte is simply the XOR of the first five.
| Function | Packet / notification | Notes |
|---|---|---|
| Tare | 03 0A 01 00 00 08 | Tare |
| Set beep level | 03 0A 02 00 LEVEL XOR | Levels 00–03 on 4.0.x |
| Set auto-off | 03 0A 03 00 MINUTES XOR | 5–30 minutes |
| Start timer | 03 0A 04 00 00 0D | Manual timer start |
| Stop timer | 03 0A 05 00 00 0C | Manual timer stop |
| Reset timer | 03 0A 06 00 00 0F | Clear elapsed time |
| Tare + start | 03 0A 07 00 00 0E | Combined command |
| Flow smoothing | 03 0A 08 00 ENABLED XOR | 00 off, 01 on |
| ★ Read firmware | 03 0A 0A 00 00 03 | Reply is 03 0C; e.g. 01 36 → 3.1.0 |
| Configure Auto stop | 03 0A 0B MODE CONDITION XOR | Separate Flow/Ratio settings on 4.0.x |
| ★ Select mode | 03 0A 0C MODE SUBMODE XOR | Weight 00, Flow 01, Ratio 02 |
| ★ Select submode | DATA2 = 00 / 01 / 02 | None, Manual, Auto |
| ★ Legacy Auto | 03 0A 0C 03 00 06 | Standalone Auto on older firmware |
| Set Ratio dose | 03 0A 0D HIGH LOW XOR | Dose in 0.1 g units |
| ★ Read mode config | 03 0A 0F 00 00 06 | Reply 03 0E contains mode + submodes |
| Shutdown | 03 0A 15 00 00 1C | Supported on 4.0.x |
| ★ Enter Ready | 03 0A 18 00 00 11 | Required before automatic brew on 4.0.x |
| ★ Exit Ready | 03 0A 18 01 00 10 | Leave Ready |
| Keep awake | 03 0A 25 00 00 2C | Firmware 4.0.1+ |
| Weight notification | 03 0B … on 0xFF11 | Time, weight, flow, battery, settings |
| Auto event | 03 0D … | Ready / started / stopped / exit |
| Powder weight | 03 0F … | Stored Ratio-mode dose |
★ = recovered or clarified from the BOOKOO N app.
For example, to enter the Auto Flow mode (which you'd use when making the espresso), you can use this pattern.
import asyncio
from bleak import BleakClient, BleakScanner
FF12 = "0000ff12-0000-1000-8000-00805f9b34fb"
def command(code, data1=0, data2=0):
packet = [0x03, 0x0A, code, data1, data2]
checksum = 0
for byte in packet:
checksum ^= byte
return bytes(packet + [checksum])
async def main():
device = await BleakScanner.find_device_by_filter(
lambda device, _: device.name and device.name.startswith("BOOKOO_SC_U")
)
async with BleakClient(device) as client:
await client.start_notify(
FF12,
lambda _, data: print("FF12:", bytes(data).hex(" "))
)
# Flow Auto on firmware 4.0.x
await client.write_gatt_char(
FF12, command(0x0C, 0x01, 0x02), response=True
)
# Enter Ready
await client.write_gatt_char(
FF12, command(0x18, 0x00, 0x00), response=True
)
asyncio.run(main())