Brand logo
HomeCloud ComputingSecuritySoftware DevelopmentAI ApplicationsStartupsGeneral
  1. Home
  2. /
  3. general
  4. /
  5. beyblade-x-bx-09-bluetooth-rpm-payload-decode

ItInsightsWorld Lab Notebook: Paging a Beybattle Pass Over Bluetooth, From RPM Records to a DiZZi 0.2 Companion

Some reverse-engineering work starts from a datasheet; this entry starts from a social feed. Filed under October 22, 2026 and logged at 10483 views on its original publication, the notebook begins with something absurdly ordinary. At the beginning of June last summer, the Instagram algorithm had just been reset for the 10th time that year, and it responded by rediscovering Beyblades — the Beyblade X generation to be precise, whose reels were impossible to scroll past: the Bit grabbing a rail, a gimmick called Xtreme Dash converting that into a violent collision. A stadium and several beys were bought in a Dublin toy shop days later, the verdict arrived at a games night That same weekend, and the reason was plain. Play reads quicker and lighter-hearted than in earlier generations, and tops ricocheting across a living room converted the entire table.

Where the BX-09 entered the picture

Over the following months the hobby compounded: local tournaments, new players, and a shelf of Beyblades nobody in the house endorses. Hunting the usual ultimate combo of Blades, Ratchets and Bits is how one research session turned up the Beybattle Pass (BX-09).

Everything published about it named Takara Tomy as its maker and described a hard regional limit — Japan. Clip it to a launcher, pair it with an official mobile app over Bluetooth, and each launch is transmitted, the Shoot Power value being nothing more exotic than the RPM (revolutions per minute) of that launch. Collected points buy entries into a lottery system reserved for Japan, whose prizes are rarer Beyblades. Patience eventually produced a listing on eBay Japan, and an unfortunate scalper price produced the receipt.

Mechanics before packets: two holes, three hooks, one lever

Nothing below came from opening the housing — too expensive to risk destroying — so the method is hands-on testing plus patient observation. The honest result is that the design explains itself almost completely.

Start with the upper surface. Official Beyblade X launchers, the string launcher in the reference video among them, present two holes; inside the first sits a small rotating disc whose colour flips between black and white according to how fast the string is pulled.

Then turn it over. Seating a Beyblade on the three hooks at the bottom also forces a little white lever upward, and that lever re-emerges through the second hole (blue arrow below):

Align the two views and a chain appears. The lever sliding upward reports to the Beybattle Pass that a Beyblade is mounted; because the lever doubles as a button, the same motion powers the accessory and arms a sensor (purple arrow) watching how quickly the black-and-white disc turns as the string is pulled.

Aiming a phone's front-facing camera at the housing exposed what appears to be an infrared sensor. Presumably the rotating disc is tracked through changes in reflected infrared, and from that the Shoot Power value is calculated. The reference video simulates a mounted Beyblade for exactly one reason: to show the lever arming that sensor.

Capture session: BEYBLADE_TOOL01, LightBlue and PacketLogger

Long press powers on; holding the button until the lights blink opens pairing. The advertisement that surfaced was BEYBLADE_TOOL01. After a short suspicion that it belonged to a neighbour's Bluetooth speaker, the link was accepted, the blinking stopped, and LightBlue plus PacketLogger were pointed at the traffic. Early relief: the Beyblade X app turned out not to be needed to see launches at all.

Two characteristics were handed over once connected:

  • 0x55c4f002f8eb11ecb9390242ac120002 — readable, with Notify
  • 0x55c4f001f8eb11ecb9390242ac120002 — Write without Response only

Initial confidence was misplaced, summed up by the thought 'Ok, this structure looks simple enough.' Subscribing to the Read and Notify characteristics produced silence. That silence broke the instant the Beybattle Pass was clipped to a launcher with a Beyblade mounted — an orange LED lit up.

In came the first record, unreadable at the time:

a0 3a 00 04 ff 00 00 00 00 00 00 00 35 b4 04 51 c4 da

Then a launch happened, and the response grew into thirteen page rows:

Page tagRaw bytes as capturedFirst-pass reading
a0a0 3a 00 00 ff 00 00 a2 0c 01 00 35 b4 04 51 c4 dametadata block: counter, status, a candidate value, device address
b0b0 a2 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00launch grid, still nearly empty, pair already mirrored here
b1b1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00reserved / zero-filled
b2b2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00reserved / zero-filled
b3b3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00reserved / zero-filled
b4b4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00reserved / zero-filled
b5b5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00reserved / zero-filled
b6b6 00 00 00 00 00 00 a2 0c 01 00 01 00 00 00 00 00tail area holding the same pair plus two single-byte counters
b7b7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5elast grid row, terminating byte still unexplained
7070 f2 28 ef 0c cc 09 0f 09 6e 0b 67 0b 73 29 35 13first opaque page of dense non-zero data
7171 34 0d e5 0a 00 00 00 00 00 00 00 00 00 00 00 00short run of values, then zeros
7272 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00zero-filled in this capture
7373 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00zero-filled in this capture

More launches confirmed the shape: a 17-byte header is always the first thing on the wire, and the bulky block follows only once a Beyblade actually flies. Its opening bytes repeat the same skeleton — a0, then b0 through b7, then 70 through 73 — which reads as page tags, so the data behind each tag had to be isolated one at a time.

Splitting the metadata block

Offset arithmetic did most of the work. Compared against the same position in the header record, the tenth byte advanced by exactly one per successful launch, i.e. a launch counter. The fixed tail 35 b4 04 51 c4 da survived every capture and resolved as the BLE device's address written backwards. What made no sense yet was why bytes 8 and 9 — the pair a2 0c in this sample — seemed to be copied into the b* pages.

Endianness, or how 41,484 became a plausible spin rate

Several launches later the grid looked like this:

a0 3a 00 00 ff 00 00 62 10 03 00 35 b4 04 51 c4 da
b0 a2 0c 62 10 95 0d 00 00 00 00 00 00 00 00 00 00
b1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b2 ...

New pairs surfaced in the b* pages in strict order: first a2 0c, then 62 10, and finally 95 0d. Converted naively to decimal each one was ridiculous — a2 0c alone yields 41,484, and no top pulled by hand spins anywhere near that. :)

The correction came from context rather than cleverness: an average launch reaches roughly 5,000 RPM. So the two bytes were swapped, and reading a2 0c as 0c a2 converts to 3,234 — finally believable.

Little-endian ordering, least significant byte first, is the standing Bluetooth Low Energy (BLE) convention, which is why the swap was legitimate. Launch values were cracked; the small header still was not, and it held a clue of its own. Every time bytes 8 and 9 (e.g. 62 10) drifted, the light report after the launch drifted too: no usual blinking green but orange → red → green. Those launches were different, and the decoded trio says why:

0c a2 → 3,234
10 62 → 4,194 🔥
0d 95 → 3,477

The largest value persisted — a stored high score, mystery solved.

Header leftovers: a readiness flag and a shrinking byte

Two behaviours closed out the header. Drop or detach a Beyblade without firing it and the LED blinks red while the record changes shape:

ScenarioObserved bytes
Beyblade attacheda0 3a 00 04 ff 00 00 02 16 1d 00 35 b4 04 51 c4 da
Dropped, no launchesa0 3a 00 00 ff 00 00 02 16 1d 00 35 b4 04 51 c4 da
Successfull launch (bulky payload)a0 3a 00 00 ff 00 00 02 16 1e 00 35 b4 04 51 c4 da, then b0: d6 0f c1 03 88 13 02 16 f0 14 c7 14 4e 11 98 13, then b1: ...

The delta sits in a single pair. The sequence 00 04 behaves like a status flag, most likely "ready for launch": a failed attempt reverts those bytes to 00 00 while the launch counter at byte 10 stays frozen, and a clean launch increments that counter while the status bytes settle back to 00 00.

The slower observation involved byte 5 (ff, or 255 in decimal, in the a0 page), which shrank steadily over the following months. At the time of writing this post, for example, its value was da, or 218 in decimal. Battery level is the likeliest explanation, and why its value differs in the larger payload remains unresolved — one day.

Launchmaxxing: finding a 50-entry ring the hard way

Page b7 was the interesting boundary condition, and reaching it meant 50 additional launches. At that point the values in page b6 halted at position 6 (counting from 1), leaving a gap padded with 00 00. The 50th launch bulky payload (32 hex) and the 51st launch bulky payload (33 hex) make the eviction visible:

Page50th launch51st launch
a0a0 3a 00 00 ff 00 00 61 16 32 00 35 b4 04 51 c4 daa0 3a 00 00 ff 00 00 61 16 33 00 35 b4 04 51 c4 da
b0b0 d6 0f c1 03 88 13 02 16 f0 14 c7 14 4e 11 98 13b0 c1 03 88 13 02 16 f0 14 c7 14 4e 11 98 13 18 12
b1b1 18 12 59 0b 1b 10 b3 09 f8 0c 29 0d 88 06 a2 09b1 59 0b 1b 10 b3 09 f8 0c 29 0d 88 06 a2 09 a3 0d
b2b2 a3 0d 3c 0a 22 0b c4 0a 04 01 67 0c 91 0d 4e 04b2 3c 0a 22 0b c4 0a 04 01 67 0c 91 0d 4e 04 09 0b
b3b3 09 0b 74 03 86 0d 35 0b a0 04 0e 0b e7 13 b3 15b3 74 03 86 0d 35 0b a0 04 0e 0b e7 13 b3 15 38 05
b4b4 38 05 9e 04 c8 13 61 16 dd 10 2e 15 b5 0e b2 0bb4 9e 04 c8 13 61 16 dd 10 2e 15 b5 0e b2 0b 48 0c
b5b5 48 0c a6 0c a9 0c 2d 0d 20 0d cb 0d 55 0e 47 0db5 a6 0c a9 0c 2d 0d 20 0d cb 0d 55 0e 47 0d bc 0d
b6b6 bc 0d 36 0d 00 00 61 16 32 00 32 00 00 00 00 00b6 36 0d 2c 13 00 00 61 16 33 00 32 00 00 00 00 00
b7b7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 dcb7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 37
7070 ...70 ...

FIFO — realised at a volume that woke the neighbourhood.

Reading the two columns against each other gives the storage rule. A maximum of 50 launches can be recorded: beyond that, the oldest entry at the beginning of b0 is discarded, and the newest launch value is written into byte position 4 of page b6 (2c 13). Past the padding bytes at positions 6 and 7 the same high score reappears (61 16), followed by the total number of launches (33 00 → 51) and the number of stored entries (32 00 → 50, the maximum).

The very last byte on page b7 was the simplest find of all: a checksum. Add together every data byte across the b* pages, skip each page's tag byte plus the checksum byte itself, then take the result modulo 256.

Going the other way: three distinct scenarios on the write characteristic

Reading 0x55c4f002 had been generous, which left 0x55c4f001 unexplained. Solving it meant installing the Beyblade X app and sniffing the Bluetooth traffic straight from an iPhone — tedious, because an official Apple Bluetooth debugging profile had to sit on the iPhone while a cable kept it connected to a Mac. Once that was running, every interaction mapped onto three distinct scenarios.

Command 0x74 answered with the grid in full, minus the opaque 7* pages:

PageResponse bytes
b0b0 a2 0c 71 0f 06 14 f4 13 55 11 88 13 bd 17 23 15
b1b1 46 13 c9 11 03 0c 1f 0f 46 0e 4d 1b 00 00 00 00
b2b2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b3b3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b4b4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b5b5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b6b6 00 00 00 00 00 00 4d 1b 0e 00 0e 00 00 00 00 00
b7b7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c

Command 0x51 answered with a single line — the 17-byte header itself:

a0 3a 00 00 d3 00 00 4d 1b 0e 00 35 b4 04 51 c4 da

Command 0x75 answered with an a1 record never seen before plus a zeroed grid, i.e. the whole internal dataset cleared:

PageResponse bytes
a1a1 00 00 00
a0a0 3a 00 00 d3 00 00 00 00 00 00 35 b4 04 51 c4 da
b0b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b1b1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b2b2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b3b3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b4b4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b5b5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b6b6 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b7b7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

The available operations were obvious from there: one command returns the full list of launch values, another retrieves the initial metadata, and the last clears the entire internal database. The destructive one was the easiest to recognise, precisely because the Beybattle Pass replied with that extra a1 page.

The 7* pages: still the unlucky ones

Anyone who reads this far is asking the same question. The answer is unsatisfying — To this day I still have not fully worked out what the values stored in these pages represent, and plotting them in a spreadsheet made nothing jump out.

Perhaps someone reading is better at this than I am. My own theory is physical data arriving directly from the Beybattle Pass sensor, and that framing also fits the availability rule: the 7* pages appear only when a Beyblade is actually launched, never when the accessory is queried through the Write Without Response commands.

With that, the heavy part of the reverse-engineering job was finally over.

DiZZi 0.2: an anime AI companion rebuilt as a scoreboard

A fully reverse engineered protocol is a licence to build, so the project continued: my own Bluetooth app, taken to tournaments, used to settle arguments with friends over who could achieve the highest spin score.

Designing the UI is the part of any project I save time for, and the brief came from nostalgia rather than a mood board. Rewatching the original anime from the early 2000s made the target obvious — DiZZi 0.1, the AI companion that lived inside Kenny's computer. Apparently exclusive to the Western version of the anime, DiZZi had a distinctive voice and a sharp, sassy personality: analysing data from Beyblade battles, offering tips to Kenny and his friends, occasionally roasting him.

Execution started with a screenshot of the frame above handed to Claude Code for an initial layout sketch; after a few measurement tweaks the reproduction is almost pixel-perfect. For functionality, the entire BLE protocol recovered from Takara Tomy feeds five surfaces:

  • Score for the launch just taken
  • History of previous launches, color-coded by launch intensity
  • The highest score
  • Battery level
  • The AI Interface

Enough, but not maximal. If the data was going on screen anyway, why not recreate DiZZi herself — sassy personality intact — and let her roast my launches and my Beyblading skills? We do live in the AI era 💀🔫

The architecture borrows the shape used for Max Headbox, with two swaps: Kokoro TTS for the voice, and all Ollama requests handled directly by the Express.js server.

In detail: the React frontend talks to the Express.js backend, which holds the BLE connection to BEYBLADE_TOOL01 and automatically subscribes to its Notify characteristic. As soon as a new launch is detected, the BLE decoder module retrieves the launch data, and Express.js queries the Ollama API using the gemma3:1b model for a read on the launch trends. The instruction handed to the model stays deliberately short — it may roast the player by judging the result or be also be kind to him when the launch power is actually good; it is told that higher RPM is better, with under 3000 weak, 3000-7000 alright and over 7000 excellent; and it must Reply with ONE short sentence (max 15 words) about how the player's launches are going.

Single-turn and event-triggered, this is obviously not a fully fledged agent like Max Headbox. Small models such as gemma3:1b are poor at arithmetic, so no raw numbers reach the prompt: the trend is pre-computed first by a helper that takes the newest value, collects the three launches before it, and, if none exist, reports "First launch: ... RPM." Otherwise it averages those previous launches, measures the difference, and classifies it — diff > 300 improving, diff < -300 getting worse, anything in between about the same — before emitting a summary of previous RPMs, the average, the last launch and the trend.

Live Beybattle Pass data reaches the main React frontend over WebSockets, while a few REST endpoints trigger the specific Bluetooth commands (0x74, 0x75, and 0x51). State management only had to mirror four scenarios, all derived directly from the device's events:

  • A Bey is attached
  • A Bey is launched
  • A Bey is dropped (failed launch)
  • The BLE device connects or disconnects

The same states drive the animations of the spinning 3D Beyblade model on the main screen.

The cherry on top is the VoiceFlare component on the left. Whenever the TTS wav file comes back from the backend, the React frontend plays it through the Web Audio API and pipes it into an AnalyserNode, which returns the frequency spectrum of DiZZi's voice on every animation frame. Only the lower ~60% of the bins are kept, and they drive a small canvas animation of blue and orange flame-like peaks and light streaks mirrored around a glowing horizon, very close to the sequence from the anime. Wiring it up is four steps: create the analyser from the audio context, set its fftSize to 256, connect the source into the analyser, and connect the analyser onward to the context destination.

Closing note from the ItInsightsWorld bench: the accessory that refused to be opened surrendered its counter, its little-endian RPMs, its status flag, its 50-launch window and its checksum, and that page map then became a talking companion. Decoder, prompt and interface all sit in the project's GitHub repository — if a reader untangles those stubborn 7* pages first, we will happily publish the correction here.

Brand logo

IT Insights

Cloud & Infrastructure Practice Media for Enterprise Technology Decision-Makers

Cloud ComputingSecuritySoftware DevelopmentAI ApplicationsStartupsGeneralAI Data News Global

© 2026 IT Insights.

Cookie Notice

We use cookies to improve your experience and analyze website traffic. Read our Privacy Policy to learn more.