ESP32 开发之旅⑧ SmartConfig——一键配网

授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力。希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石。。。

快速导航
单片机菜鸟的博客快速索引(快速找到你要的)

如果觉得有用,麻烦点赞收藏,您的支持是博主创作的动力。

文章目录

    • 1. 前言
    • 2. smartconfig
      • 2.1 smartconfig工作原理
      • 2.2 smartconfig支持库
      • 2.2.1 beginSmartConfig —— 启动配网模式
      • 2.2.2 stopSmartConfig —— 停止Smartconfig
      • 2.2.3 smartConfigDone —— 是否完成配网
    • 3. 实例
    • 4. 总结

1. 前言

    前面的博文中,博主提供的实例源代码通常都是固定了WiFi热点的账号密码。但是,在实际产品开发中,这样的限制是行不通的。

    当你拿到一块WiFi模块,如果需要连上网络,则需要将SSID名称、密码设置到模块当中。一般有几种方式:

  • 一种就是通过串口接到输入设备,通过串口输入AT指令(SSID名称和密码),但是前提是该模块本身烧入了AT固件,很明显不符合Arduino core for ESP32开发;

  • 一种就是设备提供一个AP热点,手机连上这个热点,然后通过手机把家里的WiFi的SSID和密码配置到设备上,最后手机再切换回家里的WiFi(这里就是博主后面会讲到的Web配网),这种配网成功率可以说是100%。

  • 通过SmartConfig技术配置,微信的AirKiss、ESP32的esptouch(博主也把esptouch的代码抽取了一个module,供Android Studio开发app的同学直接引入),这是最智能的配网方式。但是缺点也很明显,那就是配网成功率未达到100%,同时SmartConfig还得另外安装一个app。SmartConfig最佳的应用场景就是你开发的产品需要搭配App来使用。

2. smartconfig

    esp32核心库提供了SmartConfig技术,那么smartconfig到底是什么呢?

2.1 smartconfig工作原理

    所谓SmartConfig就是手机App端发送包含WIFI用户名以及密码的UDP广播包,智能终端(开启了sniffer混杂模式)的WIFI芯片可以接收到该UDP包,只要知道UDP包的组织形式,就可以通过接收到的UDP包解密出WIFI用户名密码,然后智能硬件配置收到的用户名密码到指定的WIFI AP上。

    直接看一个概念图:
image

    简单操作步骤如下:

  1. esp32端作为station,进入smartconfig, 等待手机端发出的用户名和密码
  2. 手机端把填写当前网络的密码通过UDP广播
  3. esp32获取到信息之后推出smartconfig配置,连接网络

2.2 smartconfig支持库

    还记得,博主其实在 ESP32 开发之旅⑤ Station——WiFiSTA库的使用 有稍微涉及到smartconfig。

而且,请读者放心,smartconfig配置非常简单,方法就三个:

  • beginSmartConfig
  • stopSmartConfig
  • smartConfigDone

2.2.1 beginSmartConfig —— 启动配网模式

函数说明:

/**
 * 启动配网模式
 * @return bool 是否启动配网模式成功
 */
bool beginSmartConfig();

看看 beginSmartConfig 源码:

/**
 * 启动 SmartConfig
 */
bool WiFiSTAClass::beginSmartConfig() {
    // SmartConfig已经开启了
    if (_smartConfigStarted) {
        return false;
    }

    // 开启STA模式
    if (!WiFi.mode(WIFI_STA)) {
        return false;
    }

    esp_wifi_disconnect();

    esp_err_t err;
    // 调用真正的smartconfig_start,并设置了_smartConfigCallback 回调函数
    err = esp_smartconfig_start(reinterpret_cast<sc_callback_t>(&WiFiSTAClass::_smartConfigCallback), 1);
    if (err == ESP_OK) {
        _smartConfigStarted = true;
        _smartConfigDone = false;
        return true;
    }
    return false;
}

注意点

  • SmartConfig需要处于STA工作模式;

我们看看 _smartConfigCallback 会做什么?源码:

/**
 * _smartConfigCallback
 * @param st
 * @param result
 */
void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) {
    smartconfig_status_t status = (smartconfig_status_t) st;
    log_d("Status: %s", sc_status_strings[st % 5]);
    if (status == SC_STATUS_GETTING_SSID_PSWD) {
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
        smartconfig_type_t * type = (smartconfig_type_t *)result;
        log_d("Type: %s", sc_type_strings[*type % 3]);
#endif
    } else if (status == SC_STATUS_LINK) {
        // 获取到配网信息(账号密码)
        wifi_sta_config_t *sta_conf = reinterpret_cast<wifi_sta_config_t *>(result);
        log_d("SSID: %s", (char *)(sta_conf->ssid));
        sta_conf->bssid_set = 0;
        // 把配置写到flash
        esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)sta_conf);
        // 重新连接
        esp_wifi_connect();
        // 标记配网完成
        _smartConfigDone = true;
    } else if (status == SC_STATUS_LINK_OVER) {
        if(result){
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
            ip4_addr_t * ip = (ip4_addr_t *)result;
            log_d("Sender IP: " IPSTR, IP2STR(ip));
#endif
        }
        // 停止配网
        WiFi.stopSmartConfig();
    }
}

2.2.2 stopSmartConfig —— 停止Smartconfig

函数说明:

/**
 * 停止Smartconfig
 * @return bool 是否停止配网模式成功
 */
bool stopSmartConfig();

源码:

bool WiFiSTAClass::stopSmartConfig() {
    if (!_smartConfigStarted) {
        return true;
    }
    // 调用停止函数
    if (esp_smartconfig_stop() == ESP_OK) {
        _smartConfigStarted = false;
        return true;
    }

    return false;
}

2.2.3 smartConfigDone —— 是否完成配网

函数说明:

/**
 * 查找状态看是否配网完成
 * @return bool 是否启动配网模式成功
 */
bool smartConfigDone();

源码:

/**
 * Query SmartConfig status, to decide when stop config
 * @return smartConfig Done
 */
bool WiFiSTAClass::smartConfigDone() {
    if (!_smartConfigStarted) {
        return false;
    }
    // 返回状态 _smartConfigCallback 会改变状态
    return _smartConfigDone;
}

3. 实例

  1. 请往esp32WiFi模块先烧入以下代码:
```c
#include 
 
void smartConfig()
{
  WiFi.mode(WIFI_STA);
  Serial.println("\r\nWait for Smartconfig");
  delay(2000);
  // 等待配网
  WiFi.beginSmartConfig();
 
 while (1)
  {
    Serial.print(".");
    delay(500);
    if (WiFi.smartConfigDone())
    {
      Serial.println("SmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      WiFi.setAutoConnect(true);  // 设置自动连接
      break;
    }
  }
 
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
 
void setup()
{
  Serial.begin(115200);
  smartConfig();
}
 
void loop()
{
  delay(100);
  Serial.println("loop");
}
  1. 然后使用ESP32提供的App ESPTouch 或者还是使用博主后面写的App SmartConfigAPP。
    当然,有兴趣的读者也可以获取到源码,请看 传输门,麻烦star。
    博主app配置如下:

image

image

注意点:

  • 如果没有配置成功,一般都是没有进入到SmartConfig中,最好重启一下吧。

测试结果:
image

4. 总结

本篇非常简单,三个方法,简单步骤,一键配置网络,值得拥有。

你可能感兴趣的:(ESP32,Arduino教程)