esp32s3中ap與sta模式的wps配對問題

無線路由器中的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 edgegpio_config_t io_conf = {};io_conf.intr_type = GPIO_INTR_NEGEDGE;//bit mask of the pins, use GPIO4/5 hereio_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;//set as input modeio_conf.mode = GPIO_MODE_INPUT;//enable pull-up modeio_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 taskxTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, GPIO_KEY_TASK_PRIORITY, NULL);//install gpio isr servicegpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);//hook isr handler for specific gpio pingpio_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_cipherwifi_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 edgegpio_config_t io_conf = {};io_conf.intr_type = GPIO_INTR_NEGEDGE;//bit mask of the pins, use GPIO4/5 hereio_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;//set as input modeio_conf.mode = GPIO_MODE_INPUT;//enable pull-up modeio_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 taskxTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, GPIO_KEY_TASK_PRIORITY, NULL);//install gpio isr servicegpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);//hook isr handler for specific gpio pingpio_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 macwifi_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信息用于下次啟動直連,方便快捷。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/14096.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/14096.shtml
英文地址,請注明出處:http://en.pswp.cn/web/14096.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

20232802 黃千里 2023-2024-2 《網絡攻防實踐》實踐十一報告

20232802 2023-2024-2 《網絡攻防實踐》實踐十一報告 1.實踐過程 1.1web瀏覽器滲透攻擊 攻擊機&#xff1a;kali172.20.10.10靶機&#xff1a;win2k172.20.10.3 首先在kali中啟動msfconsole 輸入命令search MS06-014&#xff0c;搜索滲透攻擊模塊 輸入use exploit/window…

終于讓我找到了,你也可以學會的人工智能-機器學習教程

給大家分享一套非常棒的python機器學習課程——《AI小天才&#xff1a;讓小學生輕松掌握機器學習》&#xff0c;2024年5月完結新課&#xff0c;提供配套的代碼筆記軟件包下載&#xff01;學完本課程&#xff0c;可以輕松掌握機器學習的全面應用&#xff0c;復雜特征工程&#x…

C# 跨線程訪問UI組件,serialPort1串口接收數據

在Windows應用程序&#xff08;例如WinForms或WPF&#xff09;中&#xff0c;UI組件&#xff08;如按鈕、文本框等&#xff09;都在主線程&#xff08;也稱為UI線程&#xff09;上運行。當你在一個非UI線程&#xff08;例如&#xff0c;一個后臺線程或者網絡請求線程&#xff0…

關于新配置的adb,設備管理器找不到此設備問題

上面頁面中一開始沒有找到此android設備&#xff0c; 可能是因為我重新配置的adb和設備驅動&#xff0c; 只把adb配置了環境變量&#xff0c;驅動沒有更新到電腦中&#xff0c; 點擊添加驅動&#xff0c; 選擇路徑&#xff0c;我安裝時都放在了SDK下面&#xff0c;可以嘗試…

SpringBoot 實現 RAS+AES 自動接口解密

一、講個事故 接口安全老生常談了 過年之前做了過一款飛機大戰的H5小游戲&#xff0c;里面無限模式-需要保存用戶的積分&#xff0c;因為使用的Body傳參&#xff0c;參數是可見的。 為了接口安全我&#xff0c;我和前端約定了傳遞參數是&#xff1a;用戶無限模式的積分“我們…

HTML靜態網頁成品作業(HTML+CSS)——魅族商城首頁網頁(1個頁面)

&#x1f389;不定期分享源碼&#xff0c;關注不丟失哦 文章目錄 一、作品介紹二、作品演示三、代碼目錄四、網站代碼HTML部分代碼 五、源碼獲取 一、作品介紹 &#x1f3f7;?本套采用HTMLCSS&#xff0c;未使用Javacsript代碼&#xff0c;共有1個頁面。 二、作品演示 三、代…

基于Python+OpenCV卷積神經網絡的字符識別

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景與意義 字符識別是計算機視覺和模式識別領域的一個重要應用&#xff0c;它在文檔數字化、車牌識別、驗…

gpt-4o考場安排

說明 &#xff1a;經過多次交互&#xff0c;前后花了幾個小時&#xff0c;總算完成了基本功能。如果做到按不同層次分配考場&#xff0c;一鍵出打印結果就完美了。如果不想看中間“艱苦”的過程&#xff0c;請直接跳到“最后結果”及“食用方法”。中間過程還省略了一部分交互&…

Android-多個tv_item_[i] 點擊事件簡寫

private TextView[] tvConstellations new TextView[12];//獲取當前id元素并在其點擊的時候修改其顏色 for (int i 0; i < 12; i) {int resId getResources().getIdentifier("tv_constellation_" (i1), "id", getPackageName());tvConstellations[i…

神經網絡與深度學習 課程復習總結

神經網絡的發展歷史 第一代神經網絡&#xff08;1958~1969&#xff09; MCP模型&#xff08;1943年&#xff09;&#xff1a;麥卡洛克和皮茨提出了第一個人工神經元模型&#xff0c;簡化為輸入信號線性加權、求和、非線性激活&#xff08;閾值法&#xff09;。感知器&#xf…

鴻蒙開發 組件之間的傳值

1.Prop&#xff1a;父組件傳遞給子組件&#xff0c;單向傳遞&#xff0c;子組件改變值&#xff0c;父組件UI不更新。 引入子組件 并賦值&#xff0c;子組件用Prop 接收 import headerView from ../../common/bean/BaseNavHeaderView headerView({titlestr:添加地址,isback…

go slice 擴容

擴容 slice 會遷移到新的內存位置&#xff0c;新底層數組的長度也會增加&#xff0c;這樣就可以放置新增的元素。同時&#xff0c;為了應對未來可能再次發生的 append 操作&#xff0c;新的底層數組的長度&#xff0c;也就是新 slice 的容量是留了一定的 buffer 的。否則&…

【C++】STL快速入門基礎

文章目錄 STL&#xff08;Standard Template Library&#xff09;1、一般介紹2、STL的六大組件2.1、STL容器2.2、STL迭代器2.3、相關容器的函數vectorpairstringqueuepriority_queuestackdequeset, map, multiset, multimapunordered_set, unordered_map, unordered_multiset, …

LabVIEW2022安裝教程指南【附安裝包】

文章目錄 前言一、安裝指南1、軟件包獲取 二、安裝步驟總結 前言 LabVIEW是一種程序開發環境&#xff0c;提供一種圖形化編程方法&#xff0c;可可視化應用程序的各個方面&#xff0c;包括硬件配置、測量數據和調試&#xff0c;同時可以通過FPGA數學和分析選板中的NI浮點庫鏈接…

有趣的css - 兩個圓形加載效果

大家好&#xff0c;我是 Just&#xff0c;這里是「設計師工作日常」&#xff0c;今天分享的是一款小清新的加載動畫&#xff0c;適用于 app 列表加載&#xff0c;頁面加載或者彈層內容延遲加載等場景。 最新文章通過公眾號「設計師工作日常」發布。 目錄 整體效果核心代碼html…

AWS安全性身份和合規性之Amazon Macie

Amazon Macie是一項數據安全和數據隱私服務&#xff0c;它利用機器學習&#xff08;ML&#xff09;和模式匹配來發現和保護敏感數據。可幫助客戶發現、分類和保護其敏感數據&#xff0c;以及監控其數據存儲庫的安全性。 應用場景&#xff1a; 敏感數據發現 一家金融服務公司…

20年交易老兵悟出的寶貴經驗,做到這10點或許你也能躺著賺錢

交易要靠親身體驗來真正獲得發展&#xff0c;在正確引導下&#xff0c;我們就不會把時間和精力浪費在彎路上。交易之技易學&#xff0c;實難在心態與思考。接下來&#xff0c;我將與您分享一位交易了20年的老兵所積累的10條珍貴經驗。 Nial Fuller,一個交易了接近20年的市場“老…

Git遠程控制

文章目錄 1. 創建倉庫1.1 Readme1.2 Issue1.3 Pull request 2. 遠程倉庫克隆3. 推送遠程倉庫4. 拉取遠程倉庫5. 配置Git.gitignore配置別名 使用GitHub可以&#xff0c;采用Gitee也行 1. 創建倉庫 1.1 Readme Readme文件相當于這個倉庫的說明書&#xff0c;gitee會初始化2兩份…

go mod模式下,import gitlab中的項目

背景 為了go項目能夠盡可能復用代碼&#xff0c;把一些公用的工具類&#xff0c;公用的方法等放到共用包里統一管理。把共用包放到gitlab的私有倉庫中。 遇到的問題 通過https方式&#xff0c;執行go get報了錯誤。 通過ssh方式&#xff0c;執行go get報了錯誤。 修改配置&am…

介紹一個免費的在線pdf轉word網站

Smallpdf.com - A Free Solution to all your PDF Problems 轉換效果不錯&#xff0c;比那些收費的軟件強多了&#xff0c;主要是免費的&#xff01;