ESP32学习9:SmartConfig配网

一、WIFI设备配网

        Wifi设备需要连接上路由器 (即wifi热点,AP)才能上网,进行实际的数据交互以及远程控制。我们通常将wifi设备获取热点的名字和密码的过程叫做配网。目前,主流的WIFI配置模式有以下两种:

  • WIFI设备处于AP模式,配置工具作为STA连上这个AP,对该AP发送联网信息(需要连接的路由器的SSID即密码),WIFI设备收到联网信息后,切换到STA模式,利用收到的联网信息联网。此方法优势是成功率基本在 100%,缺点是配置过程复杂,做出的产品不易操作。
  • SmartConfig模式,采用 UDP 广播模式(UDP 接收 IP 地址是 255.255.255.255)。WIFI设备先scan环境下AP(无线热点),得到AP的相关信息,如工作的 channel,然后配置WIFI芯片工作在刚才scan到的channel上去接收UDP包,如果没有接收到,继续配置工作到另外的channel上,如此循环,指导收到UDP包为止。此方法的缺点是成功率只有70%,有点是配置简单,一键完成

二、SmartConfig 特点

         SmartConfig又名快连,当前设备在没有和其他设备建立任何实际性通信链接的状态下,一键配置该设备接入 WIFI。

 1. SmartConfig实际应用场景

         现状:当手机端接入路由器的 WIFI,未联网设备没有任何实质性通信链接(信息孤立)。
         目的:如果未联网设备也想接入这个路由器的 WIFI。
         分析:肯定需要有人告诉未联网设备,路由器的 WIFI 的账号(ssid)和密码(password)。
         手段:目前我们只有手机端的资源可以利用,所以只能手机端告诉设备未联网设备。未联网设备在没有任何链接的情况下,手机端是如何告知未联网设备信息,这个方法就是 SmartConfig。流程如下图所示:

2.ESP32 的 SmartConfig 主逻辑 

 3. ESP32 的 SmartConfig 详细过程逻辑

 4.ESP32 的 SmartConfig 接口介绍

  •  SmartConfig 配置类型设置函数:esp_smartconfig_set_type();
函数原型

esp_smartconfig_set_type

(

    smartconfig_type_t type

)

函数功能SmartConfig 配置类型设置函数
参数

[in] type,

typedef enum {
    SC_TYPE_ESPTOUCH = 0, /*ESPTouch */

    SC_TYPE_AIRKISS, /*AirKiss */
    SC_TYPE_ESPTOUCH_AIRKISS, /*ESPTouch and AirKiss */
} smartconfig_type_t;

返回值ESP_OK:成功
other : 失败
  • SmartConfig 开始一键配置函数 esp_smartconfig_start();
函数原型esp_err_t esp_smartconfig_start
(
    sc_callback_t cb,
    ...
)
函数功能SmartConfig 开始一键配置函数
参数[in] cb:smartconfig 的回调函数
[in] ...:log 1:串口输出 log; 0: 串口直接输出结果
返回值ESP_OK:成功
other : 失败
  •  SmartConfig 停止一键配置函数 esp_smartconfig_stop();
回调原型esp_err_t esp_smartconfig_stop(void)
函数功能停止一键配置
参数
返回值ESP_OK:成功
other : 失败

         初始化 wifi 配置后,程序会根据 WIFI 的实时状态,在回调函数中给出状态返回,所以只需要在回调中进行相关操作,STA 开始事件触发 SC 开始进行一键配置,在 SC 的回调中处理 SC 配置过程的事件。

5.官方示例教程

         以下为官方提供的SmartConfig配置教程,经测试,工作正常。

/* Esptouch example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

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

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t s_wifi_event_group;

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "smartconfig_example";

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) {

        xTaskCreate(smartconfig_example_task, "smartconfig_example_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");
    } 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);
        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) );
    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);
        }
    }
}

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

 结果如下图所示:

 三、结束

         本文介绍了ESP32的SmartConfig配网过程。通过手机APP,成功让ESP32连接上热点。

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值