系列文章目錄
持續更新…
文章目錄
- 系列文章目錄
- 前言
- 一、Wi?Fi 智能配網概述
- 1.SmartConfig 簡介
- 2.SmartConfig 工作原理
- 3.SmartConfig 協議類型
- 二、Wi?Fi 智能配網類型定義及相關API
- 三、Wi?Fi 智能配網示例程序
- 總結
前言
在物聯網設備開發過程中,如果將 Wi-Fi 的 SSID 和密碼直接寫死在程序中肯定不合理。為了解決這一問題,ESP32 提供了多種 配網方式,其中 SmartConfig 智能配網(又稱“一鍵配網”)是一種常用且高效的方案。SmartConfig 可以讓用戶通過手機 App 將 Wi-Fi 網絡的名稱和密碼發送給 ESP32 設備,從而避免在代碼中硬編碼 Wi-Fi 信息。本篇文章將基于最新的 ESP-IDF,介紹 Wi-Fi SmartConfig 的原理和使用方法,并重點演示 Espressif 自家的 ESPTouch 智能配網方式。
一、Wi?Fi 智能配網概述
1.SmartConfig 簡介
SmartConfig 是由德州儀器(TI)開發的一種 Wi-Fi 配網技術,用于將新的 Wi-Fi 設備連接到目標路由器。它的特點是在不建立傳統網絡連接的情況下,由手機等移動設備將 Wi-Fi 憑據通過廣播的方式發送給待配網的設備。對于那些沒有屏幕或輸入接口的“無頭”設備來說,SmartConfig 提供了一種簡便的配網途徑。利用 SmartConfig,用戶無需直接在設備上輸入或預先配置 Wi-Fi SSID 和密碼,設備通電后進入配網模式,幾分鐘內即可完成網絡連接。
2.SmartConfig 工作原理
SmartConfig 的實現原理是利用手機和路由器的廣播機制傳遞 Wi-Fi 信息。在配網過程中,手機通過 App 將包含 Wi-Fi SSID 和密碼的內容編碼進一系列特殊的 UDP 廣播數據包中,并在無線網絡中發送出來。
ESP32 設備啟動 SmartConfig 后,會進入 Wi-Fi 混雜模式輪循監聽各個信道上的數據幀。當設備捕獲到符合特定編碼規則的廣播包時,就能解析出其中包含的 Wi-Fi 名稱和密碼,并據此配置 ESP32 的 Wi-Fi STA 模式連接到對應的 AP(路由器)。如果在當前信道未能監聽到有效數據,設備會切換到下一個信道繼續監聽,直到成功獲取 Wi-Fi 信息為止。整個過程無需讓手機直接與設備建立連接,避免了手動連接熱點等繁瑣步驟。
3.SmartConfig 協議類型
ESP32 平臺目前支持三種類型的 SmartConfig 協議:Airkiss、ESPTouch 和 ESPTouch v2。其中,Airkiss 是騰訊微信推出的配網協議,常用于微信硬件平臺;ESPTouch 則是樂鑫提供的官方配網協議,對應 Espressif 提供的手機 App(ESP-Touch)。開發者可以根據需求調用接口設定 SmartConfig 的類型。
需要特別說明的是 ESPTouch v2:從 SmartConfig v3.0 開始,ESP-IDF 新增了對 ESPTouch v2 的支持。相比傳統的 ESPTouch,v2 版本采用了全新的算法提高了配網速度,并增加了 AES 加密傳輸和自定義數據字段等功能。這意味著在使用 ESPTouch v2 時,Wi-Fi 密碼等敏感信息可以加密廣播,提高了配網的安全性;但同時由于加密過程增加了數據傳輸量,在開啟隨機 IV(初始化向量)等安全特性時,配網所需時間可能略有增加。一般情況下,使用 ESPTouch(包括 v2)方式能滿足多數應用需求。本文的示例也將采用 Espressif 官方的 ESPTouch 方法進行演示。
二、Wi?Fi 智能配網類型定義及相關API
需包含頭文件:esp_smartconfig.h:
Wi?Fi 智能配網類型定義
/** SmartConfig 配網協議類型枚舉 */
typedef enum {SC_TYPE_ESPTOUCH = 0, // ESPTouch 配網(Espressif 官方協議)SC_TYPE_AIRKISS, // AirKiss 配網(騰訊微信協議)SC_TYPE_ESPTOUCH_AIRKISS,// 組合配網模式(同時兼容 ESPTouch 和 AirKiss)SC_TYPE_ESPTOUCH_V2 // ESPTouch v2 配網(包含AES加密的改進版)
} smartconfig_type_t;/** SmartConfig 配網過程事件枚舉 */
typedef enum {SC_EVENT_SCAN_DONE, // 已完成周圍 Wi-Fi 信道掃描SC_EVENT_FOUND_CHANNEL, // 已找到目標路由器所在信道SC_EVENT_GOT_SSID_PSWD, // 已獲取到 Wi-Fi 的 SSID 和密碼SC_EVENT_SEND_ACK_DONE // 已發送確認信息(ACK)給手機端
} smartconfig_event_t;/* ===== GOT_SSID_PSWD 事件的數據結構 =====* 當拿到憑據時,事件回調會攜帶此結構體(從中取 ssid/password/bssid 等)*/
typedef struct {uint8_t ssid[32]; /* 目標 AP SSID(以 '\0' 結尾) */uint8_t password[64]; /* 對應密碼(以 '\0' 結尾) */bool bssid_set; /* 是否攜帶并使用 BSSID(MAC)定向入網 */uint8_t bssid[6]; /* 目標 AP 的 BSSID(當 bssid_set = true 時有效) */smartconfig_type_t type; /* 本次實際使用的協議類型(ESPTouch / AirKiss) */uint8_t token; /* 與手機 App 通訊用的 token(ACK 用) */uint8_t cellphone_ip[4]; /* 手機的 IPv4 地址(便于雙向確認) */
} smartconfig_event_got_ssid_pswd_t;/* ===== SmartConfig 啟動配置 =====* 可開啟日志、ESPTouch v2 加密(需 16 字節密鑰)*/
typedef struct {bool enable_log; /* 配網過程打印日志(默認 false) */bool esp_touch_v2_enable_crypt; /* 開啟 v2 加密(true/false) */char *esp_touch_v2_key; /* v2 加密密鑰,長度需為 16 字節 */
} smartconfig_start_config_t;
Wi?Fi 智能配網相關API
// 獲取 SmartConfig 庫版本號字符串
const char *esp_smartconfig_get_version(void);// 開始 SmartConfig 配網(Station 或 SoftAP-Sta模式下調用)
esp_err_t esp_smartconfig_start(const smartconfig_start_config_t *config);// 停止 SmartConfig 配網并釋放資源(無論成功與否都應調用)
esp_err_t esp_smartconfig_stop(void);// 設置 SmartConfig 配網超時時間(單位秒,15~255,默認加45秒偏移,從尋找信道開始計時)
esp_err_t esp_esptouch_set_timeout(uint8_t time_s);// 設置 SmartConfig 配網協議類型(需在 esp_smartconfig_start 之前調用)
esp_err_t esp_smartconfig_set_type(smartconfig_type_t type);// 設置是否啟用快速模式(需在 esp_smartconfig_start 之前調用)
esp_err_t esp_smartconfig_fast_mode(bool enable);// 獲取 ESPTouch v2 配網的預留數據(在 SC_EVENT_GOT_SSID_PSWD 事件后調用)
esp_err_t esp_smartconfig_get_rvd_data(uint8_t *rvd_data, uint8_t len);
三、Wi?Fi 智能配網示例程序
本程序演示如何使用ESP-Touch智能配網功能。
讓ESP32通過手機APP自動獲取WiFi的SSID和密碼,無需在代碼中硬編碼 WiFi 信息。
/** ESP32-S3 智能配網(SmartConfig)示例** 本程序演示如何使用ESP-Touch智能配網功能,讓ESP32通過手機APP* 自動獲取WiFi的SSID和密碼,無需在代碼中硬編碼WiFi信息。** 智能配網流程:* 1. ESP32啟動后進入SmartConfig模式,等待配網* 2. 用戶使用手機APP(如ESP-Touch)發送WiFi信息* 3. ESP32接收到WiFi信息后自動連接* 4. 連接成功后退出配網模式**/#include <string.h> // 字符串處理函數
#include "freertos/FreeRTOS.h" // FreeRTOS實時操作系統
#include "freertos/task.h" // 任務管理
#include "freertos/event_groups.h" // 事件組(用于任務間通信)
#include "esp_wifi.h" // WiFi驅動
#include "esp_event.h" // 事件處理
#include "esp_smartconfig.h" // 智能配網功能
#include "esp_netif.h" // 網絡接口
#include "nvs_flash.h" // 非易失性存儲
#include "esp_log.h" // 日志輸出// ======================== 事件位定義 ========================
// 使用事件組來標記不同的狀態
static const int CONNECTED_BIT = BIT0; // 位0:WiFi連接成功標志
static const int ESPTOUCH_DONE_BIT = BIT1; // 位1:ESP-Touch配網完成標志// ======================== 全局變量 ========================
static EventGroupHandle_t s_wifi_event_group; // 事件組句柄,用于任務間通信
static const char *TAG = "smartconfig"; // 日志標簽/** 事件處理函數 - 處理WiFi和SmartConfig相關事件** 參數說明:* - arg: 用戶數據(本例中未使用)* - event_base: 事件類型(WIFI_EVENT、IP_EVENT、SC_EVENT等)* - event_id: 具體的事件ID* - event_data: 事件攜帶的數據** 這個函數會在WiFi狀態或SmartConfig狀態發生變化時自動被調用*/
static void event_handler(void *arg, // 用戶參數(未使用)esp_event_base_t event_base, // 事件基礎類型int32_t event_id, // 事件IDvoid *event_data) // 事件數據
{// 處理WiFi STA啟動事件if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START){esp_wifi_connect(); // WiFi啟動后立即嘗試連接ESP_LOGI(TAG, "WiFi STA啟動,開始連接...");}// 處理WiFi斷開連接事件else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED){esp_wifi_connect(); // 斷開后自動重連ESP_LOGI(TAG, "WiFi斷開連接,正在重連...");}// 處理獲取IP地址事件else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP){ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;char ip[16];esp_ip4addr_ntoa(&event->ip_info.ip, ip, sizeof(ip));ESP_LOGI(TAG, "🎉 WiFi連接成功!獲取到IP地址: %s", ip);xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT); // 設置連接成功標志}// 處理SmartConfig掃描完成事件else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE){ESP_LOGI(TAG, "SmartConfig掃描完成");}// 處理SmartConfig找到信道事件else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL){ESP_LOGI(TAG, "SmartConfig找到目標信道");}// 處理SmartConfig獲取SSID和密碼事件else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD){ESP_LOGI(TAG, "SmartConfig獲取到WiFi信息");// 獲取SmartConfig傳遞的WiFi信息smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;wifi_config_t wifi_config; // WiFi配置結構體bzero(&wifi_config, sizeof(wifi_config)); // 清零配置結構體// 復制SSID和密碼到WiFi配置中memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));ESP_LOGI(TAG, "SSID: %s", wifi_config.sta.ssid);ESP_LOGI(TAG, "密碼: %s", wifi_config.sta.password);// 先斷開當前連接,然后應用新的WiFi配置esp_wifi_disconnect(); // 斷開當前連接esp_wifi_set_config(WIFI_IF_STA, &wifi_config); // 設置新的WiFi配置esp_wifi_connect(); // 使用新配置連接WiFi}// 處理SmartConfig發送確認完成事件else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE){ESP_LOGI(TAG, "? SmartConfig配網完成");xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT); // 設置配網完成標志}
}/** SmartConfig任務函數** 這個任務負責:* 1. 啟動ESP-Touch智能配網* 2. 等待WiFi連接成功或配網完成* 3. 配網完成后停止SmartConfig并刪除自己** 參數:parm - 任務參數(未使用)*/
static void smartconfig_task(void *parm) // 任務參數(未使用)
{EventBits_t uxBits; // 用于接收事件位的變量ESP_LOGI(TAG, "啟動SmartConfig配網任務");// 配置SmartConfig參數smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT(); // 使用默認配置esp_smartconfig_set_type(SC_TYPE_ESPTOUCH); // 設置配網類型為ESP-Touchesp_smartconfig_start(&cfg); // 啟動SmartConfigESP_LOGI(TAG, "請使用ESP-Touch手機APP進行配網");ESP_LOGI(TAG, "等待手機發送WiFi配置信息...");// 主循環:等待事件while (1){// 等待事件位:WiFi連接成功 或 ESP-Touch配網完成uxBits = xEventGroupWaitBits(s_wifi_event_group, // 事件組句柄CONNECTED_BIT | ESPTOUCH_DONE_BIT, // 等待的事件位true, // 讀取后清除事件位false, // 只要有一個事件位被設置就返回portMAX_DELAY); // 無限等待// 檢查WiFi是否連接成功if (uxBits & CONNECTED_BIT){ESP_LOGI(TAG, "WiFi連接成功!");}// 檢查ESP-Touch配網是否完成if (uxBits & ESPTOUCH_DONE_BIT){ESP_LOGI(TAG, "ESP-Touch配網流程完成");esp_smartconfig_stop(); // 停止SmartConfigESP_LOGI(TAG, "SmartConfig已停止");vTaskDelete(NULL); // 刪除當前任務(自我刪除)}}
}/** WiFi初始化函數** 這個函數完成以下工作:* 1. 初始化網絡棧和事件循環* 2. 創建WiFi STA接口* 3. 初始化WiFi驅動* 4. 創建事件組* 5. 注冊事件處理函數* 6. 設置WiFi模式并啟動*/
static void wifi_init(void)
{ESP_LOGI(TAG, "🔧 開始初始化WiFi系統");// 第1步:初始化網絡接口層ESP_ERROR_CHECK(esp_netif_init()); // 初始化TCP/IP網絡棧// 第2步:創建默認事件循環ESP_ERROR_CHECK(esp_event_loop_create_default()); // 創建默認事件循環// 第3步:創建默認WiFi STA接口esp_netif_create_default_wifi_sta(); // 創建STA網絡接口// 第4步:初始化WiFi驅動wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // 使用默認WiFi配置ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // 初始化WiFi驅動// 第5步:創建事件組(用于任務間通信)s_wifi_event_group = xEventGroupCreate(); // 創建事件組// 第6步:注冊事件處理函數// 注冊WiFi事件處理器ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, // 事件類型:WiFi事件ESP_EVENT_ANY_ID, // 事件ID:所有WiFi事件&event_handler, // 事件處理函數NULL, // 用戶數據NULL)); // 事件處理器實例// 注冊IP事件處理器ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, // 事件類型:IP事件IP_EVENT_STA_GOT_IP, // 事件ID:獲取IP地址&event_handler, // 事件處理函數NULL, // 用戶數據NULL)); // 事件處理器實例// 注冊SmartConfig事件處理器ESP_ERROR_CHECK(esp_event_handler_instance_register(SC_EVENT, // 事件類型:SmartConfig事件ESP_EVENT_ANY_ID, // 事件ID:所有SC事件&event_handler, // 事件處理函數NULL, // 用戶數據NULL)); // 事件處理器實例// 第7步:設置WiFi模式并啟動ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); // 設置為STA(客戶端)模式ESP_ERROR_CHECK(esp_wifi_start()); // 啟動WiFiESP_LOGI(TAG, "? WiFi系統初始化完成");
}/** 程序主入口函數** 這是ESP32程序的起始點,完成以下工作:* 1. 初始化NVS存儲* 2. 清除之前保存的WiFi配置(可選)* 3. 初始化WiFi系統* 4. 創建SmartConfig配網任務*/
void app_main(void)
{ESP_LOGI(TAG, "ESP32 SmartConfig智能配網程序啟動");// 第1步:初始化NVS存儲esp_err_t ret = nvs_flash_init(); // 初始化NVSif (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND){ESP_ERROR_CHECK(nvs_flash_erase()); // 如果有問題就擦除ESP_ERROR_CHECK(nvs_flash_init()); // 重新初始化}ESP_LOGI(TAG, "? NVS存儲初始化完成");// 第2步:清除之前保存的WiFi配置(強制重新配網)// 注意:如果您希望保留之前的WiFi配置,請注釋掉下面這行ESP_ERROR_CHECK(nvs_flash_erase_partition("nvs"));ESP_ERROR_CHECK(nvs_flash_init());ESP_LOGI(TAG, "已清除之前的WiFi配置,強制重新配網");// 第3步:初始化WiFi系統wifi_init(); // 調用WiFi初始化函數// 第4步:創建SmartConfig配網任務xTaskCreate(smartconfig_task, // 任務函數"smartconfig_task", // 任務名稱4096, // 任務堆棧大小(字節)NULL, // 任務參數3, // 任務優先級NULL); // 任務句柄ESP_LOGI(TAG, "SmartConfig任務已創建");ESP_LOGI(TAG, "系統已準備就緒,等待配網...");
}
總結
通過本篇內容,我們了解了 SmartConfig 智能配網的原理和使用方法。在 ESP32 上利用 SmartConfig,可以讓設備在運行時通過手機快速獲取 Wi-Fi 憑據,實現 開箱即用 的聯網體驗。文中介紹了 ESPTouch 和 Airkiss 兩種主要協議及其區別,并基于最新 ESP-IDF 提供的 API 展示了如何在代碼中集成 SmartConfig 功能。希望通過本文的講解,開發者可以熟練運用 SmartConfig,為自己的 ESP32 項目實現更加靈活友好的網絡配置功能。