Реализация BLE Provisioning IoT-устройств через мобильное приложение

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация BLE Provisioning IoT-устройств через мобильное приложение
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    760
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    646
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1056
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    878
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    450

Реализация BLE Provisioning IoT-устройств через мобильное приложение

BLE Provisioning — передача Wi-Fi credentials и конфигурации IoT-устройству через Bluetooth Low Energy. Это лучший метод для пользовательского UX: не нужно переключать Wi-Fi сети на телефоне, работает надёжнее SmartConfig, не зависит от настроек роутера. Для ESP32, nRF52, Nordic-чипов — предпочтительный выбор.

GATT-архитектура для Provisioning

Устройство в режиме provisioning рекламирует BLE-сервис. Мобильное приложение подключается как GATT-клиент и пишет данные в характеристики сервиса. Стандартная схема для ESP-IDF:

  • Service UUID: 021a9004-0382-4aba-aa36-ec4d15d65e0e (Espressif Provisioning)
  • Характеристика конфигурации: write (SSID, password, auth mode)
  • Характеристика статуса: notify (результат подключения устройства к сети)

После записи credentials устройство пытается подключиться к Wi-Fi и уведомляет телефон через notify-характеристику об успехе или ошибке.

Android BLE API: что идёт не так

BLE на Android — источник боли. Разные производители реализуют стек по-разному. BluetoothGatt.writeCharacteristic() может вернуть true при вызове, но onCharacteristicWrite придёт со статусом GATT_ERROR (133) — самая частая необъяснимая ошибка.

Правильный паттерн — очередь команд. BLE не поддерживает параллельные GATT-операции:

class BleCommandQueue {
    private val queue: LinkedList<() -> Unit> = LinkedList()
    private var isExecuting = false

    fun enqueue(command: () -> Unit) {
        queue.add(command)
        if (!isExecuting) executeNext()
    }

    fun onCommandComplete() {
        isExecuting = false
        executeNext()
    }

    private fun executeNext() {
        if (queue.isEmpty()) return
        isExecuting = true
        queue.poll()?.invoke()
    }
}

Каждый writeCharacteristic, readCharacteristic, setNotification — через очередь. onCharacteristicWrite callback → queue.onCommandComplete(). Без этого при параллельных операциях GATT стек зависает и соединение разрывается.

MTU negotiation. По умолчанию MTU = 23 байта (20 байт payload). Credentials с длинным SSID и паролем могут не влезть. Сразу после подключения запрашивать расширение:

override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
    if (newState == BluetoothProfile.STATE_CONNECTED) {
        gatt.requestMtu(512) // до 517 байт
    }
}

override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
    // Теперь можно писать данные размером mtu - 3 байта
    startProvisioning()
}

Espressif provisioning-android SDK

Espressif предоставляет готовый SDK, который скрывает низкоуровневую работу с GATT:

val device = ESPProvisionManager.getInstance(context)
    .createESPDevice(
        ESPConstants.TransportType.TRANSPORT_BLE,
        ESPConstants.SecurityType.SECURITY_1
    )

device.connectBLEDevice(scanResult) { connected ->
    if (!connected) return@connectBLEDevice
    device.scanNetworks { networks, error ->
        // networks — список Wi-Fi сетей, которые видит устройство
    }
}

// После выбора сети пользователем
device.provision(selectedSsid, password) { status ->
    when (status) {
        ProvisioningStatus.SUCCESS -> navigateToSuccess()
        ProvisioningStatus.FAILURE -> showError(status.toString())
    }
}

SDK реализует шифрование канала через SRP6a (Security 2) или Curve25519+AES (Security 1). Credentials никогда не передаются в открытом виде.

iOS: CoreBluetooth + ESPProvision

На iOS — ESPProvision Swift Package от Espressif или нативный CoreBluetooth для кастомных протоколов.

import ESPProvision

ESPProvisionManager.shared.searchESPDevices(devicePrefix: "PROV_", transport: .ble, security: .secure) { devices, error in
    guard let device = devices?.first else { return }
    device.connect(delegate: self) { status in
        if case .connected = status {
            device.provision(ssid: selectedSSID, passPhrase: password) { status in
                // handle result
            }
        }
    }
}

На iOS нет фрагментации GATT-стека — CoreBluetooth работает одинаково на всех устройствах. Но есть ограничение: сканирование BLE в background режиме работает только для устройств с известными Service UUID, заранее прописанными в Info.plist.

Типичные ошибки provisioning UX

Нет обратной связи о прогрессе. Устройство подключается к Wi-Fi 5–15 секунд. Без прогресс-индикатора пользователи думают, что приложение зависло и нажимают назад.

Не обрабатывают ошибку неправильного пароля. Устройство вернёт статус AUTH_ERROR через notify-характеристику. Нужно показать «Неверный пароль Wi-Fi» — не «Ошибка подключения».

Не выходят из режима provisioning после успеха. Устройство после подключения к Wi-Fi перестаёт рекламировать BLE-сервисы — нормальное поведение. Приложение должно закрыть BLE-соединение и перейти к следующему шагу.

Реализация BLE Provisioning на базе Espressif SDK: 2–3 недели. Кастомный GATT-протокол с шифрованием под другой чип: 4–6 недель.