无线路由器中的WPS是Wi-Fi Protected Setup的简称,中文翻译为Wi-Fi安全防护设置,它是由Wi-Fi安全联盟推出的一种无线加密认证方式。主要是为了简化无线局域网的安装及安全性能配置工作,通过这种设置,让无线连接更加方便和安全。省去了输入繁琐密码的过程,也增加了wifi的安全性,但现在手机只有少部分还保留了这个功能。
在嵌入式wifi系统中比如esp32无线配对还是非常实用,匹配时需要一对一触发,否则相互干扰。
esp32作为ap端:
1.需要在menuconfig中添加组件支持,
component config -->wifi-->add wps register support in softap mode
2.wps配置和功能
#ifndef __BOARD_AP_WPS_H__
#define __BOARD_AP_WPS_H__
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_mac.h"
#include "esp_log.h"
#include "esp_wps.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include <string.h>
/**
* #ifndef os_memcpy
* #define os_memcpy(d, s, n) memcpy((d), (s), (n))
* #endif
* 由此可见是一回事
* */
#include <os.h>
/*set wps mode via project configuration */
#define WPS_MODE WPS_TYPE_PBC
//PBC方式使用默认的PIN"00000000",改变他和常规的差异化,只适合自己的设备配对
#define WPS_PIN_REDEFINE "12345678"
static esp_wps_config_t ap_config = WPS_CONFIG_INIT_DEFAULT(WPS_MODE);
static bool is_wps_rg_status = false;
static inline void ap_wps_start(void)
{
os_memcpy((void *)ap_config.pin, WPS_PIN_REDEFINE, 8);
ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&ap_config));
if (ap_config.wps_type == WPS_TYPE_PBC) {
//ESP_LOGI(TAG, "Staring WPS registrar in PBC mode");
} else {
//ESP_LOGI(TAG, "Staring WPS registrar with random generated pin");
}
is_wps_rg_status = false;
ESP_ERROR_CHECK(esp_wifi_ap_wps_start(NULL));
}
static inline void ap_wps_restart(void)
{
os_memcpy((void *)ap_config.pin, WPS_PIN_REDEFINE, 8);
ESP_ERROR_CHECK(esp_wifi_ap_wps_disable());
ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&ap_config));
is_wps_rg_status = false;
ESP_ERROR_CHECK(esp_wifi_ap_wps_start(NULL));
}
static inline void ap_wps_stop(void)
{
ESP_ERROR_CHECK(esp_wifi_ap_wps_disable());
}
static inline void ap_wps_set_rg_status(bool status)
{
is_wps_rg_status = status;
}
static inline bool ap_wps_get_rg_status(void)
{
return is_wps_rg_status;
}
#endif
3.板上配置一个按键用来监听配对触发
#ifndef __BOARD_GPIO_IN_H__
#define __BOARD_GPIO_IN_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
//复用BOOT脚作为wps key触发引脚,这个脚默认是没有接的,悬空状态,那就将其配置为内部上拉,下降沿触发
#define GPIO_INPUT_IO (0)
#define GPIO_INPUT_PIN_SEL (1ULL<<GPIO_INPUT_IO)//((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT (0)
static QueueHandle_t gpio_evt_queue = NULL;
//需要这种事件传递的形式
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void gpio_task_example(void* arg)
{
#define WPS_TRIGGER_TIME (2000)
#define WPS_LOOP_TIME (100)
#define WPS_TIMEOUT (20 * 1000)
uint32_t io_num;
for(;;) {
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
//printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
int loop_cnt = 0;
while(loop_cnt < (WPS_TRIGGER_TIME / WPS_LOOP_TIME))
{
//按键松开了就重新开始监听
if(gpio_get_level(io_num))
{
break;
}
loop_cnt++;
vTaskDelay(WPS_LOOP_TIME / portTICK_PERIOD_MS);
}
if(loop_cnt < (WPS_TRIGGER_TIME / WPS_LOOP_TIME))
{
printf("wps key abort!\n");
continue;
}
printf("wps key pressed!\n");
ap_wps_restart();
/**
* 尽管WIFI_EVENT_AP_WPS_RG_TIMEOUT时间比较长,不过他是
* 超时以后不断循环ap_wps_restart,所以默认上超时是无限期的,
* 这时候就可以人为的使用一个延时来主动停止wps即可,同时也避免了
* wps按键的重复触发问题.
* */
loop_cnt = 0;
while(loop_cnt < (WPS_TIMEOUT / WPS_LOOP_TIME))
{
if(ap_wps_get_rg_status())
{
break;
}
loop_cnt++;
vTaskDelay(WPS_LOOP_TIME / portTICK_PERIOD_MS);
}
ap_wps_stop();
printf("wps stop!\n");
//清空队列防止干扰
xQueueReset(gpio_evt_queue);
}
}
}
static inline void gpio_in_init(void)
{
//interrupt of rising edge
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_NEGEDGE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = 1;//下降沿触发当然默认拉高
io_conf.pull_down_en = 0;//上升沿当然先拉低默认
gpio_config(&io_conf);
//change gpio interrupt type for one pin
//gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
//create a queue to handle gpio event from isr
//不需要发送10次,发送1次就好
gpio_evt_queue = xQueueCreate(1/*10*/, sizeof(uint32_t));
//start gpio task
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, GPIO_KEY_TASK_PRIORITY, NULL);
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_handler, (void*) GPIO_INPUT_IO);
}
static inline void test_gpio_in(void)
{
gpio_in_init();
gpio_out_init();
gpio_out_value(0);
}
#endif
/ /
4.wifi事件的监听和处理
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
switch (event_id) {
case WIFI_EVENT_AP_START:
ESP_LOGI(TAG, "WIFI_EVENT_AP_START");
break;
case WIFI_EVENT_AP_STADISCONNECTED:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_STADISCONNECTED");
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
break;
case WIFI_EVENT_AP_STACONNECTED:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_STACONNECTED");
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
}
break;
case WIFI_EVENT_AP_WPS_RG_SUCCESS:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_SUCCESS");
wifi_event_ap_wps_rg_success_t *evt = (wifi_event_ap_wps_rg_success_t *)event_data;
ESP_LOGI(TAG, "station "MACSTR" WPS successful",
MAC2STR(evt->peer_macaddr));
ap_wps_set_rg_status(true);
}
break;
case WIFI_EVENT_AP_WPS_RG_FAILED:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_FAILED");
wifi_event_ap_wps_rg_fail_reason_t *evt = (wifi_event_ap_wps_rg_fail_reason_t *)event_data;
ESP_LOGI(TAG, "station "MACSTR" WPS failed, reason=%d",
MAC2STR(evt->peer_macaddr), evt->reason);
ap_wps_restart();
}
break;
case WIFI_EVENT_AP_WPS_RG_TIMEOUT:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_TIMEOUT");
ap_wps_restart();
}
break;
default:
break;
}
}
static void wifi_init_softap(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t*mynetif = esp_netif_create_default_wifi_ap();
esp_netif_ip_info_t ipInfo;
IP4_ADDR(&ipInfo.ip, 192,168,28,1);
IP4_ADDR(&ipInfo.gw, 192,168,28,1);
IP4_ADDR(&ipInfo.netmask, 255,255,255,0);
esp_netif_dhcps_stop(mynetif);
esp_netif_set_ip_info(mynetif, &ipInfo);
esp_netif_dhcps_start(mynetif);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL));
//这个是默认mac base,比如softap是+1等等.
//本地无线网卡地址
uint8_t local_mac[6];
//esp_efuse_mac_get_default(mac);
esp_read_mac(local_mac,ESP_MAC_WIFI_SOFTAP);
//for(int i=0;i<sizeof(mac);i++)
// printf("%2X ",mac[i]);
//printf("\n");
uint8_t buf[32] = {0};
sprintf((char*)buf,"%s-%02X%02X%02X",EXAMPLE_ESP_WIFI_SSID_PREFIX,local_mac[3],local_mac[4],local_mac[5]);
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID_PREFIX,//此处只能常量
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID_PREFIX),
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
#ifdef CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT
.authmode = WIFI_AUTH_WPA3_PSK,
.sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
#else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */
.authmode = WIFI_AUTH_WPA2_PSK,
#endif
.pmf_cfg = {
.required = true,
},
},
};
//wifi_config.ap.pairwise_cipher
wifi_config.ap.ssid_len = strlen((char*)buf);
memcpy(wifi_config.ap.ssid,buf,wifi_config.ap.ssid_len);
wifi_config.ap.channel = sta_wifi_get_best_channel();
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
buf, EXAMPLE_ESP_WIFI_PASS, wifi_config.ap.channel);
}
esp32作为sta端:
1.wps配置和功能
#ifndef __BOARD_STA_WPS_H__
#define __BOARD_STA_WPS_H__
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_wps.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include <string.h>
#define WPS_PIN_REDEFINE "12345678"
static esp_wps_config_t sta_config = WPS_CONFIG_INIT_DEFAULT(WPS_TYPE_PBC);
static bool is_wps_er_status = false;
static inline void sta_wps_start(void)
{
//暂停wifi连接
esp_wifi_disconnect();
memcpy(sta_config.pin, WPS_PIN_REDEFINE, 8);
ESP_ERROR_CHECK(esp_wifi_wps_enable(&sta_config));
is_wps_er_status = false;
ESP_ERROR_CHECK(esp_wifi_wps_start(0));
}
static inline void sta_wps_restart(void)
{
//暂停wifi连接
esp_wifi_disconnect();
memcpy(sta_config.pin, WPS_PIN_REDEFINE, 8);
ESP_ERROR_CHECK(esp_wifi_wps_disable());
ESP_ERROR_CHECK(esp_wifi_wps_enable(&sta_config));
is_wps_er_status = false;
ESP_ERROR_CHECK(esp_wifi_wps_start(0));
}
static inline void sta_wps_stop(void)
{
ESP_ERROR_CHECK(esp_wifi_wps_disable());
//恢复wifi连接
esp_wifi_connect();
}
static inline void sta_wps_set_er_status(bool status)
{
is_wps_er_status = status;
}
static inline bool sta_wps_get_er_status(void)
{
return is_wps_er_status;
}
#endif
/
2.板上配置一个按键用来监听配对触发
#ifndef __BOARD_GPIO_IN_H__
#define __BOARD_GPIO_IN_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
//暂时假设服用BOOT脚作为wps key触发引脚,这个脚默认是没有接的,悬空状态,那就将其配置为内部上拉,下降沿触发
#define GPIO_INPUT_IO (0)
#define GPIO_INPUT_PIN_SEL (1ULL<<GPIO_INPUT_IO)//((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT (0)
extern int global_wifi_connect;
static QueueHandle_t gpio_evt_queue = NULL;
static bool is_wps_key_pressed = false;
//需要这种事件传递的形式
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void gpio_task_example(void* arg)
{
#define WPS_TRIGGER_TIME (2000)
#define WPS_LOOP_TIME (100)
#define WPS_TIMEOUT (20 * 1000)
uint32_t io_num;
for(;;) {
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
//printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
int loop_cnt = 0;
while(loop_cnt < (WPS_TRIGGER_TIME / WPS_LOOP_TIME))
{
//按键松开了就重新开始监听
if(gpio_get_level(io_num))
{
break;
}
loop_cnt++;
vTaskDelay(WPS_LOOP_TIME / portTICK_PERIOD_MS);
}
if(loop_cnt < (WPS_TRIGGER_TIME / WPS_LOOP_TIME))
{
printf("sta wps key abort!\n");
continue;
}
printf("sta wps key pressed!\n");
is_wps_key_pressed = true;
/**在wifi已经连接上的情况下,先断开wifi连接,再终止wifi重连,再启动wps
* */
if(global_wifi_connect > 0)
{
//由于is_wps_key_pressed = true,WIFI_EVENT_STA_DISCONNECTED中wifi不能改变状态
//所以要手动更改.
global_wifi_connect = 0;
esp_wifi_disconnect();
vTaskDelay(100 / portTICK_PERIOD_MS);
}
/**
* W (20543) wifi:sta_scan: STA is connecting, scan are not allowed!
* 看来wifi在连接的时候是不能进行wps配对的.
* */
sta_wps_restart();
/**
* 尽管WIFI_EVENT_AP_WPS_RG_TIMEOUT时间比较长,不过他是
* 超时以后不断循环ap_wps_restart,所以默认上超时是无限期的,
* 这时候就可以人为的使用一个延时来主动停止wps即可,同时也避免了
* wps按键的重复触发问题.
* */
loop_cnt = 0;
while(loop_cnt < (WPS_TIMEOUT / WPS_LOOP_TIME))
{
if(sta_wps_get_er_status())
{
break;
}
loop_cnt++;
vTaskDelay(WPS_LOOP_TIME / portTICK_PERIOD_MS);
}
if(!sta_wps_get_er_status())
{
sta_wps_stop();
printf("sta wps stop!\n");
}
is_wps_key_pressed = false;
//清空队列防止干扰
xQueueReset(gpio_evt_queue);
}
}
}
static inline void gpio_in_init(void)
{
//interrupt of rising edge
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_NEGEDGE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = 1;//下降沿触发当然默认拉高
io_conf.pull_down_en = 0;//上升沿当然先拉低默认
gpio_config(&io_conf);
//change gpio interrupt type for one pin
//gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
//create a queue to handle gpio event from isr
//不需要发送10次,发送1次就好
gpio_evt_queue = xQueueCreate(1/*10*/, sizeof(uint32_t));
//start gpio task
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, GPIO_KEY_TASK_PRIORITY, NULL);
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_handler, (void*) GPIO_INPUT_IO);
}
static inline bool board_gpio_get_wps_key_status(void)
{
return is_wps_key_pressed;
}
static inline void test_gpio_in(void)
{
gpio_in_init();
gpio_out_init();
gpio_out_value(0);
}
#endif
/ /
3.wifi事件的监听和处理
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)
{
global_wifi_connect = -1;
esp_wifi_connect();
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
{
if(!board_gpio_get_wps_key_status())
{
/**
* 这种基于事件的重连方式不错
* */
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
global_wifi_connect = 0;
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
} else {
global_wifi_connect = -1;
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
}
ESP_LOGI(TAG,"connect to the AP fail");
}
}
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED)
{
//此处获取bssid,wifi ap's wlan mac
wifi_event_sta_connected_t* event = (wifi_event_sta_connected_t*) event_data;
//printf("get ap's bssid:");
//print0x(event->bssid,sizeof(event->bssid));
uint16_t chs = Crc_Calculate(event->bssid, sizeof(event->bssid));
set_send_mavlink_protocol_crc(chs >> 8,chs & 0xFF);
//printf("ap's mac chs=%04X\n",chs);
char str[32] = {0};
size_t str_len = sizeof(str);
esp_err_t err;
err = board_read_string("wifi_name", str, &str_len);
if(err == ESP_OK && str_len > 0)
{
str[str_len] = 0;
//和已经保存的ssid不一致才需要重新保存
if(strcmp((char*)event->ssid,(char*)str))
{
board_write_string("wifi_name", (char*)event->ssid);
printf("wifi name differ,need save!\n");
}
}
else
{
//没有保存ssid就立即保存
if(ESP_ERR_NVS_NOT_FOUND == err)
{
board_write_string("wifi_name", (char*)event->ssid);
printf("wifi name not found,need save!\n");
}
}
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
global_wifi_connect = 1;
}
//wps连接
switch (event_id) {
case WIFI_EVENT_STA_WPS_ER_SUCCESS:
ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS");
{
wifi_event_sta_wps_er_success_t *evt =
(wifi_event_sta_wps_er_success_t *)event_data;
int i;
if (evt) {
s_ap_creds_num = evt->ap_cred_cnt;
for (i = 0; i < s_ap_creds_num; i++) {
memcpy(wps_ap_creds[i].sta.ssid, evt->ap_cred[i].ssid,
sizeof(evt->ap_cred[i].ssid));
memcpy(wps_ap_creds[i].sta.password, evt->ap_cred[i].passphrase,
sizeof(evt->ap_cred[i].passphrase));
}
/* If multiple AP credentials are received from WPS, connect with first one */
ESP_LOGI(TAG, "Connecting to SSID: %s, Passphrase: %s",
wps_ap_creds[0].sta.ssid, wps_ap_creds[0].sta.password);
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wps_ap_creds[0]) );
}
//此处已经说明只有一个ap wps则没有event data,直接连接即可
/*
* If only one AP credential is received from WPS, there will be no event data and
* esp_wifi_set_config() is already called by WPS modules for backward compatibility
* with legacy apps. So directly attempt connection here.
*/
ESP_ERROR_CHECK(esp_wifi_wps_disable());
sta_wps_set_er_status(true);
esp_wifi_connect();
}
break;
case WIFI_EVENT_STA_WPS_ER_FAILED:
ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED");
sta_wps_restart();
break;
case WIFI_EVENT_STA_WPS_ER_TIMEOUT:
ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT");
sta_wps_restart();
break;
case WIFI_EVENT_STA_WPS_ER_PIN:
ESP_LOGI(TAG, "WIFI_EVENT_STA_WPS_ER_PIN");
/* display the PIN code */
wifi_event_sta_wps_er_pin_t* event = (wifi_event_sta_wps_er_pin_t*) event_data;
printf("display pincode=%s\n",(char*)event->pin_code);
break;
default:
break;
}
}
void wifi_init_sta(void)
{
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&event_handler,
NULL,
&instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.password = EXAMPLE_ESP_WIFI_PASS,
/* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).
* If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
* to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
* WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
*/
.threshold.authmode = WIFI_AUTH_WPA3_PSK,
.sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
.sae_h2e_identifier = "",
},
};
/**
* 获取已经保存的wifi&password
* */
char str[32] = {0};
size_t str_len = sizeof(str);
esp_err_t err;
err = board_read_string("wifi_name", str, &str_len);
if(err == ESP_OK && str_len > 0)
{
str[str_len] = 0;
strcpy((char*)wifi_config.sta.ssid,str);
printf("get saved wifi_name=%s\n",str);
memset(str,0,sizeof(str));
str_len = sizeof(str);
}
err = board_read_string("wifi_passwd", str, &str_len);
if(err == ESP_OK && str_len > 0)
{
str[str_len] = 0;
strcpy((char*)wifi_config.sta.password,str);
printf("get saved wifi_passwd=%s\n",str);
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
//禁止modem休眠,降低延迟
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(TAG, "wifi_init_sta finished.");
//不需要堵塞等候连接!不过没有连接堵塞在这里也不搓,也没必要后续初始化和任务启动,只需要wps已经启动即可
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
* happened. */
if (bits & WIFI_CONNECTED_BIT) {
// ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
// EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
wifi_config.sta.ssid, wifi_config.sta.password);
} else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
}
最后两块板子在2秒时间内依次按下配对按键,即可建立无线配对,sta端保存ap端wifi信息用于下次启动直连,方便快捷。