简介
smartconfig 直译过来就是智能配置,它是一种可以是wifi快速连接到网络的技术。可以省去直接将wifi账号和密码写入到无线设备中的过程,通过手机将无限设备连接到网络中去。 smartconfig只是无线连接的一种,乐鑫还支持airkiss 方式将设备连接到网络。 具体原理我就不过多介绍了,只是简单介绍一下esp32 如何通过smartconfig技术接入到网络中。
- esp32 进入smartconfig模式:将自己设置成wifiAP模式,以UDP的模式将此信息广播出去,等待有wifi接入。
- 打开手机中的esptouch app(乐鑫提供的smartconfig软件),输入wifi密码后开始搜索wifi信号
- 搜索到esp32的wifi信号,通过wifi协议连接,此时手机app软件将手机当前所连接的wifi的账号密码发送给esp32
- esp32 接收到wifi账号和密码后开始连接路由器,连接成功后,esp32和手机app断开连接.
具体的原理,可以上网上搜索
eps32 smartconfig API
1.esp32 关于smartconfig的API都定义在“esp_smartconfig.h”中,而且应用起来也十分方便
#ifndef __ESP_SMARTCONFIG_H__
#define __ESP_SMARTCONFIG_H__
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* 配置状态标志,在实际操作总根据函数的配置状态标志来判断当前smartconfig所执行的阶段*/
typedef enum {
SC_STATUS_WAIT = 0, /**< 等待开始连接 */
SC_STATUS_FIND_CHANNEL, /**< 发现目标通道 */
SC_STATUS_GETTING_SSID_PSWD, /**< 获取到app发送回来 wifi账号和密码*/
SC_STATUS_LINK, /**< 连接路由器 */
SC_STATUS_LINK_OVER, /**< 连接路由器成功 */
} smartconfig_status_t;
/*smartconfig 类型 乐鑫支持epstouch 和airkiss 两种wifi快连方式 根据这个标志判断使用哪种方式*/
typedef enum {
SC_TYPE_ESPTOUCH = 0, /**< 支持 ESPTouch */
SC_TYPE_AIRKISS, /**< 支持 AirKiss */
SC_TYPE_ESPTOUCH_AIRKISS, /**< 两种协议都支持 ESPTouch and AirKiss */
} smartconfig_type_t;
/**
* @brief 回调函数,用于在smartconfig status 改变时 调用
*
* @param status Status of SmartConfig
* @param 不同的staus pdata的值也不同.
*
*/
typedef void (*sc_callback_t)(smartconfig_status_t status, void *pdata);
/**
* @brief 获取当前smartconfig的版本
*
* @return
* - 返回值是一个数组指针,返回当前版本字符串指针的首地址
*/
const char *esp_smartconfig_get_version(void);
/**
* @brief 开始 SmartConfig,通过手机app设置,在配置过程中,通过c_callback_t cb 回调函数,实时的判断当前smartconfig的状态
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t esp_smartconfig_start(sc_callback_t cb, ...);
/**
* @brief 停止 SmartConfig,无论smartconfig 配置是否成功都应该调用这个函数,这个函数主要是释放smartconfig start 中 申请的 内存,我们知道对于单片机来说内存是很宝贵的,所以必须执行这个函数。
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t esp_smartconfig_stop(void);
/**
* @brief 设置SmartConfig进程超时,从获取到SC_STATUS_FIND_CHANNEL标志开始计时,如果超时了SmartConfig就会重新开始。
* @param 超时范围 15s~255s, offset:45s.
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t esp_esptouch_set_timeout(uint8_t time_s);
/**
* @brief 设置smarconfig的协议类型,ESPTOUCH还是AIRKISS。
*/
esp_err_t esp_smartconfig_set_type(smartconfig_type_t type);
#ifdef __cplusplus
}
#endif
#endif
应用实例
- 在手机上安装esptouch APP, ESP-TOUCH 是乐鑫自主研发的协议。采用的是 Smart Config(智能配置)技术。简单在app上操作就可以使esp32 或者esp8266 快速连接到wifi中。
下载地址:https://www.espressif.com/zh-hans/products/software/esp-touch/resources
我使用的是在谷歌的安卓市场中下载esptouch,因为我在github下载最新的esptouch apk 在实际配网过程中总是配置失败不知道是什么原因。
- 修改代码 官方提供smartconfg例程,位置在esp-idf/examples/wifi/smart_config 着重分析一下这个例程代码:
/*
* app_main()是esp-idf应用程序的入口函数
* 初始化flash。(nvs_flash_init())
*
* 在实际的工程代码中应该在初始化flash之后
* 判断当前是否存在wifi的账号密码,如果存在应该使用原有的账号密码进行wifi连接,如果连接失败,有两种操作:1.不* 做任何处理,2.开始进行smartconfig,3.是否存在物理按键,检测按键是否被按下,如果按下就行smartconfig
*
* 初始化wifi(initialise_wifi();),一般smartconfig都是设备初始化阶段进行的。
*/
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
initialise_wifi();
}
/**
* 初始化tcp/ip 协议栈,tcpip_adapter_init();esp-idf的网络协议栈使用的是lwip,有机会的话我会简单介绍一下 。
*
* esp_event_loop_init(event_handler, NULL) 初始化 事件回调函数,event_handler 函数中主要是实时判断当前wifi的执行状态,用户根据这个函数中的状态标志,对程序进行进一步处理
*/
static void initialise_wifi(void)
{
tcpip_adapter_init();
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );//初始化wifi的各种配置
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );//设置当前wifi为station 模式
ESP_ERROR_CHECK( esp_wifi_start() );//开始连接wifi
}
/* wifi 事件标志 回调函数
*
* SYSTEM_EVENT_STA_START: 当wifi 在sta 模式下运行后, 这个标志被执行,在这个标志下 创建samartconfig任务。
* SYSTEM_EVENT_STA_GOT_IP:直译过来就是获取到IP,在进入到这个标志时,表示esp32 已经成功连接到路由器中,并被分配了IP。
* SYSTEM_EVENT_STA_DISCONNECTED:wifi连接断开,在这里面需要连接wifi,重新联网。
*/
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch(event->event_id) {
case SYSTEM_EVENT_STA_START://
xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);
break;
case SYSTEM_EVENT_STA_GOT_IP:
xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
esp_wifi_connect();//
xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
break;
default:
break;
}
return ESP_OK;
}
/**
* 1.设置配网类型为ESPTOUCH,esp_smartconfig_set_type(SC_TYPE_ESPTOUCH)
* 2. 设置回调函数,开始配网esp_smartconfig_start(sc_callback),根据sc_callback中标志去执行相应的操作。
* 3. uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); 根据sc_callback和 event_handler中的事件标志位,判断当前的wifi状态。当判断到CONNECTED_BIT标志设备已经成功连接到wifi,当判断ESPTOUCH_DONE_BIT标志时 应该停止智能配网
* 4. 停止smartconfig esp_smartconfig_stop();
*/
void smartconfig_example_task(void * parm)
{
EventBits_t uxBits;
ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
ESP_ERROR_CHECK( esp_smartconfig_start(sc_callback) );
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 sc_callback(smartconfig_status_t status, void *pdata)
{
switch (status) {
case SC_STATUS_WAIT://等待开始连接
ESP_LOGI(TAG, "SC_STATUS_WAIT");
break;
case SC_STATUS_FIND_CHANNEL://发现目标通道
ESP_LOGI(TAG, "SC_STATUS_FINDING_CHANNEL");
break;
case SC_STATUS_GETTING_SSID_PSWD://获取账号和密码
ESP_LOGI(TAG, "SC_STATUS_GETTING_SSID_PSWD");
break;
case SC_STATUS_LINK://开始连接路由器
ESP_LOGI(TAG, "SC_STATUS_LINK");
wifi_config_t *wifi_config = pdata;
ESP_LOGI(TAG, "SSID:%s", wifi_config->sta.ssid);
ESP_LOGI(TAG, "PASSWORD:%s", wifi_config->sta.password);
ESP_ERROR_CHECK( esp_wifi_disconnect() );//断开连接
ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_config) );//配置wifi
ESP_ERROR_CHECK( esp_wifi_connect() );//连接wifi
break;
case SC_STATUS_LINK_OVER://连接路由器成功,发送ESPTOUCH_DONE_BIT 完成标志
ESP_LOGI(TAG, "SC_STATUS_LINK_OVER");
if (pdata != NULL) {
uint8_t phone_ip[4] = { 0 };
memcpy(phone_ip, (uint8_t* )pdata, 4);
ESP_LOGI(TAG, "Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]);
}
xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
break;
default:
break;
}
}
具体操作
- 将代码下载到esp32中
$ cp -r esp-idf/examples/wifi/smart_config .
$ cd smart_config
$ make menuconfig # 将下载端口改成实际的端口
$ make -j8
$ make flash monitor
- 打开EspTouch app ESP32 不支持5G wifi。
- 软件输入wifi密码,点击确认.开始连接。
- esp32 接收到esptouch信号还是配置
- 配置成功
- 通知手机APP连接完成