Two BLE Provisioning Protocols for Android IoT Devices, Side by Side
Most IoT SDKs hide these protocol details behind a library. Seeing the raw byte structures and state machines makes it easier to debug provisioning failures, support devices from different vendors in a single app, or build a custom provisioning flow when the vendor SDK is too heavy or unavailable.
IoT device provisioning on Android often means juggling multiple proprietary BLE protocols. This implementation walks through two of them: CoolKit uses an AES-encrypted handshake over GATT characteristics `bbb0`/`bbb1` with a phased command set for WiFi scanning, connection, and cloud registration. TanGe and similar IoT devices take a simpler route — a fixed 78-byte WiFi configuration packet written to characteristic `9999`, with single-byte ACKs or JSON responses coming back on `8888`.
Both flows share the same skeleton: scan for devices by name prefix, connect over BLE, deliver SSID and password, then poll a cloud endpoint for binding confirmation. The differences live in the wire format and the handshake. CoolKit demands a secret-key exchange before any WiFi commands move; TanGe just expects the 78-byte payload with a frame header and footer.
Timeout and retry logic is baked in at multiple levels — a 180-second total timeout, a separate 3-minute watchdog for TanGe devices, up to three automatic reconnection attempts, and a 5-second WiFi scan polling loop. Resource cleanup funnels through a single `resetData()` call that tears down scans, closes the GATT connection, and cancels all RxJava disposables.
Embedding two completely different BLE protocols in one app is common in Chinese IoT ecosystems where a single OEM ships devices built on different module vendors' stacks.
The CoolKit protocol's AES handshake adds a meaningful security layer — without the secret key fetched from the cloud, an attacker can't inject WiFi credentials even if they connect to the device over BLE.
TanGe's 78-byte fixed packet is easier to implement but sends the WiFi password in what appears to be plaintext (UTF-8 padded with null bytes), which is a weaker security posture if the BLE link itself isn't encrypted.
The static state machine approach in `BleScanUtils` keeps connection lifecycle manageable but can become brittle when adding a third or fourth protocol — each new device type risks bloating the state transitions.