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.

FunctionPacket / notificationNotes
Tare03 0A 01 00 00 08Tare
Set beep level03 0A 02 00 LEVEL XORLevels 00–03 on 4.0.x
Set auto-off03 0A 03 00 MINUTES XOR5–30 minutes
Start timer03 0A 04 00 00 0DManual timer start
Stop timer03 0A 05 00 00 0CManual timer stop
Reset timer03 0A 06 00 00 0FClear elapsed time
Tare + start03 0A 07 00 00 0ECombined command
Flow smoothing03 0A 08 00 ENABLED XOR00 off, 01 on
★ Read firmware03 0A 0A 00 00 03Reply is 03 0C; e.g. 01 36 → 3.1.0
Configure Auto stop03 0A 0B MODE CONDITION XORSeparate Flow/Ratio settings on 4.0.x
★ Select mode03 0A 0C MODE SUBMODE XORWeight 00, Flow 01, Ratio 02
★ Select submodeDATA2 = 00 / 01 / 02None, Manual, Auto
★ Legacy Auto03 0A 0C 03 00 06Standalone Auto on older firmware
Set Ratio dose03 0A 0D HIGH LOW XORDose in 0.1 g units
★ Read mode config03 0A 0F 00 00 06Reply 03 0E contains mode + submodes
Shutdown03 0A 15 00 00 1CSupported on 4.0.x
★ Enter Ready03 0A 18 00 00 11Required before automatic brew on 4.0.x
★ Exit Ready03 0A 18 01 00 10Leave Ready
Keep awake03 0A 25 00 00 2CFirmware 4.0.1+
Weight notification03 0B … on 0xFF11Time, weight, flow, battery, settings
Auto event03 0D …Ready / started / stopped / exit
Powder weight03 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())