图51.3.1.1 程序流程图
51.3.2 程序解析
在本章节实验中,我们只关心main.c文件内容即可,该文件内容如下:
i2c_obj_t i2c0_master;
/* 定义事件 */
static EventGroupHandle_t s_wifi_event_group;
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "smartconfig_example";
static void smartconfig_task(void * parm);
static char lcd_buff[100] = {0};
/**
* @param event_base:WIFI事件
* @param event_id:事件ID
* @param event_data:事件数据
* @retval 无
*/
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
xTaskCreate(smartconfig_task, "smartconfig_task", 4096, NULL, 3, NULL);
}
else if (event_base == WIFI_EVENT &&
event_id == WIFI_EVENT_STA_DISCONNECTED)
{
esp_wifi_connect();
xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
}
else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE)
{
ESP_LOGI(TAG, "Scan done");
lcd_show_string(0,90,320,16,16,"In the distribution network", BLUE);
}
else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL)
{
ESP_LOGI(TAG, "Found channel");
}
/* 已获取SSID和密码,表示配网成功 */
else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD)
{
ESP_LOGI(TAG, "Got SSID and password");
smartconfig_event_got_ssid_pswd_t *evt =
(smartconfig_event_got_ssid_pswd_t *)event_data;
wifi_config_t wifi_config;
uint8_t ssid[33] = { 0 };
uint8_t password[65] = { 0 };
uint8_t rvd_data[33] = { 0 };
bzero(&wifi_config, sizeof(wifi_config_t));
memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
memcpy(wifi_config.sta.password, evt->password,
sizeof(wifi_config.sta.password));
wifi_config.sta.bssid_set = evt->bssid_set;
if (wifi_config.sta.bssid_set == true)
{
memcpy(wifi_config.sta.bssid, evt->bssid,
sizeof(wifi_config.sta.bssid));
}
memcpy(ssid, evt->ssid, sizeof(evt->ssid));
memcpy(password, evt->password, sizeof(evt->password));
ESP_LOGI(TAG, "SSID:%s", ssid);
ESP_LOGI(TAG, "PASSWORD:%s", password);
lcd_fill(0,90,320,240,WHITE);
sprintf(lcd_buff, "%s",ssid);
lcd_show_string(0, 90, 320, 16, 16, lcd_buff, BLUE);
sprintf(lcd_buff, "%s",password);
lcd_show_string(0, 110, 320, 16, 16, lcd_buff, BLUE);
lcd_show_string(0,130,320,16,16,"distribution network", BLUE);
/* 手机APPEspTouch软件使用ESPTOUCH V2模式,会执行以下代码 */
if (evt->type == SC_TYPE_ESPTOUCH_V2)
{
ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data,
sizeof(rvd_data)) );
ESP_LOGI(TAG, "RVD_DATA:");
for (int i = 0; i < 33; i++)
{
printf("%02x ", rvd_data);
}
printf("\n");
}
ESP_ERROR_CHECK( esp_wifi_disconnect() );
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
esp_wifi_connect();
}
else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE)
{
xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
}
}
/**
* @brief WiFi一键配网
* @param 无
* @retval 无
*/
static void wifi_smartconfig_sta(void)
{
/* 初始化网卡 */
ESP_ERROR_CHECK(esp_netif_init());
/* 创建事件 */
s_wifi_event_group = xEventGroupCreate();
/* 使用默认配置初始化包括netif的Wi-Fi */
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* 把WIFI网卡设置为STA模式 */
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
/* WIFI初始化 */
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
/* 注册WIFI事件 */
ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
&event_handler, NULL) );
ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
&event_handler, NULL) );
ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID,
&event_handler, NULL) );
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK( esp_wifi_start() );
}
/**
* @brief 一键配网回调函数
* @param parm:传入的形参(未使用)
* @retval 无
*/
static void smartconfig_task(void * parm)
{
parm = parm;
EventBits_t uxBits;
/* 设置配网协议 */
ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
/* 设置配网参数 */
smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
/* 开始配网 */
ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
while (1)
{
/* 获取事件 */
uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT
| ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
/* 配网成功 */
if(uxBits & CONNECTED_BIT)
{
ESP_LOGI(TAG, "WiFi Connected to ap");
}
/* 智能配置结束 */
if(uxBits & ESPTOUCH_DONE_BIT)
{
/* 配网结束,删除任务 */
esp_smartconfig_stop();
vTaskDelete(NULL);
}
}
}
/**
* @brief 程序入口
* @param 无
* @retval 无
*/
void app_main(void)
{
/* 省略部分代码..... */
wifi_smartconfig_sta();
while (1)
{
LED_TOGGLE();
vTaskDelay(500);
}
}
上述源码是把ESP32-S3设备配置为STA模式,然后开启配网任务并启动配网,此时,ESP32-S3处于混杂模式下,监听网络中的所有报文,当手机APP将当前连接的SSID和密码编码到UDP报文中,通过广播或组播的方式发送报文,ESP32-S3接收到UDP报文后解码,得到SSID和密码,然后使用该组SSID和密码去连接当前网络。
51.4 下载验证
程序下载成功后,我们打开“EspTouch”软件,在此软件下点击 “EspTouch”选项,注意:手机必须连接WiFi,才能一键配网,如下图所示。
图51.4.1 手机配置要连接的WiFi账号与密码
此时,我们填写好“ALIENTEK-YF_5G”WiFi密码和传输方式,可按下确定按键发送UDP报文。当ESP32-S3设备接收到这个报文时,系统会提取该报文的SSID和密码去连接该网络。下图是ESP32-S3配网成功效果图。