Wi-Fi Provisioning для IoT-пристроїв через мобільні додатки
Wi-Fi Provisioning — передача мережевих кредієнціалів (SSID, пароль) від мобільного додатку до IoT-пристрою, який ще не знає, до якої мережі підключатися. Звучить просто. Однак фрагментованість Android, відмінності в поведінці ConnectivityManager між версіями та особливості конкретних чипів роблять це нетривіальним завданням.
Методи Wi-Fi Provisioning
Soft AP (Access Point Mode). Пристрій піднімає свою Wi-Fi точку доступу. Телефон підключається до неї та відправляє дані через HTTP/UDP. Мінус: на Android 10+ система автоматично переключає трафік на мобільну мережу, якщо у AP немає доступу до інтернету.
SmartConfig / EZ Connect. Телефон відправляє SSID та пароль через зашифровані UDP-пакети broadcasting. Пристрій у режимі моніторингу Wi-Fi перехоплює та декодує дані. Espressif ESP-TOUCH, Ti SmartConfig — реалізації цього підходу. Працює без фізичного підключення до пристрою, але нестійко на маршрутизаторах з ізоляцією клієнтів AP.
BLE + Wi-Fi комбо. BLE для передачі кредієнціалів, Wi-Fi — лише для роботи в мережі. Найнадійніший UX: не потребує перемикання Wi-Fi мереж на телефоні. Деталі — у окремій послузі BLE Provisioning.
QR-код з кредієнціалами. Кредієнціали вбудовані в QR під час виробництва. Підходить для розгортання на підприємстві, не для споживацьких пристроїв.
Soft AP Provisioning на Android 10+
Основна складність — явне прив'язування HTTP-запитів до потрібної мережі. Без цього OkHttp використовує маршрут за замовчуванням (мобільні дані):
val specifier = WifiNetworkSpecifier.Builder()
.setSsid("MyDevice_AP")
.setWpa2Passphrase("provisioning_key")
.build()
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifier)
.build()
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
val client = OkHttpClient.Builder()
.socketFactory(network.socketFactory)
.dns { hostname ->
network.getAllByName(hostname).toList()
}
.build()
// Відправити кредієнціали на 192.168.4.1 (типова IP ESP32 AP)
postWifiCredentials(client, ssid, password)
}
override fun onUnavailable() { onProvisioningFailed("Не вдалося підключитися до пристрою") }
}
connectivityManager.requestNetwork(request, callback, 30_000) // 30 сек таймаут
removeCapability(NET_CAPABILITY_INTERNET) критично важливий. Без цього Android 10 відхилить запит на підключення до AP без інтернету.
На Android 9 та нижче — WifiManager.enableNetwork() + WifiManager.disconnect(). API застарілий, але працює.
ESP-IDF SoftAP Provisioning
Для пристроїв Espressif — компонент esp_wifi_prov_mgr + офіційний provisioning-android SDK:
// Ініціалізація менеджера
val wifiProvisioningManager = ESPProvisionManager.getInstance(context)
// Пошук AP пристрою
wifiProvisioningManager.createESPDevice(
ESPConstants.TransportType.TRANSPORT_SOFTAP,
ESPConstants.SecurityType.SECURITY_1
).let { device ->
device.connectWiFiDevice() { isConnected ->
if (isConnected) {
// Сканування доступних мереж через пристрій
device.scanNetworks { networks, _ ->
// Показати список мереж користувачу
}
}
}
}
SDK шифрує транспорт через sec1 (Curve25519 key exchange). Не потребує ручної реалізації шифрування.
Сканування мереж через пристрій — цінна функція: замість прохання користувача ввести SSID вручну пристрій сам сканує оточення та повертає список. Користувач вибирає зі списку, зменшуючи помилки вводу.
SmartConfig: Коли працює, коли ні
Ti SmartConfig та Espressif ESP-TOUCH працюють лише якщо:
- Маршрутизатор не активував ізоляцію клієнтів AP
- Телефон підключений до 2.4 ГГц (не 5 ГГц)
- Пристрій знаходиться в зоні гарного сигналу
На корпоративних мережах ізоляція AP майже завжди активована. SmartConfig тут не працює. М'яко кажучи, це поганий вибір для B2B-пристроїв.
Помилки користувачів та як їх перехопити
Користувачі часто вводять пароль мережі 5 ГГц, тоді як ESP32 підтримує лише 2.4 ГГц. Перевірте заздалегідь:
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val currentNetwork = wifiManager.connectionInfo
val is5Ghz = currentNetwork.frequency > 4000 // 5 ГГц > 4000 МГц
if (is5Ghz) showWarning("Ваш пристрій працює в мережі 5 ГГц. Переконайтеся, що IoT-пристрій її підтримує.")
На Android 10+: WifiInfo доступна лише з дозволом ACCESS_FINE_LOCATION — запросіть явно.
Реалізація Wi-Fi Provisioning (один метод, ESP32/ESP8266): 2–3 тижні. Мультиметодний підхід з fallback та повним UX-флоу: 4–6 тижнів.







