Skip to main content
This is independent, unofficial reverse-engineering documentation produced by static analysis of publicly downloadable firmware images. It is not affiliated with or endorsed by Totem Labs. No services were attacked. Findings come from reading the firmware binaries and the companion mobile app. The BLE protocol was additionally exercised with the totemctl client against the author’s own device (firmware 4.1.3 and 5.0.3); where that changed a conclusion, the page says so.

What this documents

The Totem Compass is a festival navigation and social device: a handheld puck with a ring of addressable LEDs (called the “halo” in the companion app; RING_PX_COUNT in firmware), a light-up capacitive touch crystal (the app’s “Touch Crystal”; CRYSTAL_PX_COUNT plus the ESP32 touch_pad peripheral), a GNSS receiver, an IMU, and three 2.4 GHz radios. Groups of Totems bond into a mesh so friends can find each other, send taps and messages, and navigate to a shared point. This site documents firmware v5.0.3 at the level recoverable from the binary. It started from v5.0.2; What changed in 5.0.3 lists the differences.
  • The firmware is an ESP32 application built on ESP-IDF v5.4.
  • The device runs MicroPython v1.25.0; all of Totem’s own logic is Python, frozen into the image as compiled bytecode across 94 modules (plus 2 on-flash VFS source files, boot.py and webrepl_cfg.py, for 96 total .py files; v5.0.2 had 96 frozen modules).
  • Three radios share the 2.4 GHz band: BLE (phone app), ESP-NOW (Totem-to-Totem mesh, called the “Unity Mesh” in the companion app; MODE_ESP_NOW_* / MESH_* in firmware), and WiFi (station-mode OTA updates; the device-hosted hotspot path is sunset).

Firmware architecture

MicroPython app layout, the 94 frozen modules, and how they fit together.

2.4 GHz protocols

BLE, ESP-NOW mesh, WiFi OTA — message format, categories, and framing.

Navigation stack

u-blox GNSS, AssistNow, IMU fusion, and World Magnetic Model declination.

OTA & download URL

How updates are fetched and how the firmware URL is constructed.

Firmware at a glance

How to read this documentation

Findings are graded by how directly the binary supports them:
Directly present in the image: version strings, module names, GATT UUIDs, struct/format strings, log messages, and the observed (cat_id, cmd_id) pairs.
Strongly implied by symbol names and log text but assembled by the analyst (for example, the role of a module or the meaning of a command namespace).
Exact numeric values that live only inside frozen bytecode — the complete cmd_id enumeration and the precise binding of each struct format to a message. See methodology for how to close these gaps.