ESP32-IDF学习笔记(2)---Smartconfig 配网

一、SmartConfig配网

  • SmartConfig配网,这是由TI研发的一种配网方式,手机发出一组特殊长度编码的带WIFI信息的UDP包,设备循环在每一个通道上监听UDP包,当监听到符合长度规则的UDP包时,获取UDP包中的SSID和Password,然后配置WIFI芯片为STA模式去连接WIFI,如果没有监听到UDP包则切换至下一个通道,如此往复。

本文通过调用ESP32-IDF的smartconfig模块,模块协议使用AirKiss,参考ESP历程:examples/wifi/smart_config

二、具体过程

1、初始化WIFI协议栈

  • 初始化WIFI配置,设定WIFI为STA模式,配置使用默认配置
  • 绑定事件回调,将WIFI的全部事件、获取到IP事件与smartconfig的全部事件绑定到回调函数中
static void initialise_wifi(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

    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() );

}

2、设置smartconfig

  • 设定Smartconfig的模式,协议使用AirKiss,其他默认
static void smartconfig_example_task(void * parm)
{
    EventBits_t uxBits;
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );
    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_LOGI(TAG, "smartconfig over");
            esp_smartconfig_stop();
            vTaskDelete(NULL);
        }
    }
}

3、掉电存储

  • 在第一次成功配网时,将Wifi的数据保存至Flash中,后续上电时,检测是否有wifi信息,如果有wifi信息则直接读取wifi信息进行连接,如果没有wifi信息,则开启Smartconfig配网

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) {
        ESP_LOGI(TAG, "STA start ");
    } 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");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
        ESP_LOGI(TAG, "Found channel");
    } 
		//在成功获取WiFi信息事件的回调处理中,将wifi信息保存至flash中
		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);
       
       
        /* save wifi info to flash */
        ESP_ERROR_CHECK(nvs_open("wifi_info",NVS_READWRITE,&Set_Wifi_handle));
        ESP_ERROR_CHECK(nvs_set_str(Set_Wifi_handle,"wifi_ssid",(const char*)ssid));
        ESP_ERROR_CHECK(nvs_set_str(Set_Wifi_handle,"wifi_pswd",(const char*)password));
        ESP_ERROR_CHECK(nvs_set_u8(Set_Wifi_handle,"wifi_info_flag",wifi_configed));
        ESP_ERROR_CHECK(nvs_commit(Set_Wifi_handle));
        nvs_close(Set_Wifi_handle); 
       

        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[i]);
            }
            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);
    }
}
  • 检测Flash中是否存在wifi信息
static void check_wifi_info(void)
{
    esp_err_t err;  
    uint8_t wifi_ssid[33] = { 0 };     
    uint8_t wifi_passwd[65] = { 0 };  
    size_t len;
    nvs_handle_t Get_Wifi_handle;
    uint8_t flag;
    wifi_config_t wifi_config;

    nvs_open("wifi_info",NVS_READONLY,&Get_Wifi_handle);
    nvs_get_u8(Get_Wifi_handle,"wifi_info_flag",&flag);
    
    if(flag == 1)
    {
        ESP_LOGI(TAG,"flash hava wifi Info");
        len = sizeof(wifi_ssid);
        err = nvs_get_str(Get_Wifi_handle,"wifi_ssid",(char *)wifi_ssid,&len);
        if(err == ESP_OK) 
        {
            ESP_LOGI(TAG, "Flash SSID = %s",wifi_ssid);
            memcpy(wifi_config.sta.ssid,wifi_ssid,sizeof(wifi_config.sta.ssid));
        }

        len = sizeof(wifi_passwd);
        err = nvs_get_str(Get_Wifi_handle,"wifi_pswd",(char *)wifi_passwd,&len);
        if(err == ESP_OK) 
        {
            ESP_LOGI(TAG, "Flash pswd = %s",wifi_passwd);
            memcpy(wifi_config.sta.password,wifi_passwd,sizeof(wifi_config.sta.password));
        }

        nvs_close(Get_Wifi_handle);
        ESP_LOGI(TAG, "wifi ssid :%s, paws:%s",wifi_config.sta.ssid,wifi_config.sta.password);
        ESP_LOGI(TAG,"start wifi connect ....");
        esp_wifi_disconnect();
        esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
        esp_wifi_connect();

    }
    else{
        nvs_close(Get_Wifi_handle);
        xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);    
    }

}

三、查看情况

1、首次上电

  • 使用微信小程序,一键配网,协议模式使用AirKiss,填入wifi信息
    在这里插入图片描述

  • 观察串口输出信息,已成功配网
    在这里插入图片描述

  • 小程序上显示配网成功
    在这里插入图片描述

2、非首次上电

在这里插入图片描述

四、完整代码

#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_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
#include "nvs.h"


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";

static nvs_handle_t Set_Wifi_handle;

typedef enum {
        wifi_unconfiged = 0,
        wifi_configed,
}wifi_info_storage_t;


static void smartconfig_example_task(void * parm);

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) {
        ESP_LOGI(TAG, "STA start ");
    } 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");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
        ESP_LOGI(TAG, "Found channel");
    } 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);
       
       
        /* save wifi info to flash */
        ESP_ERROR_CHECK(nvs_open("wifi_info",NVS_READWRITE,&Set_Wifi_handle));
        ESP_ERROR_CHECK(nvs_set_str(Set_Wifi_handle,"wifi_ssid",(const char*)ssid));
        ESP_ERROR_CHECK(nvs_set_str(Set_Wifi_handle,"wifi_pswd",(const char*)password));
        ESP_ERROR_CHECK(nvs_set_u8(Set_Wifi_handle,"wifi_info_flag",wifi_configed));
        ESP_ERROR_CHECK(nvs_commit(Set_Wifi_handle));
        nvs_close(Set_Wifi_handle); 
       

        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[i]);
            }
            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);
    }
}

static void initialise_wifi(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

    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() );

}

static void smartconfig_example_task(void * parm)
{
    EventBits_t uxBits;
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );
    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_LOGI(TAG, "smartconfig over");
            esp_smartconfig_stop();
            vTaskDelete(NULL);
        }
    }
}

static void check_wifi_info(void)
{
    esp_err_t err;  
    uint8_t wifi_ssid[33] = { 0 };     
    uint8_t wifi_passwd[65] = { 0 };  
    size_t len;
    nvs_handle_t Get_Wifi_handle;
    uint8_t flag;
    wifi_config_t wifi_config;

    nvs_open("wifi_info",NVS_READONLY,&Get_Wifi_handle);
    nvs_get_u8(Get_Wifi_handle,"wifi_info_flag",&flag);
    
    if(flag == 1)
    {
        ESP_LOGI(TAG,"flash hava wifi Info");
        len = sizeof(wifi_ssid);
        err = nvs_get_str(Get_Wifi_handle,"wifi_ssid",(char *)wifi_ssid,&len);
        if(err == ESP_OK) 
        {
            ESP_LOGI(TAG, "Flash SSID = %s",wifi_ssid);
            memcpy(wifi_config.sta.ssid,wifi_ssid,sizeof(wifi_config.sta.ssid));
        }

        len = sizeof(wifi_passwd);
        err = nvs_get_str(Get_Wifi_handle,"wifi_pswd",(char *)wifi_passwd,&len);
        if(err == ESP_OK) 
        {
            ESP_LOGI(TAG, "Flash pswd = %s",wifi_passwd);
            memcpy(wifi_config.sta.password,wifi_passwd,sizeof(wifi_config.sta.password));
        }

        nvs_close(Get_Wifi_handle);
        ESP_LOGI(TAG, "wifi ssid :%s, paws:%s",wifi_config.sta.ssid,wifi_config.sta.password);
        ESP_LOGI(TAG,"start wifi connect ....");
        esp_wifi_disconnect();
        esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
        esp_wifi_connect();

    }
    else{
        nvs_close(Get_Wifi_handle);
        xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);    
    }

}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    initialise_wifi();
    check_wifi_info();
}

参考文档:

乐鑫官方文档
esp32-C3学习笔记(2)保持配网信息+自动重连

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值