·通过wifi_scan学习esp32wifi程序编写

    在ESP32的统筹开发中,大家必定会需要动用到wifi或ble功用,先天就讲解下哪些将WIFI效能纳入到ESP32中来。

初始化WiFi环境

   首先,WiFi子系统的开头化需要由大家团结来机关,当我们写自己的主次时,需要经过调用 esp_wifi_init() 方法 来完成 。

    推荐的方法如下:

wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&config);

安装操作形式

  ESP32得以是网络中的一个站点,也可以是任何设施的接入点。 请记住,当ESP32正在一个站,它可以连接到长途一个
ACCESS点(您的WiFi核心),当作为接入点时,其他WiFi站可以接连到ESP32(想想ESP32变为WiFi集线器)。通过我们的设定,大家可以采用我们的配备进行什么样操作格局的属性(站,接入点或站点接入点)。

  那种设定是调用函数esp_wifi_set_mode()举行设定的,wifi_mode_t 其可拥有 WIFI_MODE_NULL,WIFI_MODE_STA,WIFI_MODE_AP 或 WIFI_MODE_APSTA的值。

  大家得以调用 esp_wifi_get_mode()来探寻大家脚下的格局。

环视接入点

  即便ESP32将要执行一个电台的角色,我们将索要连接到一个切入点。 大家得以要求列出我们得以动用的可用接入点尝试连接。 大家该用 esp_wifi_scan_start() 函数来 完成 。

  WiFi扫描的结果存储在ESP32分红的动态存储器内部y,当大家调用 esp_wifi_scan_get_ap_records()
时,数据再次来到到我们 这也释放内部y分配的贮存。大家誉为破坏性阅读。

  扫描记录包含在含蓄 wifi_ap_record_t 结构 的一个实例 如下:

uint8_t bssid[6]
uint8_t ssid[32]
uint8_t primary
wifi_second_chan_t second
int8_t rssi
wifi_auth_mode_t authmode

该 wifi_auth_mode_t 是以下选项中的一个:

•               WIFI_AUTH_OPEN – 没有安全性。

•               WIFI_AUTH_WEP – WEP安全性。

•               WIFI_AUTH_WPA_PSK – WPA安全性。

•               WIFI_AUTH_WPA2_PSK – WPA2安全。

•               WIFI_AUTH_WPA_WPA2_PSK – WPA或WPA2安全性。

在暴发最先施行扫描的请求后,我们将被打招呼扫描。

当 SYSTEM_EVENT_SCAN_DONE 事件发表 完成 。 

事件数量包含找到的接入点的数码,我们得以因而调用esp_wifi_scan_get_ap_num()来得到。

俺们愿目的在于完成扫描从前自行裁撤扫描,大家可以调用esp_wifi_scan_stop()。

    下面大家是一个完整的WIFI_SCAN的例证,通常,大家在事件处理程序中执行工作,当我们检测到扫描完成事件时,大家寻找定位的接入点并记下其详细音讯。

 

  1 #include "freertos/FreeRTOS.h"
  2 #include "freertos/task.h"
  3 #include "freertos/event_groups.h"
  4 #include "esp_wifi.h"
  5 #include "esp_system.h"
  6 #include "esp_event.h"
  7 #include "esp_event_loop.h"
  8 #include "esp_log.h"
  9 #include "nvs_flash.h"
 10 
 11 
 12 static EventGroupHandle_t wifi_event_group;//定义一个事件的句柄
 13 const int SCAN_DONE_BIT = BIT0;//定义事件,占用事件变量的第0位,最多可以定义32个事件。
 14 static wifi_scan_config_t scanConf  = {
 15     .ssid = NULL,
 16     .bssid = NULL,
 17     .channel = 0,
 18     .show_hidden = 1
 19 };//定义scanConf结构体,供函数esp_wifi_scan_start调用
 20 
 21 static const char *TAG = "example";
 22 
 23 esp_err_t event_handler(void *ctx, system_event_t *event)
 24 {
 25     if (event->event_id == SYSTEM_EVENT_SCAN_DONE) {
 26         xEventGroupSetBits(wifi_event_group, SCAN_DONE_BIT);        //设置事件位
 27     }
 28     return ESP_OK;
 29 }
 30 
 31 static void initialise_wifi(void)        //define a static function ,it's scope is this file
 32 {
 33     wifi_event_group = xEventGroupCreate();    //创建一个事件标志组
 34     ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));//创建事件的任务
 35     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//设置默认的wifi栈参数
 36     ESP_ERROR_CHECK(esp_wifi_init(&cfg));    //初始化WiFi Alloc资源为WiFi驱动,如WiFi控制结构,RX / TX缓冲区,WiFi NVS结构等,此WiFi也启动WiFi任务。
 37     ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));// Set the WiFi API configuration storage type
 38     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));//Set the WiFi operating mode
 39     ESP_ERROR_CHECK(esp_wifi_start());
 40     /*
 41     *           If mode is WIFI_MODE_STA, it create station control block and start station
 42     *          If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP
 43     *          If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station
 44      */
 45 }
 46 
 47 static void scan_task(void *pvParameters)
 48 {
 49     while(1) {
 50         xEventGroupWaitBits(wifi_event_group, SCAN_DONE_BIT, 0, 1, portMAX_DELAY);    //等待事件被置位,即等待扫描完成
 51         ESP_LOGI(TAG, "WIFI scan doen");
 52         xEventGroupClearBits(wifi_event_group, SCAN_DONE_BIT);//清除事件标志位
 53 
 54         uint16_t apCount = 0;
 55         esp_wifi_scan_get_ap_num(&apCount);//Get number of APs found in last scan
 56         printf("Number of access points found: %d\n", apCount);
 57         if (apCount == 0) {
 58             ESP_LOGI(TAG, "Nothing AP found");
 59             return;
 60         }//如果apCount没有受到数据,则说明没有路由器
 61         wifi_ap_record_t *list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);//定义一个wifi_ap_record_t的结构体的链表空间
 62         ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, list));//获取上次扫描中找到的AP列表。
 63         int i;
 64         printf("======================================================================\n");
 65         printf("             SSID             |    RSSI    |           AUTH           \n");
 66         printf("======================================================================\n");
 67         for (i=0; i<apCount; i++) {
 68             char *authmode;
 69             switch(list[i].authmode) {
 70             case WIFI_AUTH_OPEN:
 71                authmode = "WIFI_AUTH_OPEN";
 72                break;
 73             case WIFI_AUTH_WEP:
 74                authmode = "WIFI_AUTH_WEP";
 75                break;           
 76             case WIFI_AUTH_WPA_PSK:
 77                authmode = "WIFI_AUTH_WPA_PSK";
 78                break;           
 79             case WIFI_AUTH_WPA2_PSK:
 80                authmode = "WIFI_AUTH_WPA2_PSK";
 81                break;           
 82             case WIFI_AUTH_WPA_WPA2_PSK:
 83                authmode = "WIFI_AUTH_WPA_WPA2_PSK";
 84                break;
 85             default:
 86                authmode = "Unknown";
 87                break;
 88             }
 89             printf("%26.26s    |    % 4d    |    %22.22s\n",list[i].ssid, list[i].rssi, authmode);
 90         }//将链表的数据信息打印出来
 91         free(list);//释放链表
 92         printf("\n\n");//换行
 93 
 94         // scan again
 95         vTaskDelay(2000 / portTICK_PERIOD_MS);//调用延时函数,再次扫描
 96         //The true parameter cause the function to block until the scan is done.
 97         ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 1));//扫描所有可用的AP。
 98     }
 99 
100 
101 }
102 
103 int app_main(void)
104 {
105     nvs_flash_init();//初始化NVS flash storage
106     tcpip_adapter_init();//初始化i本机TCP/IP协议
107     initialise_wifi();//初始化wifi
108 
109     xTaskCreate(&scan_task, "scan_task", 2048, NULL, 15, NULL);//创建扫描任务
110 
111     ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 1));    //The true parameter cause the function to block until
112                                                               //the scan is done.
113     return 0;
114 }

 程序运行结果如下

      图片 1

 

 

 

 

处理WiFi事件

   在作为WiFi设备运行的长河中,ESP32恐怕会时有暴发一些事件需要驾驭。 这个也许对应用程序的运行很重大,大家清楚不可以让我们的使用程序块等待她们发​​生,因为大家不明了如何时候事情会生出,以及事件是否会时有暴发。因而,我们应该定义一个回归函数,假设事件时有发生的话就被调用,该函数就是上例中的esp_event_loop_init(), 它注册一个效果当ESP32检测到某些类型的WiFi相关事件时调用。该回调函数被调用并传递一个添加的数据结构,其中囊括事件的门类和对应于该事件的涉及数据。 

    导致回调发生的轩然大波类型:

•               大家连接受接入点

•               大家 从一个接入点 断开连接

•               授权情势已转移

•               当大家处于接入点格局时,与我们总是的一个站点

•               当我们处于接入点形式时,站与我们断开连接

•               SSID扫描完成

    当ESP32
WiFi环境运行时,它会在好几情状下发布“事件”暴发WiFi级别,例如新站连接。 我们能够挂号一个回调发表事件时调用的函数。 

    回调识别函数是:

esp_err_t eventHandler(void *ctx, system_event_t *event) {
   // Handle event here ...
   return ESP_OK;
}

    平常大家需要include下边.h文件

•               #include <esp_event.h>

•               #include <esp_event_loop.h>

•               #include <esp_wifi.h>

•               #include <esp_err.h>

要注册回调函数,大家调用:esp_event_loop_init(eventHandler,NULL);

假若我们意在随着更改与我们的WiFi处理相关联的事件处理程序我们得以

             esp_event_loop_set_cb(eventHandler,NULL);

当事件处理程序被调用时,事件参数将被填充事件。

此参数的数据类型是一个“system_event_t”,让大家前几日探视传递给system_event_t中的事件处理程序的五个属性数据结构,其中蕴涵:

system_event_id_t event_id
system_event_info_t event_info

这里event_id描述检测事件的项目,同时event_info包含基于在
event_id标识的档次事件的切实可行细节 。

•               EVENT_ID – 一个枚举类型,有下列潜在价值:

    ◦ SYSTEM_EVENT_WIFI_READY – ESP32的WiFi我 已经准备好。

    ◦
SYSTEM_EVENT_SCAN_DONE – 接入点扫描完毕。 该scan_done 数据字段是实用的拜访。

    ◦  SYSTEM_EVENT_STA_START – 作为一个station起初。

    ◦  SYSTEM_EVENT_STA_STOP – 截至作为一个station。

    ◦  SYSTEM_EVENT_STA_CONNECTED – 连接到的接入点作为站。所连接的数码字段是卓有功效的,可以拓展走访。

      ◦  SYSTEM_EVENT_STA_DISCONNECTED – 从ACCESS点作为一个站断开连接,断开连接的数据字段是可以使得的拜访的。

    ◦SYSTEM_EVENT_STA_AUTHMODE_CHANGE – 身份验证格局已经改变。该auth_change 数据字段是足以有效的拜访的。

    ◦SYSTEM_EVENT_STA_GOT_IP – 得到了 来自接入 分配的 IP地址指向大家连接受一个站点。 该 got_ip 数据字段是足以使得访问的。

    ◦  SYSTEM_EVENT_AP_START – 起初作为接入点。

    ◦SYSTEM_EVENT_AP_STOP – 结束作为接入点。

    ◦SYSTEM_EVENT_AP_STACONNECTED – 连接到一个站作为接入点。 该 sta_connected 数据字段是足以有效的访问的。

    ◦
SYSTEM_EVENT_AP_STADISCONNECTED – 从正值对接点断开一个站, 该 sta_disconnected 数据字段是足以有效的访问的。

    ◦
 SYSTEM_EVENT_AP_PROBEREQRECVED – 作为接入点收到的探测请求,该 ap_probereqrecved 数据字段是足以有效的走访。

 

 


event_info – 这是 键控关闭不同 的 数据类型 的C语言联合该事项标识 。其中饱含的不比结构是:

      结构体                    领域                    事件           

system_event_sta_connected_t              connected           
 SYSTEM_EVENT_STA_CONNECTED

system_event_sta_disconnected_t             disconnected          
 SYSTEM_EVENT_STA_DISCONNECTED

system_event_sta_scan_done_t              scan_done          
     SYSTEM_EVENT_SCAN_DONE

system_event_sta_ authmode_change_t          auth_change         
    SYSTEM_EVENT_STA_AUTHMODE_CHANGE

system_event_sta_got_ip_t                got_ip             
 SYSTEM_EVENT_STA_GOT_IP

system_event_ap_staconnected_t             sta_connected          
 SYSTEM_EVENT_AP_STACONNECTED

system_event_ao_stadisconnected_t            ap_probereqrecved        SYSTEM_EVENT_AP_PROBEREQRECVED

这一个数据结构包含与接收的事件类型有关的信息。

 

 

 

system_event_sta_connected_t

此数据类型与 SYSTEM_EVENT_STA_CONNECT 事件 相关联 。

uint8_t ssid[32]    //SSID 是,这是我们连年WiFi网络名称。

uint8_t
ssid_len    //该 ssid_len 是在包含名称 SSID 字段中 的字节数 。

uint8_t bssid[6]    //BSSID 是MAC地址的接入点

uint8_t channel    //信道 是用于该连接的无线信道

wifi_auth_mode_t
authmode    //该authmode 是连接过程中使用的安全身份验证情势。

 

 

system_event_sta_disconnected_t

此数据类型与 SYSTEM_EVENT_STA_DISCONNECTED 事件 相关联 。

uint8_t ssid[32]

uint8_t ssid_len

uint8_t bssid[6]

uint8_t reason

案由代码reason是为啥我们断开连接的指令。 符号定义为各种数字原因,下边是原因代码:

•               WIFI_REASON_UNSPECIFIED – 1

•               WIFI_REASON_AUTH_EXPIRE – 2

•               WIFI_REASON_AUTH_LEAVE – 3

•               WIFI_REASON_ASSOC_EXPIRE – 4

•               WIFI_REASON_ASSOC_TOOMANY – 5

•               WIFI_REASON_NOT_AUTHED – 6

•               WIFI_REASON_NOT_ASSOCED – 7

•               WIFI_REASON_ASSOC_LEAVE – 8

•               WIFI_REASON_ASSOC_NOT_AUTHED – 9

•               WIFI_REASON_DISASSOC_PWRCAP_BAD – 10

•               WIFI_REASON_DISASSOC_SUPCHAN_BAD – 11

•               WIFI_REASON_IE_INVALID – 13

•               WIFI_REASON_MIC_FAILURE – 14

•               WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT – 15

•               WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT – 16

•               WIFI_REASON_IE_IN_4WAY_DIFFERS – 17

•               WIFI_REASON_GROUP_CIPHER_INVALIð – 18

•               WIFI_REASON_PAIRWISE_CIPHER_INVALID – 19

•               WIFI_REASON_AKMP_INVALID – 20

•               WIFI_REASON_UNSUPP_RSN_IE_VERSION – 21

•               WIFI_REASON_INVALID_RSN_IE_CAP – 22

•               WIFI_REASON_802_1X_AUTH_FAILED – 23

•               WIFI_REASON_CIPHER_SUITE_REJECTED – 24

•               WIFI_REASON_BE ACON_TIMEOUT – 200

•               WIFI_REASON_NO_AP_FOUND – 201

•               WIFI_REASON_AUTH_FAIL – 202

•               WIFI_REASON_ASSOC_FAIL – 203

•               WIFI_REASON_HANDSHAKE_TIMEOUT – 204

 

 

 

system_event_sta_scan_done_t

此数据类型与 SYSTEM_EVENT_SCAN_DONE 事件 相关联 。

uint32_t status

uint8_t number

uint8_t scan_id

 

 

system_event_authmode_change_t

此数据类型与 SYSTEM_EVENT_STA_AUTHMODE_CHANGE 事件 相关联 。

wifi_auth_mode_t old_mode

wifi_auth_mode_t new_mode

 

system_event_sta_got_ip_t

此数据类型与 SYSTEM_EVENT_STA_GOT_IP 事件 相关联 。

tcpip_adapter_ip_info_t ip_info

所述ip_info元件是 包含两个 一 tcpip_adapter_ip_info_t 的一个实例

字段:

•               IP -The IP地址。

•              netmask – 网络掩码。

•               gw- 通信网关。

负有这三个世界是 ip4_addr_t 这是一个IP的32位表示地址。 在支付期间,您可能需要考虑记录的IP地址设备。 为此,您可以 使用:

ESP_LOGD(tag, "Got an IP: " IPSTR, IP2STR(&event->event_info.got_ip.ip_info.ip));

 

system_event_ap_staconnected_t

此数据类型与 SYSTEM_EVENT_AP_STACONNECTED 事件 相关联 。

uint8_t mac [6]

uint8_t aid

 

system_event_ap_stadisconnected_t

此数据类型与 SYSTEM_EVENT_AP_STADISCCONNECTED 事件 相关联 。

uint8_t mac[6]

uint8_t aid

 

system_event_ap_probe_req_rx_t

此数据类型与 SYSTEM_EVENT_AP_PROBREQRECVED 事件 相关联 。

int rssi

uint8_t mac [6]

假如大家启用正确的日记记录级别,我们得以看看事件到达及其内容。

例如:

D (2168) event: SYSTEM_EVENT_STA_CONNECTED, ssid:RASPI3, ssid_len:6,
bssid:00:00:13:80:3d:bd, channel:6, authmode:3
V (2168) event: enter default callback
V (2174) event: exit default callback

D (9036) event: SYSTEM_EVENT_STA_GOTIP, ip:192.168.5.62, mask:255.255.255.0,
gw:192.168.5.1
V (9036) event: enter default callback
I (9037) event: ip: 192.168.5.62, mask: 255.255.255.0, gw: 192.168.5.1
V (9043) event: exit default callback

 

 

站配置

当我们想用到ESP32用作wifi站,之后大家将认识到,在另外一个时间, 它不得不连续到一个接入点。 换句话说,该装置在同一时间连接到四个或更四个接入点。

这是大家意在赢得有关的接入点的标识设置数据结构称为 wifi_sta_config_t。该 wifi_sta_config_t 包含:

char ssid[32]
char password[64]
bool bssid_set
uint8_t bssid[6]

该协会中隐含五个要命重大的世界“SSID” 和“ password”。 SSID 字段是接入点的SSID,这是大家将连续到的AP的名称。password字段是密码的明文值将用于将我们的装置验证到目的接入点以允许连接。

 

对此这样的一个例子起始化结构可能是:

 

wifi_config_t staConfig = {
   .sta = {
      .ssid="<access point name>",
      .password="<password>",
      .bssid_set=false
   }
};

假使大家填写了那多少个结构的实例,大家就足以指示ESP32的选取了。

esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *)&staConfig);

 

我们在此以前讲到的格局设置也可以应用了

esp_wifi_set_mode(WIFI_MO DE_STA)
或
esp_wifi_set_mode(WIFI_MODE_APSTA)

 

 

 

启动WiFi环境

  当WiFi阐明通过后,可能会问的问题是“啥时候WiFi可以利用?”通常对于ESP32我们要告知它它是一个站点或接入点,然后配置它参数如连续到哪个接入点(假使是站)或自己的接入点身份应该是(尽管它将改成接入点)。 鉴于那多少个是一文山会海的步骤,我们实在不希望ESP32履行这个职责直到我们完成了富有的安装。  例如,假如我们启动一个ESP32并安装它是一个接入点,要是他立即作为接入点的话,可能会产出错误,或者暂时作为不当的接入点存在,这是我们不指望看到的。因而,我们必须学习最终的下令指示到WiFi子系统开始工作。 那么些命令是esp_wifi_start()。在调用这么些函数在此之前,大家正在做的是确立环境。只有经过调用 esp_wifi_start() ,WiFi子系统才起先做此外实际工作。同样的有个照应的命令esp_wifi_stop(),其可以告一段落WIFI子系统。

 

总是到接入点

  通过前边的任课,已经主导教学了wifi的基本操作,ES32接入接入点AP的实例请看下一篇著作

有关esp32的省电格局的WiFi连接

 

 

 

连带知识:wifi相关的API接口

 

 

 

 

 

 

 

相关文章