How we did it
How we worked out the Xiaomi Smart Band 10
The goal: use the Xiaomi Smart Band 10 / 10 Pro with our own iPhone app, without Mi Fitness or a Xiaomi account, with the data staying on the phone.
-
1. Desk research
- We read the Xiaomi code in Gadgetbridge (an open source Android app): connection, authentication, encryption, commands and file formats.
- We compared it with the protobuf schemas of AstroBox, an iOS app that supports the Band 10.
- Conclusion: the Band 10 speaks Xiaomi's new protocol, and doing this over BLE on an iPhone was very likely possible.
-
2. First contact from a Mac
- In a BLE scan the band showed up with Xiaomi's
FE95advertisement. - Connecting from the Mac timed out twice: the band only accepts the iPhone it is paired with.
- nRF Connect showed that the band doesn't advertise at all while it's connected to the iPhone.
- In a BLE scan the band showed up with Xiaomi's
-
3. A test app on the iPhone
We picked up the band that iOS already keeps connected, without pairing again. Its GATT table had the
FE95service with the005E(read) and005F(write) characteristics: the BLE V2 channel was open. This was the make-or-break moment of the project. -
4. The key
- The band wants a 16-byte auth key that Xiaomi's server creates when the band is first paired.
- On an iPhone that key sits in Files → Mi Fitness, inside a cache database.
- The app asks you to pick that folder, reads the key on the phone and keeps it in the Keychain. The key is never sent anywhere.
-
5. The handshake
- The phone and the band swap random numbers (nonces).
- Session keys are derived from the key and those numbers with HKDF-SHA256 (
"miwear-auth"). When the band's HMAC matches, the key is right. - In the last step we introduce ourselves as
device_type = iOS, encrypted with AES-CCM.
After the handshake, every message is protobuf encrypted with AES-128-CTR. -
6. The encrypted channel and the first command
- Messages travel as AES-128-CTR encrypted protobuf, in frames that start with
a5 a5and carry a CRC16. - The first command was the battery: 46%. We read the same value from the standard BLE battery service too, which proved the decryption right.
46%the answer to the first command: batteryThe frame of one message on the encrypted channel. - Messages travel as AES-128-CTR encrypted protobuf, in frames that start with
-
7. Independent check
We checked the protocol code against 13 test vectors with a separate Python implementation on the Mac.
-
8. Live data
One command makes the band stream live stats: steps, calories, heart rate. We turn it off after 2 minutes to save the battery.
-
9. Getting along with Mi Fitness
- There can't be two sessions on the same channel. When our app didn't let go of the channel, Mi Fitness's sync got stuck; we added releasing the channel.
- When Mi Fitness acknowledges (ACKs) the files, the band deletes them.
-
10. Other commands
Sending notifications, finding the band by making it vibrate, setting the clock.
-
11. History (activity files)
- The band lists the files for today and for past days.
- Each file has a 7-byte ID: time, time zone, version and kind (per-minute data, daily summary, sleep, sleep stages, manual readings).
- Files arrive in chunks and end with a CRC32.
- We never send the ACK, so nothing is deleted from the band.
-
12. File formats
- We wrote the formats down first. Then we wrote the code from scratch: a Python reference parser, and a Swift parser that gives exactly the same output.
- 147 tests pass, and it doesn't crash even on 37,000 corrupted files.
147tests passing37,000corrupted files, no crash -
13. The product
- From this data Freeband works out its own Sleep, Recovery and Strain scores; each score shows its contributors and how confident it is.
- Alongside it there is an optional API and web panel on Cloudflare.
-
14. Still open
- A real sleep file hasn't been verified yet.
- We don't know yet what the
2/110message, which the band sends on its own, means. - Pairing a brand-new band without Mi Fitness isn't possible for now, because the key is created on Xiaomi's server.
Thanks
- GadgetbridgeThe most detailed open source account of the protocol.
- AstroBoxBLE on iOS, the
device_type = iOShint and the protobuf schemas. - xiaomi-band-ios-exportWhere the key lives on an iPhone.
- blueband-mapOne of the open source experiments with BLE on the Band 10.
- band9-rust-iosOne of the open source experiments with BLE on the Band 10.