专栏《WiFi 嵌入式物联网开发全套实战》专栏定位嵌入式 Linux/ESP32 WiFi 从原理→驱动→配网→协议→稳定性→抓包调试→量产优化全套工业实战适配物联网设备、智能家居、工控网关、无线透传设备、4GWiFi 双模设备 点赞 收藏 关注嵌入式 WiFi 量产实战全套教程持续更新本章前言前面章节我们吃透了三大主流配网方案SmartConfig、AirKiss 一键配网、SoftAP 网页配网。但在量产落地时两类场景始终无法完美解决1、企业路由器、商场WiFi、开启AP隔离/广播抑制环境SmartConfig 广播/组播报文被拦截一键配网直接失效2、手机 2.4G/5G 双频合一路由手机默认挂5G频段传统一键配网完全收不到报文3、SoftAP 网页配网用户体验差需要手动切换手机WiFi用户投诉率高。而BLEWiFi 蓝牙辅助配网是目前行业公认的量产最优解也是高端智能家居、智能设备标配方案。核心优势不依赖路由器、不依赖2.4G频段、不受AP隔离/广播抑制影响、无需切换手机WiFi。通过蓝牙BLE通道透明传输WiFi SSID、密码、服务器地址成功率接近100%。本章系统讲解BLE双模配网原理、时序流程、架构优势、完整可编译工程代码、蓝牙广播策略、防重入机制、量产稳定性优化彻底解决IoT设备配网成功率低的行业痛点。前置阅读第21/22/23章 三大传统配网方案原理与优缺点24.1 为什么 BLE 配网是量产最优方案24.1.1 传统配网方案的致命短板SmartConfig/AirKiss依赖局域网UDP广播/组播路由器策略即可直接封杀环境兼容性极差SoftAP 网页配网兼容性满分但用户需要手动切WiFi操作繁琐、转化率低所有单WiFi配网天生无法解决「手机连5G、设备监听2.4G」的硬BUG。24.1.2 BLE 辅助配网核心优势BLE 蓝牙和 WiFi 属于完全独立的物理通道数据走蓝牙广播/蓝牙GATT通道和路由器没有任何关系不区分2.4G/5G路由手机无论连什么网络都可以配网不受AP隔离、广播抑制、VLAN隔离影响无需切换手机WiFi用户体验最优配网成功率行业最高量产几乎零失败。工程选型结论消费级IoT量产设备优先 BLEWiFi 双模配网传统 SmartConfig/SoftAP 作为降级兜底。24.2 BLEWiFi 双模配网整体架构与时序24.2.1 整体流程设备上电检测未配网开启BLE广播服务WiFi保持空闲手机APP扫描周边BLE设备发现设备并建立蓝牙连接APP通过BLE GATT特征值下发 WiFi SSID、WiFi密码、MQTT服务器参数设备接收参数、合法性校验、NVS持久化保存关闭BLE广播降低功耗、防误配ESP32 切换 STA 模式连接目标路由器联网成功后通过BLE回传配网成功状态APP提示完成设备正常业务运行不再开启BLE广播。24.2.2 核心架构亮点通道分离配置信息走BLE业务数据走WiFi互不干扰一次配网永久存储NVS保存参数上电自动联网配网完成关闭BLE防止他人恶意重新配网提升设备安全性。24.3 BLE配网核心原理GATT 服务与特征值ESP32 BLE配网基于标准蓝牙BLE GATT协议无需自定义复杂协议。我们自定义两个核心特征值写特征值WriteAPP向设备下发 WiFi SSID、密码读特征值Read/Notify设备向APP反馈配网状态、联网结果。24.3.1 协议数据格式量产标准格式采用 JSON 轻量化透传简单、通用、APP 极易解析{ssid:MyWiFi,pwd:12345678,server:192.168.1.100}设备接收后解析 JSON校验合法性存入 NVS。24.4 完整工程代码BLEWiFi 双模配网基于 ESP-IDF 官方 BLE 组件可直接编译量产包含BLE广播、参数接收、NVS保存、自动联网、配网关闭BLE、状态回传。#include stdio.h #include string.h #include stdlib.h #include freertos/FreeRTOS.h #include freertos/task.h #include freertos/event_groups.h #include esp_wifi.h #include esp_event.h #include esp_log.h #include nvs_flash.h #include nvs.h #include esp_netif.h #include ble_server.h #include cJSON.h #define TAG BLE_WIFI_CFG /* 配网完成标志位 */ #define WIFI_CONNECT_OK_BIT BIT0 static EventGroupHandle_t wifi_event_group; /* 全局WiFi参数缓存 */ static char g_wifi_ssid[33] {0}; static char g_wifi_pwd[65] {0}; static bool g_config_finish false; /** * brief NVS 保存/读取WiFi参数 */ esp_err_t wifi_nvs_save(const char *ssid, const char *pwd) { nvs_handle_t handle; esp_err_t err nvs_open(wifi_cfg, NVS_READWRITE, handle); if(err ! ESP_OK) return err; nvs_set_str(handle, ssid, ssid); nvs_set_str(handle, pwd, pwd); nvs_commit(handle); nvs_close(handle); strncpy(g_wifi_ssid, ssid, sizeof(g_wifi_ssid)-1); strncpy(g_wifi_pwd, pwd, sizeof(g_wifi_pwd)-1); return ESP_OK; } esp_err_t wifi_nvs_load(void) { nvs_handle_t handle; esp_err_t err nvs_open(wifi_cfg, NVS_READONLY, handle); if(err ! ESP_OK) return err; size_t len sizeof(g_wifi_ssid); err | nvs_get_str(handle, ssid, g_wifi_ssid, len); len sizeof(g_wifi_pwd); err | nvs_get_str(handle, pwd, g_wifi_pwd, len); nvs_close(handle); return err; } /** * brief WiFi STA 初始化连接 */ static void wifi_event_cb(void* arg, esp_event_base_t base, int32_t id, void* data) { if(base WIFI_EVENT id WIFI_EVENT_STA_DISCONNECTED) { esp_wifi_connect(); xEventGroupClearBits(wifi_event_group, WIFI_CONNECT_OK_BIT); } else if(base IP_EVENT id IP_EVENT_STA_GOT_IP) { xEventGroupSetBits(wifi_event_group, WIFI_CONNECT_OK_BIT); ESP_LOGI(TAG, WiFi 联网成功配网完成); } } void wifi_sta_init(void) { wifi_event_group xEventGroupCreate(); esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(cfg); esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_cb, NULL, NULL); esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_cb, NULL, NULL); wifi_config_t sta_cfg {0}; strncpy((char*)sta_cfg.sta.ssid, g_wifi_ssid, 32); strncpy((char*)sta_cfg.sta.password, g_wifi_pwd, 64); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_set_config(WIFI_IF_STA, sta_cfg); esp_wifi_start(); esp_wifi_connect(); } /** * brief BLE接收数据回调解析WiFi参数 */ void ble_recv_data_cb(uint8_t *data, uint16_t len) { if(g_config_finish) return; data[len] 0; ESP_LOGI(TAG, BLE收到配网数据:%s, data); cJSON *root cJSON_Parse((char*)data); if(!root) return; cJSON *ssid cJSON_GetObjectItem(root, ssid); cJSON *pwd cJSON_GetObjectItem(root, pwd); if(ssid pwd ssid-valuestring) { strncpy(g_wifi_ssid, ssid-valuestring, 32); strncpy(g_wifi_pwd, pwd-valuestring, 64); /* 保存参数启动WiFi联网 */ wifi_nvs_save(g_wifi_ssid, g_wifi_pwd); g_config_finish true; /* 关闭BLE广播防止二次配网 */ ble_server_stop(); ESP_LOGI(TAG, 参数保存完成启动WiFi连接); wifi_sta_init(); } cJSON_Delete(root); } void app_main(void) { nvs_flash_init(); /* 上电读取WiFi参数 */ if(wifi_nvs_load() ESP_OK strlen(g_wifi_ssid) 0) { /* 已有参数直接联网 */ wifi_sta_init(); } else { /* 无参数开启BLE配网模式 */ ESP_LOGI(TAG, 进入BLE蓝牙配网模式); ble_server_start(ble_recv_data_cb); } }24.5 BLE配网关键工程逻辑解读24.5.1 上电自动判断配网状态NVS 存在合法WiFi参数 → 直接启动STA联网无参数/参数损坏 → 自动开启BLE广播等待APP配网。24.5.2 配网完成立即关闭BLE这是量产安全关键配网成功后立刻停止BLE广播服务避免陌生人恶意覆盖设备WiFi配置长期开启BLE导致功耗升高、设备被扫描劫持。24.5.3 数据防错处理使用cJSON解析避免自定义协议解析出错增加全局配网锁g_config_finish防止重复配网、参数覆盖严格限制SSID、密码长度规避缓冲区溢出。24.6 四大配网方案全方位量产对比配网方案路由器兼容性5G路由适配用户体验成功率量产推荐等级SmartConfig差怕广播抑制不支持优中降级兜底AirKiss中怕组播拦截不支持优中辅助备选SoftAP网页配网满分支持差高终极兜底BLEWiFi双模配网满分完全支持最优接近100%量产首选24.7 量产高频坑点与解决方案坑点1BLE广播功耗过高电池设备续航短根因默认BLE广播间隔过短、持续高频率广播。优化配网模式下拉长BLE广播间隔降低平均电流配网超时自动关闭BLE。坑点2设备重启后可被随意重新配网根因正常工作模式下BLE未彻底关闭。解决方案仅未配网状态开启BLE已配网设备永久关闭BLE广播如需重置必须按键恢复出厂。坑点3多设备同时配网乱序、参数错乱解决方案增加设备唯一MAC识别、配网锁定机制单次只允许一台手机配网。坑点4BLE连接频繁断开、重连抖动根因手机系统蓝牙后台限制、连接参数不合理。优化调整BLE连接间隔、超时参数适配iOS/安卓双系统。24.8 产品级最优配网架构量产标准目前行业头部IoT产品统一采用三层配网架构首选BLE蓝牙辅助配网高成功率、好体验备选SmartConfig一键配网兼容老旧APP场景兜底SoftAP网页配网极端环境100%兜底这套架构可以覆盖家用路由、企业路由、5G合并路由、隔离网络、老旧手机、新系统手机全场景。24.9 本章小结BLEWiFi 双模配网彻底解决了传统WiFi配网依赖路由器、受环境干扰、成功率低的行业痛点。它不依赖任何局域网报文转发、不区分2.4G/5G频段、无需切换手机WiFi是目前稳定性、兼容性、用户体验综合最优的量产配网方案。对于电池设备、智能家居、量产IoT设备BLE双模配网已经是产品标配传统单WiFi配网方案逐步被淘汰。下一章我们将针对性解决配网量产顽疾干扰、超时、成功率低讲解全场景优化方案。 点赞 收藏 关注嵌入式 WiFi 量产实战全套教程持续更新下一章第 25 章 配网成功率低、干扰大、超时问题工程优化方案