Wi-Fi, or a wireless network, is a communication model that makes it possible to interact with another system. With these, we can perform common network tasks over network protocols such as TCP/IP, UDP/IP, HTTP, or SMTP/POP3. Since the ESP32 chip has built-in Wi-Fi and a Bluetooth module, we connect our ESP32 board to an existing network.
To work with Wi-Fi on ESP32, we need the esp_wifi.h header file to be included in our project:
Wi-Fi programming in ESP32 uses an event-based model. We call the Wi-Fi API from the board driver in order to access the Wi-Fi module on the ESP32 board. The ESP32 Wi-Fi API supports Wi-Fi security such as WPA, WPA2, and WEP. A list of Wi-Fi API functions can be found at https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/network/esp_wifi.html.
In this chapter, we will work with a Wi-Fi network stack in the ESP32 board. For demo purposes, I have used the ESP-WROVER-KIT v4 board.
The first demo is used to perform Wi-Fi scanning. We will scan for all existing Wi-Fi networks in the surrounding area in which we are present. First, we will create the ESP32 project, called wifiscan. Our main program is wifiscan.c.
Next, we load all libraries from header files into our program as follows:
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
In the main entry app_main() function, we initialize storage for the Wi-Fi program by calling the esp_wifi_set_storage() function. We also need a function to listen to incoming events from the Wi-Fi API. For instance, we create a function named event_handler() and pass it into the esp_event_loop_init() function.
Next, we run the Wi-Fi service on ESP32 by calling the esp_wifi_start() function:
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
tcpip_adapter_init();
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));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());
After the Wi-Fi service has started, we will perform Wi-Fi scanning using the esp_wifi_scan_start() function. To do this, we should pass the wifi_scan_config_t parameter into esp_wifi_scan_start(). For Wi-Fi scanning, we set NULL for the ssid and bssid parameters.
We perform looping in Wi-Fi scanning. After the Wi-Fi scanning process is done, we again call esp_wifi_scan_start():
wifi_scan_config_t scanConf = {
.ssid = NULL,
.bssid = NULL,
.channel = 0,
.show_hidden = true
};
while(true){
ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, true));
vTaskDelay(3000 / portTICK_PERIOD_MS);
} Now, we will implement the event_handler() function. Technically, we receive all events from the Wi-Fi service. You can read about Wi-Fi events in the ESP32 documentation at https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/wifi.html.
In this scenario, we will wait for the SYSTEM_EVENT_SCAN_DONE event. This event is raised after ESP32 performs the Wi-Fi scanning. To get the result of Wi-Fi scanning, we can call the esp_wifi_scan_get_ap_num() function.
Then, we will loop our program to retrieve Wi-Fi hotspot information by calling the esp_wifi_scan_get_ap_records() function. We will then print the Wi-Fi information into the Terminal as follows:
esp_err_t event_handler(void *ctx, system_event_t *event)
{
if (event->event_id == SYSTEM_EVENT_SCAN_DONE) {
uint16_t apCount = 0;
esp_wifi_scan_get_ap_num(&apCount);
printf("Wi-Fi found: %d\n",event->event_info.scan_done.number);
if (apCount == 0) {
return ESP_OK;
}
wifi_ap_record_t *wifi = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, wifi));
....
}
After we have obtained a list of wifi_ap_record_t items, we will set the authentication name based on the wifi_ap_record_t.authmode type, as follows:
for (int i=0; i<apCount; i++) {
char *authmode;
switch(wifi[i].authmode) {
case WIFI_AUTH_OPEN:
authmode = "NO AUTH";
break;
case WIFI_AUTH_WEP:
authmode = "WEP";
break;
case WIFI_AUTH_WPA_PSK:
authmode = "WPA PSK";
break;
case WIFI_AUTH_WPA2_PSK:
authmode = "WPA2 PSK";
break;
case WIFI_AUTH_WPA_WPA2_PSK:
authm...