OTA-оновлення прошивки IoT-пристроїв через мобільний додаток
OTA (Over-The-Air) оновлення прошивки — критично важлива функція для будь-якого IoT-продукту. Баги в прошивці, нові протоколи, патчі безпеки — всі це потребує доставлення на пристрої без фізичного доступу до них. Мобільний додаток або ініціює оновлення, або служить транспортом для передачі прошивки напрямки через BLE.
Два сценарії OTA
Cloud OTA: Пристрій самостійно скачує прошивку з сервера, коли опиняється у Wi-Fi. Мобільний додаток лише повідомляє користувача про доступне оновлення та показує прогрес. Логіка оновлення — на стороні прошивки (ESP-IDF OTA, Mender, Hawkbit).
BLE OTA: Прошивка скачується на телефон, телефон передає її на пристрій через BLE. Використовується коли пристрій не має прямого виходу в інтернет або коли потрібен жорсткий контроль над процесом оновлення.
BLE OTA: DFU для Nordic nRF
Для пристроїв nRF51/nRF52 — Nordic DFU (Device Firmware Update). Офіційна бібліотека від Nordic Semiconductor:
// build.gradle
implementation 'no.nordicsemi.android:dfu:2.3.0'
// Запуск DFU
val starter = DfuServiceInitiator(deviceAddress)
.setDeviceName(deviceName)
.setKeepBond(true)
.setForceDfu(false)
.setPacketsReceiptNotificationsEnabled(true)
.setNumberOfPackets(12) // PRN - баланс швидкості та надійності
.setZip(firmwareUri) // .zip з прошивкою та init packet
val controller = starter.start(context, DfuService::class.java)
setPacketsReceiptNotificationsEnabled(true) + setNumberOfPackets(12) — пристрій підтверджує кожні 12 пакетів. Без PRN втрата пакету означає перезавантаження всього. З PRN — продовження з останньої підтвердженої позиції.
DFU-бібліотека запускає DfuService як foreground service — користувач може згорнути додаток, оновлення продовжиться. Прогрес через 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)
}
})
Типова швидкість DFU: 50–80 кб/с для nRF52840. Прошивка 200 кб — близько 3 хвилин.
ESP32 OTA через BLE
Для ESP32 — esp_ota_ops на стороні пристрою + користувацький BLE-сервіс для приймання даних. Espressif не надає готового BLE DFU SDK (на відміну від Nordic), тому протокол потребує самостійної реалізації або використання бібліотеки esp-idf-ble-ota.
Базова схема: телефон відправляє прошивку чанками по MTU-3 байти. Пристрій збирає прошивку в OTA-буфер (esp_ota_begin, esp_ota_write, esp_ota_end), потім перезавантажується з новим образом. При помилці — rollback на попередню версію через esp_ota_mark_app_invalid_rollback_and_reboot().
// Розбивка прошивки на чанки та відправка
val chunkSize = mtu - 3
val chunks = firmware.toList().chunked(chunkSize)
chunks.forEachIndexed { index, chunk ->
writeCharacteristic(firmwareDataCharacteristic, chunk.toByteArray())
// Очікування ACK від пристрою перед наступним чанком
awaitAck()
updateProgress((index + 1) * 100 / chunks.size)
}
Важливо: ніколи не починайте OTA при заряді телефону нижче 20% та слабому BLE-сигналі. Розрив серед прошивки — потенційна цегла, якщо на пристрої немає механізму rollback.
Cloud OTA: Роль мобільного додатку
При cloud OTA телефон — лише UI. Користувач бачить «Доступно оновлення 2.1.0», натискає «Оновити», стежить за прогресом.
Прогрес оновлення пристрій відправляє через MQTT або WebSocket. Статуси: idle → downloading (з відсотком) → applying → rebooting → updated / failed.
Не показуйте нескінченний спіннер. Оновлення може займати 5–15 хвилин (скачування + запис flash). Показуйте конкретний прогрес з етапами. Після перезавантаження пристрій з'явиться у мережі з новою версією прошивки — це треба одразу відобразити у UI.
Безпека OTA
Прошивка має бути підписана — пристрій перевіряє підпис перед застосуванням. RSA-2048 або ECDSA-256. При cloud OTA — HTTPS з certificate pinning для захисту від MITM. Для BLE OTA — init packet Nordic DFU вже містить hash та підпис.
Без перевірки підпису будь-який зловмисник з доступом до BLE може залити шкідливу прошивку.
Реалізація BLE OTA з Nordic DFU: 2–3 тижні. Cloud OTA UI з моніторингом прогресу: 1–2 тижні. Користувацький ESP32 BLE OTA протокол: 3–5 тижнів.







