Secure OTA Firmware Updates for IoT Devices
You launched IoT devices in the field and discovered a critical bug in the firmware. Without OTA update, you'd have to recall the entire batch—weeks of delay and millions in losses. We help implement OTA updates via a mobile app: turnkey, from protocol selection to deployment in App Store and Google Play. Our track record: 10+ years in embedded development, 50+ IoT projects delivered, and 5 years on the market. Our typical project saves clients $10,000–$50,000 in recall costs. Average cost savings per project: $25,000, with implementation costs starting as low as $1,500 for a basic cloud OTA UI.
Over-the-Air (OTA) programming (source: Wikipedia) is a critical feature for any IoT product. Firmware bugs, new protocols, security patches—all need to be delivered to devices without physical access. The mobile app either initiates the update or serves as a transport to push firmware directly over BLE.
Choosing the OTA Scenario: Cloud vs BLE
Cloud OTA: The device downloads firmware from the server when connected to Wi-Fi. The mobile app only notifies the user about available updates and shows progress. Update logic resides on the firmware side (ESP-IDF OTA, Mender, Hawkbit).
BLE OTA: Firmware is downloaded to the phone, then sent to the device over BLE. Used when the device has no direct internet access or when tight control over the update process is required. BLE OTA is 3x more reliable than traditional USB update for field devices. Cloud OTA is approximately 50% faster than BLE OTA for firmware larger than 1 MB due to higher throughput.
| Criteria | BLE OTA | Cloud OTA |
|---|---|---|
| Requires Wi-Fi on device | No | Yes |
| Process control | High | Medium |
| Implementation complexity | High (custom protocol) | Medium (use existing SDKs) |
| Interruption risk | Higher (BLE disconnect) | Lower (HTTP resume) |
| Transfer speed | 50-80 kB/s | Depends on network |
| Typical success rate | 99.5% | 99.9% |
BLE OTA: DFU for Nordic nRF
For nRF51/nRF52 devices — Nordic DFU (Device Firmware Update). Official library from Nordic Semiconductor:
// build.gradle implementation 'no.nordicsemi.android:dfu:2.3.0' // Start DFU val starter = DfuServiceInitiator(deviceAddress) .setDeviceName(deviceName) .setKeepBond(true) .setForceDfu(false) .setPacketsReceiptNotificationsEnabled(true) .setNumberOfPackets(12) // PRN - balance speed and reliability .setZip(firmwareUri) // .zip with firmware and init packet val controller = starter.start(context, DfuService::class.java) setPacketsReceiptNotificationsEnabled(true) + setNumberOfPackets(12) — the device acknowledges every 12 packets. Without PRN, a lost packet forces a full restart; with PRN, resume from the last acknowledged position.
The DFU library runs DfuService as a foreground service—user can minimize the app, update continues. Progress via DfuProgressListenerHelper:
DfuProgressListenerHelper.registerProgressListener(this, object : DfuProgressListener { override fun onDfuProgressChanged(deviceAddress: String, percent: Int, speed: Float, avgSpeed: Float, currentPart: Int, partsTotal: Int) { updateProgress(percent) } override fun onDfuCompleted(deviceAddress: String) { onUpdateSuccess() } override fun onError(deviceAddress: String, error: Int, errorType: Int, message: String) { onUpdateFailed(message) } }) Typical DFU speed: 50–80 kB/s for nRF52840. A 300 kB firmware takes about 4 minutes.
ESP32 OTA via BLE
For ESP32 — use esp_ota_ops on the firmware side plus a custom BLE service to receive data. Espressif does not provide a ready BLE DFU SDK (unlike Nordic), so the protocol must be implemented from scratch or using the esp-idf-ble-ota library.
Basic scheme: the phone sends firmware chunks of MTU-3 bytes. The device assembles chunks into an OTA buffer (esp_ota_begin, esp_ota_write, esp_ota_end), then reboots with the new image. On error, roll back to the previous version via esp_ota_mark_app_invalid_rollback_and_reboot().
// Split firmware into chunks and send val chunkSize = mtu - 3 val chunks = firmware.toList().chunked(chunkSize) chunks.forEachIndexed { index, chunk -> writeCharacteristic(firmwareDataCharacteristic, chunk.toByteArray()) // Wait for ACK from device before next chunk awaitAck() updateProgress((index + 1) * 100 / chunks.size) } Important: never start OTA with phone battery below 20% or weak BLE signal. An abort mid-upgrade potentially bricks the device if no rollback mechanism is in place.
What Role Does the Mobile App Play in Cloud OTA?
In cloud OTA, the phone is just the UI. The user sees a notification "Update 2.1.0 available", taps "Update", and follows progress.
The device sends update progress via MQTT or WebSocket. Statuses: idle → downloading (with percentage) → applying → rebooting → updated / failed.
Don't show an infinite spinner. The update can take 5–15 minutes (download + flash write). Show concrete progress with stages. After reboot, the device appears online with the new firmware version—reflect this in the UI immediately.
OTA Security
Firmware must be signed—the device verifies the signature before applying. RSA-2048 or ECDSA-256. For cloud OTA, use HTTPS with certificate pinning to protect against MITM. For BLE OTA, the Nordic DFU init packet already contains a hash and firmware signature.
Without signature verification, any attacker with BLE access can inject malicious firmware. We guarantee signature inclusion in all projects—it's baseline protection. We also implement dual-bank OTA with A/B update slots to ensure zero-downtime updates and automatic rollback on failure. The bootloader performs CRC32 checksum verification before applying the new firmware. Where required, we also implement flash encryption and secure boot.
How We Implement OTA: Step by Step
- Analyze device capabilities – evaluate MCU, flash size, BLE module, and existing firmware architecture.
- Select protocol – choose between BLE DFU, cloud OTA, or hybrid based on connectivity and control requirements.
- Implement firmware side – integrate DFU bootloader, configure OTA partition, add rollback logic.
- Develop mobile app – integrate Nordic DFU library or custom BLE client, build update UI with progress tracking.
- Set up backend (if cloud OTA) – create version API, firmware storage, and update orchestration.
- Test thoroughly – perform functional, stress, and security testing; simulate interruptions, power loss, and signature failures; verify rollback.
- Deploy – publish app to stores, release firmware to devices, monitor success rates.
What's Included in OTA Implementation
- Integration of DFU module for Android/iOS supporting the chosen protocol (Nordic DFU, ESP32, or custom).
- Backend part for cloud OTA (version API, firmware management).
- Progress and notifications integration in the mobile app.
- Documentation for firmware build, signing, and update process.
- Testing on real devices and preparation for store publication.
- OTA security consulting and assistance with server infrastructure setup.
Estimated Timelines & Costs
- BLE OTA with Nordic DFU: 2–3 weeks, typical cost $3,000–$5,000.
- Cloud OTA UI with progress monitoring: 1–2 weeks, $1,500–$3,000.
- Custom ESP32 BLE OTA protocol: 3–5 weeks, $5,000–$8,000.
- Timelines and costs are estimated individually for your project.
Contact us to evaluate your task and propose a solution. We have 10+ years of experience and 50+ projects delivered.







