В данной статье мы рассмотрим как сканировать все ближайшие точки доступа с помощью ESP32 и ESP-IDF. Мы отобразим значения RSSI отсканированных точек доступа, тип аутентификации и канал. ESP-IDF предоставляет библиотеку esp_wifi.h, которую мы используем для сканирования, подключения к точкам доступа и мониторинга состояния Wi-Fi ESP32 с помощью различных событий. Этот API включает в себя настройку режимов точки доступа и Wi-Fi-станции ESP32 в различных режимах безопасности, например, WPA, WEP и т. д., мониторинг пакетов Wi-Fi и сканирование ближайших точек доступа.

Функция сканирования Wi-Fi полезна, когда у вас несколько точек доступа и вы хотите подключиться к самой мощной точке доступа. Например, вы используете ESP32 в режиме станции. В этом режиме ESP32 может отключиться от вашей сети по какой-либо причине, например, из-за отключения сети и т. д. В такой ситуации мы можем использовать сканирование Wi-Fi и подключить ESP32 к другому маршрутизатору или точке доступа.
В предыдущих статьях на нашем сайте мы рассмотрели, как настроить ESP32 в качестве точки доступа и как перевести его в режим станции. Эти статьи вы можете прочитать по следующим ссылкам:
- настройка Wi-Fi точки доступа (AP) на ESP32 с помощью ESP-IDF;
- подключение ESP32 по Wi-Fi в режиме станции с помощью ESP-IDF.
Сканирование Wi-Fi на ESP32
Давайте создадим пример проекта в ESP-IDF и запрограммируем нашу плату ESP32 с помощью скетча сканирования Wi-Fi. Также мы обсудим API из файла esp_wifi.h, которые потребуются для этого проекта.
Создание примера проекта
Откройте VS Code и перейдите в меню View > Command Palette («Вид» > «Палитра команд»). Введите в строке поиска ESP-IDF: New Project и нажмите Enter.
Укажите название проекта и каталог. Мы назвали наш проект «ESP32_WIFI_SCAN». Для платы ESP-IDF мы выбрали опцию custom board («Пользовательская плата»). В качестве целевой платформы ESP-IDF мы выбрали модуль ESP32. Нажмите кнопку ‘Choose Template’ («Выбрать шаблон»), чтобы продолжить.
В разделе Extension («Расширение») выберите опцию ESP-IDF:
На вкладке get-started («Начало работы») мы щелкнем по пункту «sample_project». Затем нажмем ‘Create project using template sample_project’ («Создать проект, используя шаблон sample_project»).
Вы получите уведомление о создании проекта. Чтобы открыть проект в новом окне, нажмите «Да».
Это открывает наш проект ESP32_WIFI_SCAN, который мы создали на вкладке EXPLORER. Внутри папки проекта находится несколько папок. Это справедливо для всех проектов, которые вы будете создавать с помощью ESP-IDF Explorer.
Код ESP-IDF для сканирования Wi-Fi на ESP32
В папке main находится исходный код, то есть файл main.c будет расположен здесь. Перейдите в папку main > main.c и откройте его. Скопируйте приведенный ниже код и сохраните его. Следующий код использует функции библиотеки esp_wifi.h для сканирования всех ближайших сетей Wi-Fi, а также их значений RSSI, канала и типа аутентификации.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_event_loop.h" #include "esp_wifi.h" #include "esp_log.h" #include "nvs_flash.h" #define MAXIMUM_AP 20 static esp_err_t event_handler(void * ctx, system_event_t *event) { return ESP_OK; } static char *auth_mode_type(wifi_auth_mode_t auth_mode) { char *types[] = {"OPEN", "WEP", "WPA PSK", "WPA2 PSK", "WPA WPA2 PSK", "MAX"}; return types[auth_mode]; } void wifiInit() { ESP_ERROR_CHECK(nvs_flash_init()); tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&wifi_config)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); } void app_main() { wifiInit(); wifi_scan_config_t scan_config = { .ssid = 0, .bssid = 0, .channel = 0, .show_hidden = true }; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, true)); wifi_ap_record_t wifi_records[MAXIMUM_AP]; uint16_t max_records = MAXIMUM_AP; ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&max_records, wifi_records)); printf("Number of Access Points Found: %d\n", max_records); printf("\n"); printf(" SSID | Channel | RSSI | Authentication Mode \n"); printf("***************************************************************\n"); for (int i = 0; i < max_records; i++) printf("%32s | %7d | %4d | %12s\n", (char *)wifi_records[i].ssid, wifi_records[i].primary, wifi_records[i].rssi, auth_mode_type(wifi_records[i].authmode)); printf("***************************************************************\n"); } |
Как работает код?
Для начала мы подключим необходимые библиотеки, включая esp_wifi.h для работы с Wi-Fi, esp_log.h в качестве библиотеки для ведения журналов и библиотеку энергонезависимой памяти (NVS).
|
1 2 3 4 5 6 7 |
#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_event_loop.h" #include "esp_wifi.h" #include "esp_log.h" #include "nvs_flash.h" |
Мы определили максимальное количество точек доступа, которые могут быть просканированы, равным 20.
|
1 |
#define MAXIMUM_AP 20 |
Эта функция возвращает режим аутентификации. Доступные типы: Open, WEP, WPA PSK, WPA2 PSK, WPA WPA2 PSK и MAX.
|
1 2 3 4 5 |
static char *auth_mode_type(wifi_auth_mode_t auth_mode) { char *types[] = {"OPEN", "WEP", "WPA PSK", "WPA2 PSK", "WPA WPA2 PSK", "MAX"}; return types[auth_mode]; } |
wifiInit()
|
1 2 3 4 5 6 7 8 9 10 11 |
void wifiInit() { ESP_ERROR_CHECK(nvs_flash_init()); tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&wifi_config)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); } |
Внутри функции wifiInit() мы сначала инициализируем NVS и базовый стек TCP/IP, вызвав функции nvs_flash_init() и tcpip_adapter_init() соответственно.
|
1 2 |
ESP_ERROR_CHECK(nvs_flash_init()); tcpip_adapter_init(); |
Для запуска реализации цикла событий мы вызываем функцию esp_event_loop_init(). Эта функция принимает два параметра. Первый параметр — это указатель на функцию обработчика событий, а второй — произвольный указатель на контекст.
|
1 |
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); |
Это функция event_handler().
|
1 2 3 |
static esp_err_t event_handler(void * ctx, system_event_t *event) { return ESP_OK; } |
Затем мы инициализируем ресурс выделения Wi-Fi для драйвера Wi-Fi. Он отвечает за запуск задачи Wi-Fi. Он принимает единственный параметр wifi_config, который является указателем на уже инициализированную структуру конфигурации Wi-Fi, установленную в значение WIFI_INIT_CONFIG_DEFAULT(), так что инициализация конфигурации происходит со значениями по умолчанию. Здесь wifi_init_config_t — это структура, обозначающая параметры конфигурации стека Wi-Fi, которые передаются в функцию esp_wifi_init().
|
1 2 |
wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&wifi_config)); |
Кроме того, мы устанавливаем режим Wi-Fi как «станция». Для этого мы используем функцию esp_wifi_set_mode() и передаем в качестве параметра параметр WiFI_MODE_STA.
|
1 |
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); |
Затем мы запускаем Wi-Fi-соединение с заданной конфигурацией, используя функцию esp_wifi_start().
|
1 |
ESP_ERROR_CHECK(esp_wifi_start()); |
app_main()
Внутри функции app_main() мы сначала вызовем функцию wifiInit() для инициализации и запуска Wi-Fi-соединения.
|
1 |
wifiInit(); |
Далее мы вызываем функцию esp_wifi_scan_start() для сканирования всех ближайших точек доступа. Эта функция принимает два параметра.
- Первый параметр — это конфигурация сканирования, определяемая структурой wifi_scan_config_t. Она содержит различные параметры конфигурации сканирования, включая SSID, BSSID, канал и отображение скрытых точек доступа.
- Второй параметр — это переменная 'block' типа bool. Если она установлена как true, то вызывающая сторона будет заблокирована до завершения сканирования, в противном случае функция немедленно возвращает управление.
|
1 2 3 4 5 6 7 8 |
wifi_scan_config_t scan_config = { .ssid = 0, .bssid = 0, .channel = 0, .show_hidden = true }; ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, true)); |
Чтобы получить список точек доступа, которые были просканированы в ходе последнего сканирования, мы вызываем функцию esp_wifi_scan_get_ap_records(). Эта функция принимает два параметра.
- Первый параметр может выступать как в качестве входного, так и в качестве выходного параметра. В качестве входного параметра он содержит максимальное количество точек доступа. В качестве выходного параметра он получает номер точки доступа, который возвращает данный API.
- Второй параметр — это 'ap_records', в нашем случае это 'wifi_records'. Это массив типа wifi_ap_record_t, содержащий список отсканированных точек доступа.
|
1 2 3 4 |
wifi_ap_record_t wifi_records[MAXIMUM_AP]; uint16_t max_records = MAXIMUM_AP; ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&max_records, wifi_records)); |
В этот момент ESP-IDF выводит количество найденных точек доступа, которые хранятся в переменной 'max_records'. После этого он выводит подробную информацию о сканированных ближайших сетях, включая SSID, канал, RSSI и режим аутентификации.
|
1 2 3 4 5 6 7 |
printf("Number of Access Points Found: %d\n", max_records); printf("\n"); printf(" SSID | Channel | RSSI | Authentication Mode \n"); printf("***************************************************************\n"); for (int i = 0; i < max_records; i++) printf("%32s | %7d | %4d | %12s\n", (char *)wifi_records[i].ssid, wifi_records[i].primary, wifi_records[i].rssi, auth_mode_type(wifi_records[i].authmode)); printf("***************************************************************\n"); |
Компиляция скетча
Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте заменить COM-порт на тот, через который подключена ваша плата.
|
1 |
idf.py -p COMX flash monitor |
После успешной прошивки кода терминал ESP-IDF выводит количество отсканированных точек доступа и список различных параметров. В нашем случае было отсканировано 5 точек доступа поблизости. Также можно увидеть SSID, канал, уровень RSSI и режим аутентификации каждой сети.
1 просмотров







