OTA Firmware Updates from Mobile Apps: A Practical Guide
Over-the-air (OTA) firmware updates are essential for any connected device. But implementing them from a mobile app — especially over BLE — is one of the trickiest challenges in IoT development.
A failed OTA update can brick a device. A poorly designed update process can frustrate users. Here's how to get it right.
Understanding OTA Over BLE
BLE's limited bandwidth (~1 Mbps theoretical, ~100 KB/s practical) makes firmware updates slow. A 200 KB firmware image takes 2-3 minutes over BLE. Your update process needs to handle this gracefully.
Nordic DFU vs Custom Protocol
Nordic DFU (Device Firmware Update) is the gold standard for nRF-based devices. It's battle-tested, well-documented, and has mobile SDKs for both iOS and Android.
Custom OTA protocols give you flexibility but require more testing. Use them when Nordic DFU doesn't fit your hardware.
The OTA Update Flow
A robust OTA update follows this sequence:
1. Pre-Update Checks
- Verify device is in DFU mode
- Check battery level (>30% recommended)
- Verify firmware file integrity (checksum)
- Confirm firmware compatibility with device model
2. Firmware Transfer
- Split firmware into BLE MTU-sized packets
- Send packets sequentially with acknowledgment
- Implement pause/resume capability
- Show progress to the user
3. Post-Update Verification
- Wait for device reboot
- Verify new firmware version
- Run basic functionality tests
- Report success or failure
Implementation Details
Packet Size and MTU
Negotiate the maximum MTU before starting the transfer. Larger MTU = fewer packets = faster updates.
// Request maximum MTU
mtu = requestMtu(247) // Max for BLE 4.2+
packetSize = mtu - 3 // 3 bytes for ATT headerProgress Tracking
Calculate progress as: packetsSent / totalPackets * 100
Update the UI every 5-10% to avoid overwhelming the main thread.
Error Recovery
If a packet fails:
1. Retry the same packet (up to 3 times)
2. If all retries fail, abort and report error
3. Device should remain in DFU mode for retry
Never leave a device in a half-updated state.
Mobile App Implementation
iOS (Swift)
Use CoreBluetooth with the Nordic DFU library. Handle background mode carefully — iOS may suspend BLE operations if the app goes to the background.
Android (Kotlin)
Use the Nordic DFU library for Android. Android handles background BLE better than iOS, but still implement foreground service for long updates.
Flutter
Use flutter_blue_plus with a custom DFU implementation. Be aware of platform channel overhead during high-frequency packet transfers.
Production Deployment Strategy
Staged Rollouts
Never push firmware to all devices at once:
1. Update 5% of devices first
2. Monitor for errors over 24 hours
3. If clean, expand to 25%
4. Then 100%
Rollback Capability
Keep the previous firmware version available. If the new version has issues, users should be able to roll back.
User Communication
Tell users:
- What's being updated and why
- How long it will take
- What to do (keep app open, stay in range)
- What happens if it fails
Common Pitfalls
Pitfall 1: Not Testing with Weak Signal
OTA updates at the edge of BLE range will fail. Test at various distances.
Pitfall 2: Ignoring Battery Level
Updating on low battery can brick devices. Always check battery before starting.
Pitfall 3: No Timeout
OTA updates can hang. Implement a timeout (5 minutes typical) and abort gracefully.
Pitfall 4: Blocking the UI
Don't block the entire app during OTA. Let users navigate away while the update continues in the background.
Conclusion
OTA firmware updates from mobile apps are complex but essential. The key is thorough testing, graceful error handling, and clear user communication.
Get it right, and your devices stay up-to-date and secure. Get it wrong, and you're shipping replacement hardware.
Need help implementing OTA updates for your IoT product? Let's connect.