The Whoop I wear every day has an accelerometer and a gyroscope that sample 100 times a second. The official app uses them for steps, sleep and strain. I wanted to know if they were good enough for something more fun: a Guitar Hero style drums game, with a band on each wrist. The Whoop on the left, an Apple Watch on the right, notes sliding down the track and you hitting the air on time.
It works. And the interesting part was not the game, but the problem I had to solve to make it work.
How it is put together
A small Python bridge connects to the Whoop over Bluetooth, switches on its motion sensor, detects hits and broadcasts them over a WebSocket. The game runs in the browser: Three.js served as plain ES modules, no build step, and the drum kit is a Web Audio synth with no samples. The Apple Watch sends its motion to the same bridge over Wi-Fi, and the keyboard plays too, for testing without wearables.
Detecting a hit is the simplest part. At rest the acceleration is 1 g, gravity. A hit is a spike above 2.5 g, followed by 300 ms of quiet so the rebound does not count twice. No machine learning.
The problem: the Whoop is late
The first thing I did was measure the delay. The Whoop samples at 100 Hz, but it does not send every sample: it collects a whole second and sends it as one packet. So every hit reaches the Mac between 0.5 and 1 second after it happened.
In a rhythm game that is forever. The window for a Perfect is 70 ms.
It looked like the end of the project, until I looked at what each packet carries: every sample comes with the exact time it was measured. So the game does not judge a hit by when it arrived, but by when it happened. A hit that shows up 900 ms late, but that you landed right on the beat, is a Perfect.
Two more details keep the delay from being felt. The music is played by the game, not by your hit, so the song never drifts. And a note is not called a miss until the longest time that band can take to deliver a hit has passed. Otherwise the game would say "miss" and change its mind a second later.
The second problem: the feedback is late too
A correct score is not enough. If you hit and the drum lights up a second later, it feels broken even when the final number is right.
The fix is a small trick. If you have been landing the notes on the slow hand, the game assumes you will land the next one and makes it burst at its exact time. When the real hit arrives, it only confirms the note, or turns it into a miss. On the slow lane the guide drum also plays louder, standing in for the sound of your own hit. It is what online games do with network lag: predict, then correct.
Calibrate instead of guessing
Every device has its own delay, and its clock may be slightly off from the Mac's. Instead of modelling all of that, there is a Calibrate screen: eight clicks, one every two seconds, and you hit along with each hand. The game takes the median gap between your hits and the clicks, and that is the correction for that device. One number absorbs the sensor delay, the clock offset and even the way you hit.
The clicks are slow on purpose. With a large clock offset, a fast beat would pair each hit with the wrong click.
What I learned
Before dropping an idea because of latency, check whether the data carries timestamps. The Whoop's delay looked fatal. It was not, because what matters in a rhythm game is not when you find out about a hit, but when it happened. Measuring first changed the whole design.
Latency decides which games you can make. The same technique works for rhythm and for nothing real-time: aiming or dodging with the Whoop hand is impossible. So the list of games is drums, boxing to the beat of the music, and one about charging energy with your breathing. No reflex games.
Getting the number right is not enough; it has to feel right. The score was correct from day one. What was missing was immediate feedback, and that came from prediction, not from more precision.
Real hardware always corrects the README. Several things only showed up with the band in my hand:
- The Whoop only enters pairing mode off the wrist: take it off, wait for the lights to go out, and tap it firmly with two fingers until it blinks blue.
- It pairs with one device at a time, so the phone's Bluetooth has to be off.
- The motion sensor takes about 10 seconds to start sending data. My first "nothing is arriving" warning fired too early.
- If the band refuses to pair, retrying forever only drains its battery. The bridge now gives up after three refusals.
- When the connection works, the band vibrates. That buzz turned out to be a better "it works" signal than any log line.
Sometimes the no-code path is the best one. For the Apple Watch I built a native Watch and iPhone app. With a free Apple account, Xcode never found my watch, which was stuck on watchOS 26 next to an iPhone on iOS 27. The way out was Sensor Logger, a free App Store app that streams the watch's motion over HTTP. The bridge receives it, detects the hits, and that is it, no Xcode. Its data arrives up to 2 seconds late, but the same timestamp technique takes care of it.
Read the license of what you use as a reference. The Whoop's Bluetooth protocol is not public. I implemented it from the documentation of the open source project noop. The code is my own, but noop's license is non-commercial, and I wrote that down in the project before thinking about publishing anything.
What is next
Boxing, with combos to the beat. The force of the hit will matter less than I hoped, since the Whoop's accelerometer saturates around 8 g and every hard punch reads about the same. And Ki: charge energy with your breathing and your heart rate, which the Whoop also streams live, then release it with both hands.
An independent project, not affiliated with WHOOP, Inc. or Apple. Only use it with devices you own.