ESP32 WiFi — различия между версиями

Материал из razgovorov.ru
Перейти к: навигация, поиск
(Initializing the WiFi environment)
(/)
 
(не показано 11 промежуточных версий этого же участника)
Строка 1: Строка 1:
===WiFi Theory===
+
===WiFi теория===
When working with a WiFi oriented device, it is important that we have at least some
+
При работе с ориентированным на WiFi устройством важно, чтобы у нас было хотя бы некоторое понимание концепций, связанных с WiFi. На высоком уровне WiFi - это способность
understanding of the concepts related to WiFi. At a high level, WiFi is the ability to
+
участвовать в соединениях TCP/IP по линии беспроводной связи. Wi-Fi - это, в частности, набор протоколов, описанных в архитектуре беспроводной локальной сети IEEE 802.11.
participate in TCP/IP connections over a wireless communication link. WiFi is
 
specifically the set of protocols described in the IEEE 802.11 Wireless LAN architecture.
 
  
Within this story, a device called a Wireless Access Point (access point or AP) acts as
+
В этой истории устройство, называемое точкой беспроводного доступа (точка доступа или AP), выступает в качестве центра всех коммуникаций. Обычно он подключается (или действует как) как маршрутизатор TCP/IP к остальной части сети TCP/IP. Например, в вашем доме вы, вероятно, будете иметь точку доступа WiFi, подключенную к вашему модему (кабель или DSL). Затем к точке доступа формируются соединения WiFi (через устройства, называемые клиентами), а трафик TCP/IP - через точку доступа в Интернет.
the hub of all communications. Typically it is connected to (or acts as) as TCP/IP router
 
to the rest of the TCP/IP network. For example, in your home, you are likely to have a
 
WiFi access point connected to your modem (cable or DSL). WiFi connections are then
 
formed to the access point (through devices called stations) and TCP/IP traffic flows
 
through the access point to the Internet.
 
  
The devices that connect to the access points are called "stations":
+
Устройства, которые подключаются к точкам доступа, называются «клиентами»:
  
An ESP32 device can play the role of an Access Point, a Station or both at the same
+
Устройство ESP32 может играть роль точки доступа, клиента или обоих одновременно.
time.
 
  
Very commonly, the access point also has a network connection to the Internet and acts
+
Чаще всего точка доступа также имеет сетевое подключение к Интернету и выступает в качестве моста между беспроводной сетью и более широкой сетью TCP/IP, являющейся Интернетом.
as a bridge between the wireless network and the broader TCP/IP network that is the
 
Internet.
 
  
A collection of stations that wish to communicate with each other is termed a Basic
+
Набор клиентов, которые хотят общаться друг с другом, называется базовым набором услуг (BSS). Общая конфигурация - это то, что известно как BSS инфраструктуры. В этом режиме все входящие и исходящие сообщения от отдельной станции маршрутизируются через точку доступа.
Service Set (BSS). The common configuration is what is known as an Infrastructure
 
BSS. In this mode, all communications inbound and outbound from an individual station
 
are routed through the access point.
 
  
A station must associate itself with an access point in order to participate in the story. A
+
Клиент должен ассоциироваться с точкой доступа для участия в истории. Клиент может быть связан только с одной точкой доступа в любой момент времени. Каждый участник сети имеет уникальный идентификатор, называемый MAC-адресом. Это 48-битное значение.
station may only be associated with a single access point at any one time.
 
Each participant in the network has a unique identifier called the MAC address. This is
 
a 48bit value.
 
  
When we have multiple access points within wireless range, the station needs to know
+
Когда у нас есть несколько точек доступа в беспроводном диапазоне, станция должна знать, с какой из них можно подключиться. Каждая точка доступа имеет сетевой идентификатор, называемый BSSID (или чаще всего SSID). SSID - это идентификатор набора услуг. Это 32-значное значение, которое представляет собой цель пакетов информации, отправляемых по сети.
with which one to connect. Each access point has a network identifier called the BSSID
 
(or more commonly just SSID). SSID is service set identifier. It is a 32 character value
 
that represents the target of packets of information sent over the network.
 
  
 
See also:
 
See also:
Строка 53: Строка 34:
 
• esp_wifi_init
 
• esp_wifi_init
  
===Setting the operation mode===
+
===Установка режима работы===
The ESP32 can either be a station in the network, an access point for other devices or
+
ESP32 может быть либо клиентом, либо точкой доступа для других устройств, либо и тем, и другим. Помните, что когда ESP32 является станцией, он может подключаться к удаленной точке доступа (ваш WiFi-концентратор), тогда как в качестве точки доступа другие WiFi-станции могут подключаться к ESP32 (подумайте о том, что ESP32 становится WiFi-хабом). Это фундаментальное соображение, и мы захотим выбрать, как устройство ведет себя на ранней стадии разработки нашего приложения. После того, как мы выбрали то, что хотим, мы устанавливаем свойство глобального режима, которое указывает, какой из режимов работы будет выполнять наше устройство (клиент, точка доступа или точка доступа и клиент).
both. Remember, when an ESP32 is being a station, it can connect to a remote access
 
point (your WiFi hub) while when being an access point, other WiFi stations can connect
 
to the ESP32 (think of the ESP32 as becoming a WiFi hub). This is a fundamental
 
consideration and we will want to choose how the device behaves early on in our
 
application design. Once we have chosen what we want, we set a global mode
 
property which indicates which of the operational modes our device will perform (station,
 
access point or station AND access point).
 
  
This choice is set with a call to esp_wifi_set_mode(). The parameter is an instance of
+
Этот выбор задается вызовом esp_wifi_set_mode(). Параметр - это экземпляр wifi_mode_t, который может иметь значение WIFI_MODE_NULL, WIFI_MODE_STA, WIFI_MODE_AP или WIFI_MODE_APSTA. Мы можем вызвать esp_wifi_get_mode(), чтобы получить текущий режим работы.
wifi_mode_t which can have a value of WIFI_MODE_NULL, WIFI_MODE_STA, WIFI_MODE_AP
 
or WIFI_MODE_APSTA. We can call esp_wifi_get_mode() to retrieve our current mode
 
state.
 
  
===Scanning for access points===
+
===Сканирование точек доступа===
If the ESP32 is going to be performing the role of a station we will need to connect to an
+
Если ESP32 будет выполнять роль клиента, нам нужно будет подключиться к точке доступа. Мы можем запросить список доступных точек доступа, с которыми мы можем попытаться подключиться. Делается это с помощью функции esp_wifi_scan_start ().
access point. We can request a list of the available access points against which we can
 
attempt to connect. We do this using the esp_wifi_scan_start() function.
 
  
The results of a WiFi scan are stored internally in ESP32 dynamically allocated storage.
+
Результаты сканирования WiFi хранятся внутри динамически распределенного хранилища ESP32.
  
The data is returned to us when we call esp_wifi_scan_get_ap_records() which also
+
Данные возвращаются нам при вызове esp_wifi_scan_get_ap_records(), который также освобождает внутренне выделенное хранилище. Таким образом, это следует рассматривать как деструктивное чтение.
releases the internally allocated storage. As such, this should be considered a
 
destructive read.
 
  
A scan record is contained in an instance of a wifi_ap_record_t structure that contains:
+
Запись сканирования содержится в экземпляре структуры wifi_ap_record_t, которая содержит:
uint8_t bssid[6]
+
<source lang=c>
uint8_t ssid[32]
+
          uint8_t bssid[6]
uint8_t primary
+
          uint8_t ssid[32]
 +
          uint8_t primary
 
wifi_second_chan_t second
 
wifi_second_chan_t second
int8_t rssi
+
            int8_t rssi
wifi_auth_mode_t authmode
+
  wifi_auth_mode_t authmode
 +
</source>
  
The wifi_auth_mode_t is one of:
+
wifi_auth_mode_t принимает одно из значений:
WIFI_AUTH_OPEN – No security.
+
* WIFI_AUTH_OPEN – No security.
WIFI_AUTH_WEP – WEP security.
+
* WIFI_AUTH_WEP – WEP security.
WIFI_AUTH_WPA_PSK – WPA security.
+
* WIFI_AUTH_WPA_PSK – WPA security.
WIFI_AUTH_WPA2_PSK – WPA2 security.
+
* WIFI_AUTH_WPA2_PSK – WPA2 security.
WIFI_AUTH_WPA_WPA2_PSK – WPA or WPA2 security.
+
* WIFI_AUTH_WPA_WPA2_PSK – WPA or WPA2 security.
  
After issuing the request to start performing a scan, we will be informed that the scan
+
После того, как вы отправите запрос на выполнение сканирования, узнать о его завершении можно по событию SYSTEM_EVENT_SCAN_DONE. Данные события содержат количество найденных точек доступа, и могут быть получены вызовом esp_wifi_scan_get_ap_num().
completed when a SYSTEM_EVENT_SCAN_DONE event is published. The event data
 
contains the number of access points found but that can also be retrieved with a call to
 
esp_wifi_scan_get_ap_num().
 
  
Should we wish to cancel the scanning before it completes on its own, we can call
+
Если мы хотим отменить сканирование до его завершения самостоятельно, мы можем вызвать esp_wifi_scan_stop().
esp_wifi_scan_stop().
 
  
Here is a complete sample application illustrating performing a WiFi scan. Much of the
+
Вот полное примерное приложение, иллюстрирующее выполнение проверки WiFi. Большая часть работы выполняется в обработчике событий. Когда мы обнаруживаем событие завершения сканирования, мы получаем найденные точки доступа и записываем их данные.
work is performed in the event handler. When we detect a scan completion event, we
 
retrieve the located access points and log their details.
 
 
<source lang=c>
 
<source lang=c>
 
#include "esp_wifi.h"
 
#include "esp_wifi.h"
Строка 113: Строка 76:
 
esp_err_t event_handler(void *ctx, system_event_t *event)
 
esp_err_t event_handler(void *ctx, system_event_t *event)
 
{
 
{
if (event->event_id == SYSTEM_EVENT_SCAN_DONE) {
+
  if (event->event_id == SYSTEM_EVENT_SCAN_DONE) {
printf("Number of access points found: %d\n",
+
      printf("Number of access points found: %d\n",
event->event_info.scan_done.number);
+
      event->event_info.scan_done.number);
uint16_t apCount = event->event_info.scan_done.number;
+
      uint16_t apCount = event->event_info.scan_done.number;
if (apCount == 0) {
+
      if (apCount == 0) {
return ESP_OK;
+
        return ESP_OK;
 +
      }
 +
      wifi_ap_record_t *list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
 +
      ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, list));
 +
      int i;
 +
      for (i=0; i<apCount; i++) {
 +
        char *authmode;
 +
        switch(list[i].authmode) {
 +
            case WIFI_AUTH_OPEN:
 +
              authmode = "WIFI_AUTH_OPEN";
 +
              break;
 +
            case WIFI_AUTH_WEP:
 +
              authmode = "WIFI_AUTH_WEP";
 +
              break;
 +
            case WIFI_AUTH_WPA_PSK:
 +
              authmode = "WIFI_AUTH_WPA_PSK";
 +
              break;
 +
            case WIFI_AUTH_WPA2_PSK:
 +
              authmode = "WIFI_AUTH_WPA2_PSK";
 +
              break;
 +
            case WIFI_AUTH_WPA_WPA2_PSK:
 +
              authmode = "WIFI_AUTH_WPA_WPA2_PSK";
 +
              break;
 +
            default:
 +
              authmode = "Unknown";
 +
              break;
 +
        }
 +
        printf("ssid=%s, rssi=%d, authmode=%s\n",
 +
        list[i].ssid, list[i].rssi, authmode);
 +
      }
 +
      free(list);
 +
  }
 +
  return ESP_OK;
 
}
 
}
wifi_ap_record_t *list =
+
 
(wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
+
int app_main(void){
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, list));
+
  nvs_flash_init();
int i;
+
  tcpip_adapter_init();
for (i=0; i<apCount; i++) {
+
  ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
char *authmode;
+
  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
switch(list[i].authmode) {
+
  ESP_ERROR_CHECK(esp_wifi_init(&cfg));
case WIFI_AUTH_OPEN:
+
  ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
authmode = "WIFI_AUTH_OPEN";
+
  ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
break;
+
  ESP_ERROR_CHECK(esp_wifi_start());
case WIFI_AUTH_WEP:
+
  // Let us test a WiFi scan ...
authmode = "WIFI_AUTH_WEP";
+
  wifi_scan_config_t scanConf = {
break;
+
      .ssid = NULL,
case WIFI_AUTH_WPA_PSK:
+
      .bssid = NULL,
authmode = "WIFI_AUTH_WPA_PSK";
+
      .channel = 0,
break;
+
      .show_hidden = 1
case WIFI_AUTH_WPA2_PSK:
+
  };
authmode = "WIFI_AUTH_WPA2_PSK";
+
  ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 0));
break;
+
  return 0;
case WIFI_AUTH_WPA_WPA2_PSK:
 
authmode = "WIFI_AUTH_WPA_WPA2_PSK";
 
break;
 
default:
 
authmode = "Unknown";
 
break;
 
}
 
printf("ssid=%s, rssi=%d, authmode=%s\n",
 
list[i].ssid, list[i].rssi, authmode);
 
}
 
free(list);
 
}
 
return ESP_OK;
 
}
 
int app_main(void)
 
{
 
nvs_flash_init();
 
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());
 
// Let us test a WiFi scan ...
 
wifi_scan_config_t scanConf = {
 
.ssid = NULL,
 
.bssid = NULL,
 
.channel = 0,
 
.show_hidden = 1
 
};
 
ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 0));
 
return 0;
 
 
}
 
}
 
</source>
 
</source>
  
Using the Arduino libraries we can also make network scans. Here is an example:
+
Используя библиотеки Arduino, мы также можем осуществлять сетевое сканирование. Вот пример:
  
 
<source lang=c>
 
<source lang=c>
Строка 181: Строка 143:
 
printf("Found %d networks\n", count);
 
printf("Found %d networks\n", count);
 
for (uint8_t i=0; i<count; i++) {
 
for (uint8_t i=0; i<count; i++) {
String ssid;
+
  String ssid;
uint8_t encryptionType;
+
  uint8_t encryptionType;
int32_t RSSI;
+
  int32_t RSSI;
uint8_t *BSSID;
+
  uint8_t *BSSID;
int32_t channel;
+
  int32_t channel;
WiFi.getNetworkInfo(i, ssid, encryptionType, RSSI, BSSID, channel);
+
  WiFi.getNetworkInfo(i, ssid, encryptionType, RSSI, BSSID, channel);
printf("ssid=%s\n", ssid.c_str());
+
  printf("ssid=%s\n", ssid.c_str());
 
}
 
}
 
</source>
 
</source>
  
 
See also:
 
See also:
Handling WiFi events
+
* Handling WiFi events
esp_wifi_scan_start
+
* esp_wifi_scan_start
esp_wifi_scan_stop
+
* esp_wifi_scan_stop
esp_wifi_scan_get_ap_records
+
* esp_wifi_scan_get_ap_records
esp_wifi_scan_get_ap_num
+
* esp_wifi_scan_get_ap_num
  
 
===Обработчики событий WiFi===
 
===Обработчики событий WiFi===
Строка 205: Строка 167:
 
<source lang=c>
 
<source lang=c>
 
esp_err_t eventHandler(void *ctx, system_event_t *event) {
 
esp_err_t eventHandler(void *ctx, system_event_t *event) {
// здесь код обработчика события ...
+
  // здесь код обработчика события ...
return ESP_OK;
+
  return ESP_OK;
 
}
 
}
 
</source>
 
</source>
  
Как правило мы должны будем включить следующие инклюды:
+
Как правило мы должны включить следующие заголовки:
 
* #include <esp_event.h>
 
* #include <esp_event.h>
 
* #include <esp_event_loop.h>
 
* #include <esp_event_loop.h>
Строка 549: Строка 511:
 
До сих пор мы рассматривали ESP32 как клиента ​​WiFi для существующей точки доступа, но он также имеет возможность быть точкой доступа для других WiFi-устройств(клиентов), включая другие ESP32.
 
До сих пор мы рассматривали ESP32 как клиента ​​WiFi для существующей точки доступа, но он также имеет возможность быть точкой доступа для других WiFi-устройств(клиентов), включая другие ESP32.
 
Чтобы быть точкой доступа, нам нужно определить SSID, который позволяет другим устройствам увидеть нашу сеть. Этот SSID может быть помечен как скрытый, если мы не хотим чтобы его можно найти при сканировании. Кроме того, мы также должны указать режим аутентификации который будет использоваться, когда клиент захочет соединиться с нами.
 
Чтобы быть точкой доступа, нам нужно определить SSID, который позволяет другим устройствам увидеть нашу сеть. Этот SSID может быть помечен как скрытый, если мы не хотим чтобы его можно найти при сканировании. Кроме того, мы также должны указать режим аутентификации который будет использоваться, когда клиент захочет соединиться с нами.
Первой этапом для начала работы ESP32 в режиме точки доступа является установка соответствующего режима командой esp_wifi_set_mode(). Для этого необходио передать в качестве параметра код режима точки доступа или совмещенного режима точка доступа и клиента. Это будет либо:
+
Первой этапом для начала работы ESP32 в режиме точки доступа является установка соответствующего режима командой esp_wifi_set_mode(). Для этого необходимо передать в качестве параметра код режима точки доступа или совмещенного режима точка доступа и клиента. Это будет либо:
 
<source lang=c>
 
<source lang=c>
 
esp_wifi_set_mode (WIFI_MODE_AP);
 
esp_wifi_set_mode (WIFI_MODE_AP);
Строка 588: Строка 550:
 
</source>
 
</source>
  
With the structure populated, we call esp_wifi_set_config() … for example:
+
Когда структура заполнена, мы вызываем esp_wifi_set_config() … доя примера:
 +
<source lang=c>
 
esp_wifi_set_config(WIFI_IF_AP, &apConfig);
 
esp_wifi_set_config(WIFI_IF_AP, &apConfig);
Finally, we call esp_wifi_start().
+
</source>
Here is a snippet of code that can be used to setup and ESP32 as an access point:
+
 
When we become an access point, an ESP32 WiFi event is produced of type
+
Наконец, мы называем esp_wifi_start().
SYSTEM_EVENT_AP_START. Note that there is no payload data associated with this event.
+
 
Once the ESP32 starts listening for station connects by being an access point, we are
+
Вот фрагмент кода, который можно использовать для настройки, и ESP32 в качестве точки доступа:
going to want to validate that this works. You can use any device or system to scan and
+
<source lang=c>
connect. Personally, I use a Raspberry PI 3 for testing as it provides a nice Linux
+
#include "freertos/FreeRTOS.h"
environment and has a WiFi adapter build in. You can also choose to plug in a separate
+
#include "esp_wifi.h"
WiFi dongle into one of the extra USB ports. One of the first tools we want to run is
+
#include "esp_system.h"
called "iwlist" which will perform a scan for us:
+
#include "esp_event.h"
 +
#include "esp_event_loop.h"
 +
#include "nvs_flash.h"
 +
#include "tcpip_adapter.h"
 +
esp_err_t event_handler(void *ctx, system_event_t *event)
 +
{
 +
  //....
 +
  return ESP_OK;
 +
}
 +
int app_main(void)
 +
{
 +
  nvs_flash_init();
 +
  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_AP));
 +
  wifi_config_t sta_config = {
 +
      .ap = {
 +
        .ssid="test_ap",
 +
        .ssid_len=0,
 +
        .password="test_test", // 8 digit minimum
 +
        .channel=0,
 +
        .authmode=WIFI_AUTH_OPEN,
 +
        .ssid_hidden=0,
 +
        .max_connection=4,
 +
        .beacon_interval=100
 +
      }
 +
  }; 
 +
  ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &sta_config));
 +
  ESP_ERROR_CHECK(esp_wifi_start());
 +
  return 0;
 +
}
 +
</source>
 +
 
 +
Когда мы становимся точкой доступа, событие ESP32 WiFi создается из типа
 +
SYSTEM_EVENT_AP_START. Обратите внимание, что нет данных о полезной нагрузке, связанных с этим событием.
 +
 
 +
Как только ESP32 начнет прослушивать подключения к станции, будучи точкой доступа, мы захотим проверить, что это работает. Вы можете использовать любое устройство или систему для сканирования и подключения. Лично я использую Raspberry PI 3 для тестирования, поскольку он обеспечивает отличную среду Linux и имеет встроенный адаптер WiFi. Вы также можете подключить отдельный WiFi-ключ к одному из дополнительных USB-портов. Один из первых инструментов, которые мы хотим запустить, называется «iwlist», который будет выполнять сканирование:
 +
<source lang=bash>
 
$ sudo iwlist wlan1 scan
 
$ sudo iwlist wlan1 scan
In the results, we can look for our ESP32 … for example:
+
</source>
 +
 
 +
В результате мы можем искать наш ESP32 ... например:
 +
<source lang=bash>
 
Cell 02 - Address: 18:FE:34:6A:94:EF
 
Cell 02 - Address: 18:FE:34:6A:94:EF
ESSID:"ESP32"
+
          ESSID:"ESP32"
Protocol:IEEE 802.11bgn
+
          Protocol:IEEE 802.11bgn
Mode:Master
+
          Mode:Master
Frequency:2.412 GHz (Channel 1)
+
          Frequency:2.412 GHz (Channel 1)
Encryption key:off
+
          Encryption key:off
Bit Rates:150 Mb/s
+
          Bit Rates:150 Mb/s
Quality=100/100 Signal level=100/100
+
          Quality=100/100 Signal level=100/100
One of the other tools available on that environment is called "wpa_cli" which provides
+
</source>
a wealth of options for testing WiFi. The recipe I use is to connect to an access point
+
Другой доступный инструментом, доступный в этой среде, называется «wpa_cli», который предоставляет множество опций для тестирования WiFi. Способ, который я использую, заключается в подключении к точке доступа из командной строки:
from the command line is:
+
 
 +
<source lang=bash>
 
$ sudo wpa_cli
 
$ sudo wpa_cli
 
add_network
 
add_network
Строка 619: Строка 626:
 
enable_network <num>
 
enable_network <num>
 
status
 
status
You may have to run
+
</source>
 +
 
 +
Для подключения к точке доступа, вам придется выбрать
 +
<source lang=bash>
 
select_network <num>
 
select_network <num>
 
reconnect
 
reconnect
or
+
</source>
 +
или
 +
<source lang=bash>
 
reasociate
 
reasociate
to connect to the target and you can run
+
</source>
 +
для отключения от точки доступа используйте команду:
 +
<source lang=bash>
 
disconnect
 
disconnect
to disconnect from the access point.
+
</source>
ifname – show current interface
+
 
interface <name> - select current interface
+
ifname – покажет текущий интерфейс
To perform a scan run the command "scan". When complete, run "scan_results" to see
+
 
the list.
+
interface <name> - выберет текущий интерфейс
When a station connects, the ESP32 will raise the SYSTEM_EVENT_AP_STACONNECTED
+
 
event. When a station disconnects, we will see the SYSTEM_EVENT_AP_DISCONNECTED
+
Для выполнения сканирования выполните команду «scan». По завершении запустите «scan_results», чтобы просмотреть список.
event.
+
 
See also:
+
Когда станция подключается, ESP32 будет поднимать событие SYSTEM_EVENT_AP_STACONNECTED. Когда станция отключается, мы увидим событие SYSTEM_EVENT_AP_DISCONNECTED.
• man(8) wpa_cl i
+
 
When a remote station connects to the ESP32 as an access point, we will see a debug
+
Смотрите также:
message written to UART1 that may look similar to:
+
* Man (8) - wpa_cl i
 +
Когда удаленная станция подключается к ESP32 в качестве точки доступа, мы увидим отладочное сообщение, написанное в UART1, которое может выглядеть примерно так:
 +
 
 +
<source lang=bash>
 
station: f0:25:b7:ff:12:c5 join, AID = 1
 
station: f0:25:b7:ff:12:c5 join, AID = 1
This contains the MAC address of the new station joining the network. When the station
+
</source>
disconnects, we will see a corresponding debug log message that may be:
+
 
 +
Это содержит MAC-адрес нового клиента, соединяющей сеть. Когда клиент отключится, мы увидим соответствующее сообщение журнала отладки, которое может быть:
 +
<source lang=bash>
 
station: f0:25:b7:ff:12:c5 leave, AID = 1
 
station: f0:25:b7:ff:12:c5 leave, AID = 1
From within the ESP32, we can determine how many stations are currently connected
+
</source>
with a call to wifi_softap_get_station_num(). If we wish to find the details of those
+
Из ESP32 мы можем определить, сколько клиентов в настоящий момент к ней подключено вызовом wifi_softap_get_station_num (). Если нужно получить детали этих клиентов, мы можем вызвать wifi_softap_get_station_info (), которая вернет связанный список wifi_sta_list_t. Мы должны явно освободить хранилище, выделенное этим вызовом, выполнив wifi_softap_free_station_info ().
stations, we can call wifi_softap_get_station_info() which will return a linked list of
+
 
wifi_sta_list_t. We have to explicitly release the storage allocated by this call with an
+
Ниже приведен пример фрагмента кода, в котором перечислены детали подключенных станций:
invocation of wifi_softap_free_station_info().
+
<source lang=c>
Here is an example of a snippet of code that lists the details of the connected stations:
 
 
uint8 stationCount = wifi_softap_get_station_num();
 
uint8 stationCount = wifi_softap_get_station_num();
 
os_printf("stationCount = %d\n", stationCount);
 
os_printf("stationCount = %d\n", stationCount);
 
wifi_sta_list_t *stationInfo = wifi_softap_get_station_info();
 
wifi_sta_list_t *stationInfo = wifi_softap_get_station_info();
 
if (stationInfo != NULL) {
 
if (stationInfo != NULL) {
while (stationInfo != NULL) {
+
  while (stationInfo != NULL) {
os_printf("Station IP: %d.%d.%d.%d\n", IP2STR(&(stationInfo->ip)));
+
      os_printf("Station IP: %d.%d.%d.%d\n", IP2STR(&(stationInfo->ip)));
stationInfo = STAILQ_NEXT(stationInfo, next);
+
      stationInfo = STAILQ_NEXT(stationInfo, next);
 +
  }
 +
  wifi_softap_free_station_info();
 
}
 
}
wifi_softap_free_station_info();
+
</source>
}
+
Когда ESP32 действует как точка доступа, это позволяет другим устройствам подключаться к нему и формировать соединение WiFi. Однако представляется, что два устройства, подключенные к одному ESP32, действующему как точка доступа, не могут напрямую взаимодействовать друг с другом.
When an ESP32 acts as an access point, this allows other devices to connect to it and
+
Например, представьте, что два устройства подключаются к ESP32 в качестве точки доступа. Им могут быть выделены IP-адреса 192.168.4.2 и 192.168.4.3. Мы можем предположить, что 192.168.4.2 может выполнять проверку 192.168.4.3 и наоборот, но это запрещено. Похоже, что разрешено только прямое сетевое подключение между вновь подключенными клиентами и точкой доступа (ESP32).
form a WiFi connection. However, it appears that two devices connected to the same
+
 
ESP32 acting as an access point can not directly communicate between each other.
+
Это, по-видимому, ограничивает применимость ESP32 в качестве точки доступа. Основная цель ESP32 в качестве точки доступа - разрешить мобильным устройствам (например, вашему телефону) подключаться к ESP32 и вести беседу с приложением, которое работает на нем.
For example, imagine two devices connecting to an ESP32 as an access point. They
+
 
may be allocated the IP addresses 192.168.4.2 and 192.168.4.3. We might imagine
 
that 192.168.4.2 could ping 192.168.4.3 and visa versa but that is not allowed. It
 
appears that they only direct network connection permitted is between the newly
 
connected stations and the access point (the ESP32) itself.
 
This seems to limit the applicability of the ESP32 as an access point. The primary
 
intent of the ESP32 as an access point is to allow mobile devices (eg. your phone) to
 
connect to the ESP32 and have a conversation with an application that runs upon it.
 
 
See also:
 
See also:
esp_wifi_set_config
+
* esp_wifi_set_config
esp_wifi_set_mode
+
* esp_wifi_set_mode
 +
 
 +
=== Работа с подключенными клиентами===
 +
Когда наш ESP32 является точкой доступа, мы говорим, что хотим разрешить клиенту подключаться к нему. Это приводит к необходимости управления этими клиентами. Обычными вещами, которые мы хотели бы сделать, являются:
 +
* Определите, когда подключается новый клиент
 +
* Определите, когда уходит ранее подключенный клиент
 +
* Список подключенных в данный момент клиентов
 +
* Отключите одну или несколько подключенных в настоящее время клиентов
 +
 
 +
Мы можем зарегистрировать обработчик событий для обнаружения новых соединений клиентов и существующих отключений клиентов. Обработчик события получит SYSTEM_EVENT_AP_STACONNECTED, когда клиент подключится, и SYSTEM_EVENT_AP_STADISCONNECTED, что клиент отключится.
 +
 
 +
Мы можем получить список подключенных в данный момент клиентов, используя функцию esp_wifi_get_station_list(). Хранилище для этого списка выделено для нас, и мы должны указать, что мы больше не нуждаемся в нем, вызывая esp_wifi_free_station_list() по завершении.
 +
 
 +
Если по какой-то причине логика в нашей среде хочет принудительно отключить текущую подключенную станцию, мы можем использовать вызов esp_wifi_kick_station().
  
===Working with connected stations===
 
When our ESP32 is being an access point, we are saying that we wish to allow stations
 
to connect to it. This brings in the story of managing those stations. Common things
 
we might want to do are:
 
• Determine when a new station connects
 
• Determine when a previously connected station leaves
 
• List the currently connected stations
 
• Disconnect one or more currently connected stations
 
We can register an event handler for detecting new station connects and existing station
 
disconnects. The event handler will receive SYSTEM_EVENT_AP_STACONNECTED when a
 
station connects and SYSTEM_EVENT_AP_STADISCONNECTED what a station leaves.
 
We can get the list of currently connected stations using the
 
esp_wifi_get_station_list() function. This returns a linked list of stations. The
 
storage for this list is allocated for us and we should indicate that we are no longer in
 
need of it by calling esp_wifi_free_station_list() when done.
 
If for some reason the logic in our environment wants to forcibly disconnect a currently
 
connected station, we can use the esp_wifi_kick_station() call.
 
 
See also:
 
See also:
Handling WiFi events
+
* Handling WiFi events
esp_wifi_free_station_list
+
* esp_wifi_free_station_list
esp_wifi_get_station_list
+
* esp_wifi_get_station_list
esp_wifi_kick_station
+
* esp_wifi_kick_station
  
 
===WiFi at boot time===
 
===WiFi at boot time===
Строка 706: Строка 715:
 
• esp_wifi_set_storage
 
• esp_wifi_set_storage
  
===The DHCP client===
+
===DHCP клиент===
When the ESP32 connects to an access point as a station, it also runs a DHCP client to
+
Когда ESP32 подключается к точке доступа в качестве станции, он также запускает DHCP-клиент для подключения к серверу DHCP, который он предполагает, также доступен в точке доступа. Оттуда станция получает свой IP-адрес, адрес шлюза и сетевую маску. Однако есть моменты, когда мы хотим предоставить наши собственные значения для этих данных. Мы можем сделать это, вызвав tcpip_adapter_set_ip_info () во время установки. Это выглядит следующим образом:
connect to the DHCP server that it assumes is also available at the access point. From
+
<source lang=c>
there, the station is supplied its IP address, gateway address and netmask. There are
 
times however when we want to supply our own values for this data. We can do this by
 
calling tcpip_adapter_set_ip_info() during setup. The recipe is as follows:
 
 
tcpip_adapter_init();
 
tcpip_adapter_init();
 
tcpip_adapter_dhcpc_stop();
 
tcpip_adapter_dhcpc_stop();
Строка 720: Строка 726:
 
esp_wifi_start();
 
esp_wifi_start();
 
esp_wifi_config();
 
esp_wifi_config();
 +
</source>
 
(Note that the parameters are omitted in the above).
 
(Note that the parameters are omitted in the above).
The setup for calling tcpip_adapter_set_ip_info() can be as follows:
+
 
 +
Настройка для вызова tcpip_adapter_set_ip_info () может быть следующей:
 +
<source lang=c>
 
tcpip_adapter_ip_info_t ipInfo;
 
tcpip_adapter_ip_info_t ipInfo;
 
IP4_ADDR(&ipInfo.ip, 192,168,1,99);
 
IP4_ADDR(&ipInfo.ip, 192,168,1,99);
Строка 727: Строка 736:
 
IP4_ADDR(&ipInfo.netmask, 255,255,255,0);
 
IP4_ADDR(&ipInfo.netmask, 255,255,255,0);
 
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
 
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
Alternative, using strings we have:
+
</source>
 +
Альтернатива, используя строки, мы имеем:
 +
<source lang=c>
 
tcpip_adapter_ip_info_t ipInfo;
 
tcpip_adapter_ip_info_t ipInfo;
 
inet_pton(AF_INET, "192.168.1.99", &ipInfo.ip);
 
inet_pton(AF_INET, "192.168.1.99", &ipInfo.ip);
Строка 733: Строка 744:
 
inet_pton(AF_INET, "255.255.255.0", &ipInfo.netmask);
 
inet_pton(AF_INET, "255.255.255.0", &ipInfo.netmask);
 
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
 
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
 +
</source>
 +
 
See also:
 
See also:
tcpip_adapter_set_ip_info
+
* tcpip_adapter_set_ip_info
tcpip_adapter_dhcpc_start
+
* tcpip_adapter_dhcpc_start
tcpip_adapter_dhcpc_stop
+
* tcpip_adapter_dhcpc_stop
tcpip_adapter_dhcpc_get_status
+
* tcpip_adapter_dhcpc_get_status
tcpip_adapter_dhcpc_option
+
* tcpip_adapter_dhcpc_option
inet_pton
+
* inet_pton
===The DHCP server===
+
 
When the ESP32 is performing the role of an access point, it is likely that you will want it
+
===DHCP сервер===
to also behave as a DHCP server so that connecting stations will be able to be
+
Когда ESP32 выполняет роль точки доступа, вполне вероятно, что вы захотите, чтобы он также вел себя как DHCP-сервер, чтобы подключенным клиентам мог быть автоматически назначен IP-адрес и переданы их маски подсети и шлюзы.
automatically assigned IP addresses and learn their subnet masks and gateways.
+
 
The DHCP server can be started and stopped within the device using the APIs called
+
DHCP-сервер можно запустить и остановить в устройстве с помощью API, называемых wifi_softap_dhcps_start () и wifi_softap_dhcps_stop (). Текущее состояние (запущен или остановлено) DHCP-сервера можно найти с помощью вызова wifi_softap_dhcps_status().
wifi_softap_dhcps_start() and wifi_softap_dhcps_stop(). The current status
+
 
(started or stopped) of the DHCP server can be found with a call to
+
Диапазон IP-адресов по умолчанию, предлагаемый сервером DHCP, составляет 192.168.4.1 вверх.
wifi_softap_dhcps_status().
+
 
The default range of IP addresses offered by the DHCP server is 192.168.4.1 upwards.
+
Первый адрес присваивается самому ESP32. Важно понимать, что этот диапазон адресов не является тем же самым диапазоном адресов, что и ваша ЛВС, где вы можете быть
The first address becomes assigned to the ESP8266 itself. It is important to realize that
+
за работой. ESP32 сформировал собственное сетевое адресное пространство, и хотя они могут отображаться с одинаковыми номерами (192.168.x.x), они являются изолированными и независимыми сетями. Если вы запустите точку доступа на ESP32 и подключитесь к ней со своего телефона, не удивляйтесь, когда вы пытаетесь выполнить ping с вашего компьютера, подключенного к Интернету, и не получите ответа.
this address range is not the same address range as your LAN where you may be
+
 
working. The ESP8266 has formed its own network address space and even though
 
they may appear with the same sorts of numbers (192.168.x.x) they are isolated and
 
independent networks. If you start an access point on the ESP8266 and connect to it
 
from your phone, don't be surprised when you try and ping it from your Internet
 
connected PC and don't get a response.
 
 
See also:
 
See also:
Error: Reference source not found
+
* Error: Reference source not found
===Current IP Address, netmask and gateway===
+
 
Should we need it, we can query the environment for the current IP address, netmask
+
===Текущий IP адрес, маска и шлюз===
and gateway. The values of these are commonly set for us by a DHCP server when we
+
Если нам это нужно, мы можем запросить среду для текущего IP-адреса, сетевой маски и шлюза. Значения этих параметров обычно устанавливаются для нас сервером DHCP, когда мы
connect to an access point. The function called tcpip_adapter_get_ip_info() returns
+
подключитесь к точке доступа. Функция tcpip_adapter_get_ip_info () возвращает наше текущее значение. Поскольку ESP32 может иметь два IP-интерфейса (один для точки доступа
our current value. Since the ESP32 can have two IP interfaces (one for an access point
+
и один для станции), мы предоставляем интерфейс, который мы хотим получить.
and one for a station), we supply which interface we wish to retrieve.
+
 
When we connect to an access point and have chosen to use DHCP, when we are
+
Когда мы подключаемся к точке доступа и выбираем использовать DHCP, когда нам присваивается IP-адрес, генерируется событие, которое может использоваться как указание на то, что у нас теперь есть действительный IP-адрес.
allocated an IP address, an event is generated that can be used as an indication that
+
 
we now have a valid IP address.
 
 
See also:
 
See also:
Handling WiFi events
+
* Handling WiFi events
Error: Reference source not found
+
* Error: Reference source not found
tcpip_adapter_get_ip_info
+
* tcpip_adapter_get_ip_info
 +
 
 
===WiFi Protected Setup – WPS===
 
===WiFi Protected Setup – WPS===
The ESP8266 supports WiFi Protected Setup in station mode. This means that if the
+
ESP32 поддерживает функцию WiFi Protected Setup в режиме станции. Это означает, что если точка доступа поддерживает его, ESP32 может подключиться к точке доступа без представления пароля. В настоящее время реализуется только «кнопочный режим» соединения. Используя этот механизм, физическая кнопка нажата на точку доступа, и в течение двух минут любая станция в диапазоне может присоединиться к сети с использованием протоколов WPS. Примером использования может быть нажата кнопка WPS точки доступа, а затем устройство ESP32, вызывающее wifi_wps_enable (), а затем wifi_wps_start (). Затем ESP32 подключился к сети.
access point supports it, the ESP8266 can connect to the access point without
+
 
presenting a password. Currently only the "push button mode" of connection is
 
implemented. Using this mechanism, a physical button is pressed on the access point
 
and, for a period of two minutes, any station in range can join the network using the
 
WPS protocols. An example of use would be the access point WPS button being
 
pressed and then the ESP8266 device calling wifi_wps_enable() and then
 
wifi_wps_start(). The ESP8266 would then connect to the network.
 
 
See also:
 
See also:
wifi_wps_enable
+
* wifi_wps_enable
wifi_wps_start
+
* wifi_wps_start
wifi_set_wps_cb
+
* wifi_set_wps_cb
Simple Questions: What is WPS (WiFi Protected Setup)
+
* Simple Questions: What is WPS (WiFi Protected Setup)
Wikipedia: WiFi Protected Setup
+
* Wikipedia: WiFi Protected Setup
 +
 
 
===Алгоритм инициализации WiFi===
 
===Алгоритм инициализации WiFi===
 
Представьте, что мы создали проект с использованием ESP32, который хочет подключиться к сети. Чтобы это произошло, мы хотим, чтобы ESP32 подключался к существующей точке доступа. Это работает, потому что ESP32 может быть Wi-Fi-клиентом. Для того, чтобы ESP32 соединился с точкой доступа, он должен знать два важных элемента. Он должен знать, к какой сети присоединиться (SSID), и ему нужно будет знать пароль для подключения к этой сети, поскольку большинство сетей требуют аутентификации. И есть головоломка. Если ESP32 перенесен в физически новую среду, как он «узнает», к какой сети подключиться и какой пароль использовать? Мы должны предположить, что ESP32 не имеет прикрепленного к нему экрана. Если бы это было так, мы могли бы запросить у пользователя информацию. Одним из решений является то, что ESP32 первоначально «будет» точкой доступа. Если бы это была точка доступа, мы могли бы использовать наш телефон для связи с ним, спросить, какие WiFi-сети он видит, предоставить пароль для сети и разрешить ему подключаться.  
 
Представьте, что мы создали проект с использованием ESP32, который хочет подключиться к сети. Чтобы это произошло, мы хотим, чтобы ESP32 подключался к существующей точке доступа. Это работает, потому что ESP32 может быть Wi-Fi-клиентом. Для того, чтобы ESP32 соединился с точкой доступа, он должен знать два важных элемента. Он должен знать, к какой сети присоединиться (SSID), и ему нужно будет знать пароль для подключения к этой сети, поскольку большинство сетей требуют аутентификации. И есть головоломка. Если ESP32 перенесен в физически новую среду, как он «узнает», к какой сети подключиться и какой пароль использовать? Мы должны предположить, что ESP32 не имеет прикрепленного к нему экрана. Если бы это было так, мы могли бы запросить у пользователя информацию. Одним из решений является то, что ESP32 первоначально «будет» точкой доступа. Если бы это была точка доступа, мы могли бы использовать наш телефон для связи с ним, спросить, какие WiFi-сети он видит, предоставить пароль для сети и разрешить ему подключаться.  

Текущая версия на 11:57, 8 июля 2017

WiFi теория

При работе с ориентированным на WiFi устройством важно, чтобы у нас было хотя бы некоторое понимание концепций, связанных с WiFi. На высоком уровне WiFi - это способность участвовать в соединениях TCP/IP по линии беспроводной связи. Wi-Fi - это, в частности, набор протоколов, описанных в архитектуре беспроводной локальной сети IEEE 802.11.

В этой истории устройство, называемое точкой беспроводного доступа (точка доступа или AP), выступает в качестве центра всех коммуникаций. Обычно он подключается (или действует как) как маршрутизатор TCP/IP к остальной части сети TCP/IP. Например, в вашем доме вы, вероятно, будете иметь точку доступа WiFi, подключенную к вашему модему (кабель или DSL). Затем к точке доступа формируются соединения WiFi (через устройства, называемые клиентами), а трафик TCP/IP - через точку доступа в Интернет.

Устройства, которые подключаются к точкам доступа, называются «клиентами»:

Устройство ESP32 может играть роль точки доступа, клиента или обоих одновременно.

Чаще всего точка доступа также имеет сетевое подключение к Интернету и выступает в качестве моста между беспроводной сетью и более широкой сетью TCP/IP, являющейся Интернетом.

Набор клиентов, которые хотят общаться друг с другом, называется базовым набором услуг (BSS). Общая конфигурация - это то, что известно как BSS инфраструктуры. В этом режиме все входящие и исходящие сообщения от отдельной станции маршрутизируются через точку доступа.

Клиент должен ассоциироваться с точкой доступа для участия в истории. Клиент может быть связан только с одной точкой доступа в любой момент времени. Каждый участник сети имеет уникальный идентификатор, называемый MAC-адресом. Это 48-битное значение.

Когда у нас есть несколько точек доступа в беспроводном диапазоне, станция должна знать, с какой из них можно подключиться. Каждая точка доступа имеет сетевой идентификатор, называемый BSSID (или чаще всего SSID). SSID - это идентификатор набора услуг. Это 32-значное значение, которое представляет собой цель пакетов информации, отправляемых по сети.

See also: • Wikipedia – Wireless access point • Wikipedia – IEEE 802.11 • Wikipedia – WiFi Protected Access • Wikipedia – IEEE 802.11i-2004

Инициализация WiFi окружения

WiFi является лишь частью возможностей ESP32. Может быть много случаев, когда WiFi не требуется. Инициализация WiFi выполняется разработчиком приложения путем вызова метода esp_wifi_init().

Рекомендуется провести инициализацию следующим образом:

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

See also: • esp_wifi_init

Установка режима работы

ESP32 может быть либо клиентом, либо точкой доступа для других устройств, либо и тем, и другим. Помните, что когда ESP32 является станцией, он может подключаться к удаленной точке доступа (ваш 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.

Данные возвращаются нам при вызове esp_wifi_scan_get_ap_records(), который также освобождает внутренне выделенное хранилище. Таким образом, это следует рассматривать как деструктивное чтение.

Запись сканирования содержится в экземпляре структуры 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 – No security.
  • WIFI_AUTH_WEP – WEP security.
  • WIFI_AUTH_WPA_PSK – WPA security.
  • WIFI_AUTH_WPA2_PSK – WPA2 security.
  • WIFI_AUTH_WPA_WPA2_PSK – WPA or WPA2 security.

После того, как вы отправите запрос на выполнение сканирования, узнать о его завершении можно по событию SYSTEM_EVENT_SCAN_DONE. Данные события содержат количество найденных точек доступа, и могут быть получены вызовом esp_wifi_scan_get_ap_num().

Если мы хотим отменить сканирование до его завершения самостоятельно, мы можем вызвать esp_wifi_scan_stop().

Вот полное примерное приложение, иллюстрирующее выполнение проверки WiFi. Большая часть работы выполняется в обработчике событий. Когда мы обнаруживаем событие завершения сканирования, мы получаем найденные точки доступа и записываем их данные.

#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
esp_err_t event_handler(void *ctx, system_event_t *event)
{
   if (event->event_id == SYSTEM_EVENT_SCAN_DONE) {
      printf("Number of access points found: %d\n",
      event->event_info.scan_done.number);
      uint16_t apCount = event->event_info.scan_done.number;
      if (apCount == 0) {
         return ESP_OK;
      }
      wifi_ap_record_t *list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
      ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, list));
      int i;
      for (i=0; i<apCount; i++) {
         char *authmode;
         switch(list[i].authmode) {
            case WIFI_AUTH_OPEN:
               authmode = "WIFI_AUTH_OPEN";
               break;
            case WIFI_AUTH_WEP:
               authmode = "WIFI_AUTH_WEP";
               break;
            case WIFI_AUTH_WPA_PSK:
               authmode = "WIFI_AUTH_WPA_PSK";
               break;
            case WIFI_AUTH_WPA2_PSK:
               authmode = "WIFI_AUTH_WPA2_PSK";
               break;
            case WIFI_AUTH_WPA_WPA2_PSK:
               authmode = "WIFI_AUTH_WPA_WPA2_PSK";
               break;
            default:
               authmode = "Unknown";
               break;
         }
         printf("ssid=%s, rssi=%d, authmode=%s\n",
         list[i].ssid, list[i].rssi, authmode);
      }
      free(list);
   }
   return ESP_OK;
}

int app_main(void){
   nvs_flash_init();
   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());
   // Let us test a WiFi scan ...
   wifi_scan_config_t scanConf = {
      .ssid = NULL,
      .bssid = NULL,
      .channel = 0,
      .show_hidden = 1
   };
   ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 0));
   return 0;
}

Используя библиотеки Arduino, мы также можем осуществлять сетевое сканирование. Вот пример:

int8_t count = WiFi.scanNetworks();
printf("Found %d networks\n", count);
for (uint8_t i=0; i<count; i++) {
   String ssid;
   uint8_t encryptionType;
   int32_t RSSI;
   uint8_t *BSSID;
   int32_t channel;
   WiFi.getNetworkInfo(i, ssid, encryptionType, RSSI, BSSID, channel);
   printf("ssid=%s\n", ssid.c_str());
}

See also:

  • Handling WiFi events
  • esp_wifi_scan_start
  • esp_wifi_scan_stop
  • esp_wifi_scan_get_ap_records
  • esp_wifi_scan_get_ap_num

Обработчики событий WiFi

Во время работы в качестве устройства WiFi, могут возникнуть события представляющие интерес для приложения. Поскольку мы не знаем когда произойдет то или иное событие, мы не можем заблокировать приложение в их ожидании. Вместо этого мы должны определить функцию обратного вызова, которая будет вызвана если событие произойдет. Функция esp_event_loop_init() регистрирует функцию обратного вызова.

Пример функции обратного вызова:

esp_err_t eventHandler(void *ctx, system_event_t *event) {
   // здесь код обработчика события ...
   return ESP_OK;
}

Как правило мы должны включить следующие заголовки:

  • #include <esp_event.h>
  • #include <esp_event_loop.h>
  • #include <esp_wifi.h>
  • #include <esp_err.h>

Пример регистрации функции обратного вызова:

esp_event_loop_init(eventHandler, NULL);

Если в последствии предполагается изменение обработчика обратного вызова можно использовать:

esp_event_loop_set_cb(eventHandler, NULL);

В функцию обратного вызова передается параметр с деталями события. Тип данных этого параметра - «system_event_t», который содержит: System_event_id_t event_id и System_event_info_t event_info

Мы должны включить «esp_event.h», чтобы получить доступ к этим данным.

Теперь мы рассмотрим два свойства, переданные обработчику событий в system_event_t - этими свойствами являются «event_id» и «event_info». Event_id описывает, какое событие было обнаружено, а event_info содержит детали события, основанные на типе, указанном в event_id.

  • event_id – перечисление содержащее тип события, принимает следующие значения:
    • SYSTEM_EVENT_WIFI_READY – ESP32 WiFi is ready.
    • SYSTEM_EVENT_SCAN_DONE – Сканирование точек доступа завершено, список доступен.
    • SYSTEM_EVENT_STA_START – Started being a station.
    • SYSTEM_EVENT_STA_STOP – Stopped being a station.
    • SYSTEM_EVENT_STA_CONNECTED – Connected to an access point as a station. The connected data field is valid to be accessed.
    • SYSTEM_EVENT_STA_DISCONNECTED – Disconnected from access point while being a station. The disconnected data field is valid to be accessed.
    • SYSTEM_EVENT_STA_AUTHMODE_CHANGE – Authentication mode has changed. The auth_change data field is valid to be accessed.
    • SYSTEM_EVENT_STA_GOT_IP – Got an assigned IP address from the access point that we connected to while being a station. The got_ip data field is valid to be accessed.
    • SYSTEM_EVENT_AP_START – Started being an access point.
    • SYSTEM_EVENT_AP_STOP – Stopped being an access point.
    • SYSTEM_EVENT_AP_STACONNECTED – A station connected to us while we are being an access point. The sta_connected data field is valid to be accessed.
    • SYSTEM_EVENT_AP_STADISCONNECTED – A station disconnected from us while we are being an access point. The sta_disconnected data field is valid to be accessed.
    • SYSTEM_EVENT_AP_PROBEREQRECVED – Received a probe request while we are being an access point. The ap_probereqrecved data field is valid to be accessed.
  • event_info – This is a C language union of distinct data types that are keyed off the event_id. The different structures contained within are:
Structure Field Event
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 sta_disconnected SYSTEM_EVENT_AP_STADISCONNECTED
system_event_ap_probe_req_rx_t ap_probereqrecved SYSTEM_EVENT_AP_PROBEREQRECVED

These data structures contain information pertinent to the event type received.

system_event_sta_connected_t

This data type is associated with the SYSTEM_EVENT_STA_CONNECT event.

  • uint8_t ssid[32]
  • uint8_t ssid_len
  • uint8_t bssid[6]
  • uint8_t channel
  • wifi_auth_mode_t authmode

The ssid is the WiFi network name to which we connected. The ssid_len is the number of bytes in the ssid field that contain the name. The bssid is the MAC address of the access point. The channel is the wireless channel used for the connection. The authmode is the security authentication mode used during the connection.

system_event_sta_disconnected_t

This data type is associated with the SYSTEM_EVENT_STA_DISCONNECTED event.

  • uint8_t ssid[32]
  • uint8_t ssid_len
  • uint8_t bssid[6]
  • uint8_t reason

The reason code is an indication of why we disconnected. Symbolics are defined for each of the numeric reason codes to allow us to write more elegant and comprehensible applications should we need to consider a reason code.:

  • 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_INVALID – 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_BEACON_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

This data type is associated with the SYSTEM_EVENT_SCAN_DONE event.

  • uint32_t status
  • uint8_t number
  • uint8_t scan_id

See also:

  • Scanning for access points
  • esp_wifi_scan_get_ap_records

system_event_authmode_change_t

This data type is associated with the SYSTEM_EVENT_STA_AUTHMODE_CHANGE event.

  • wifi_auth_mode_t old_mode
  • wifi_auth_mode_t new_mode

system_event_sta_got_ip_t

This data type is associated with the SYSTEM_EVENT_STA_GOT_IP event.

  • tcpip_adapter_ip_info_t ip_info

The ip_info element is an instance of a tcpip_adapter_ip_info_t which contains three fields:

  • ip -The IP address.
  • netmask – The network mask.
  • gw – The gateway for communications.

All three of these fields are of ip4_addr_t which is a 32bit representation of an IP address. During development, you might want to consider logging the IP address of the device. You can do this using: ESP_LOGD(tag, "Got an IP: " IPSTR, IP2STR(&event->event_info.got_ip.ip_info.ip));

system_event_ap_staconnected_t

This data type is associated with the SYSTEM_EVENT_AP_STACONNECTED event.

  • uint8_t mac[6]
  • uint8_t aid

system_event_ap_stadisconnected_t

This data type is associated with the SYSTEM_EVENT_AP_STADISCCONNECTED event.

  • uint8_t mac[6]
  • uint8_t aid

system_event_ap_probe_req_rx_t

This data type is associated with the SYSTEM_EVENT_AP_PROBREQRECVED event.

  • int rssi
  • uint8_t mac[6]

If we enable the correct logging levels, we can see the events arrive and their content. For example:

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

and

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

Настройки WiFi клиента

ESP32 в режиме WiFi клиента может быть подключена только к одной точке доступа. Парамерты точки доступа к которой мы хотим подключиться задаются в структуре wifi_sta_config_t. wifi_sta_config_t состоит из:

  • char ssid[32] - ssid точки доступа к которой хотим подключиться
  • char password[64] - пароль к точке доступа
  • bool bssid_set
  • uint8_t bssid[6]

Пример инициализации структуры wifi_config_t:

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);

Предварительно установив режим WiFi с помощью метода esp_wifi_set_mode():

esp_wifi_set_mode(WIFI_MODE_STA)

или

esp_wifi_set_mode(WIFI_MODE_APSTA)

See also: • esp_wifi_set_mode • esp_wifi_set_config

Запуск модуля WiFi

Поскольку Wi-Fi утверждает, что он должен пройти, может быть задан вопрос: «Когда Wi-Fi готов к использованию?». Если мы предположим, что ESP32 загружается с холода, есть вероятность, что мы хотим сказать, что это клиент или точка доступа, и задать её параметры. Учитывая, что это последовательность шагов, мы фактически не хотим, чтобы ESP32 выполнял эти задачи до тех пор, пока мы не выполнили всю нашу настройку. Например, если мы загружаем ESP32 и запрашиваем его как точку доступа, если он сразу стал точкой доступа, он может еще не знать параметров точки доступа, которая должна быть или, что еще хуже, может временно проявляться как неправильная точка доступа. Таким образом, есть окончательная команда, которую мы должны изучить, которая является инструкцией для подсистемы WiFi, чтобы начать работать. Это команда esp_wifi_start (). Все команды которые мы делаем до неё, это настройка среды. Только при вызове esp_wifi_start () подсистема WiFi начинает выполнять какую-либо реальную работу от нашего имени. Если наш режим - это точка доступа, вызов этой функции включает точку доступа. Если наш режим является режимом клиента, начинается подключение к точке доступа. Существует соответствующая команда, называемая esp_wifi_stop (), которая останавливает подсистему WiFi.

Подключение к точке доступа в режиме клиента

После передачи параметров подключения к WiFi в режиме клиента, которая включает SSID и пароль, мы готовы выполнить подключение к точке доступа. Функция esp_wifi_connect() установит соединение. Процедура установки соединения происходит не мнгновенно. Спустя некоторое время мы фактически подключимся - произойдет два события. Первое - SYSTEM_EVENT_STA_CONNECTED, указывающий, что у нас есть подключение к точке доступа. Второе событие - SYSTEM_EVENT_STA_GOT_IP, которое Указывает, что DHCP-сервером был назначен IP-адрес. Только после этих событий мы можем передавать / принимать данные. Если мы используем статический IP-адреса для нашего устройства, то мы увидим только связанное событие. Если мы отключимся от точки доступа, мы увидим событие SYSTEM_EVENT_STA_DISCONNECTED. Для отключения от ранее подключенной точки доступа, нужно вызвать esp_wifi_disconnect().

Существует еще один вариант подключения к точкам доступа - автоматическое подключение. Существует булев флаг, который хранится во флеше, который указывает, следует ли ESP32 пытаться автоматически подключиться к последней используемой точке доступа. Если установлено значение true, то после запуска устройства и без кодирования любых вызовов API, ESP32 попытается подключиться к последней используемой точке доступа. Этот вариант я предпочитаю не использовать, так как хочу сам контролировать работу устройства. Мы можем включить или отключить функцию автоматического подключения, выполнив вызов esp_wifi_set_auto_connect (). Ниже приведен полный пример, иллюстрирующий все шаги, необходимые для подключения к точке доступа с информированнием, когда мы готовы к работе:

#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "tcpip_adapter.h"
esp_err_t event_handler(void *ctx, system_event_t *event)
{
   if (event->event_id == SYSTEM_EVENT_STA_GOT_IP) {
      printf("Our IP address is " IPSTR "\n",
      IP2STR(&event->event_info.got_ip.ip_info.ip));
      printf("We have now connected to a station and can do things...\n")
   }
   return ESP_OK;
}
int app_main(void)
{
   nvs_flash_init();
   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));
   wifi_config_t sta_config = {
      .sta = {
         .ssid = "RASPI3",
         .password = "password",
         .bssid_set = 0
      }
   };   
   ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &sta_config));
   ESP_ERROR_CHECK(esp_wifi_start());
   ESP_ERROR_CHECK(esp_wifi_connect());
   return 0;
}

Когда мы подключаемся к точке доступа, наше устройство является клиентом. Подключение к точке доступа автоматически не означает, что теперь у нас есть IP-адрес. Мы все еще должны запросить выделенный IP-адрес с сервера DHCP. Это может занять несколько секунд. В некоторых случаях мы можем запрашиватьопределенный IP-адрес адрес. Это приводит к значительно более быстрому времени соединения. Если мы укажем IP адрес, то необходмо также указать информацию о DNS, если нам нужно подключиться к DNS-серверам. Пример, который выделяет нам определенный IP-адрес:

#include <lwip/sockets.h>
// The IP address that we want our device to have.
#define DEVICE_IP "192.168.1.99"
// The Gateway address where we wish to send packets.
// This will commonly be our access point.
#define DEVICE_GW "192.168.1.1"
// The netmask specification.
#define DEVICE_NETMASK "255.255.255.0"
// The identity of the access point to which we wish to connect.
#define AP_TARGET_SSID "RASPI3"
// The password we need to supply to the access point for authorization.
#define AP_TARGET_PASSWORD "password"
esp_err_t wifiEventHandler(void *ctx, system_event_t *event)
{
   return ESP_OK;
}
// Пример кода здесь ...

nvs_flash_init();
tcpip_adapter_init();
tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); // Don't run a DHCP client
tcpip_adapter_ip_info_t ipInfo;
inet_pton(AF_INET, DEVICE_IP, &ipInfo.ip);
inet_pton(AF_INET, DEVICE_GW, &ipInfo.gw);
inet_pton(AF_INET, DEVICE_NETMASK, &ipInfo.netmask);
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
ESP_ERROR_CHECK(esp_event_loop_init(wifiEventHandler, 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));
wifi_config_t sta_config = {
   .sta = {
      .ssid = AP_TARGET_SSID,
      .password = AP_TARGET_PASSWORD,
      .bssid_set = 0
   }
};
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &sta_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_wifi_connect());

See also: • Handling WiFi events • esp_wifi_connect • esp_wifi_disconnect

Запуск в режиме точки доступа

До сих пор мы рассматривали ESP32 как клиента ​​WiFi для существующей точки доступа, но он также имеет возможность быть точкой доступа для других WiFi-устройств(клиентов), включая другие ESP32. Чтобы быть точкой доступа, нам нужно определить SSID, который позволяет другим устройствам увидеть нашу сеть. Этот SSID может быть помечен как скрытый, если мы не хотим чтобы его можно найти при сканировании. Кроме того, мы также должны указать режим аутентификации который будет использоваться, когда клиент захочет соединиться с нами. Первой этапом для начала работы ESP32 в режиме точки доступа является установка соответствующего режима командой esp_wifi_set_mode(). Для этого необходимо передать в качестве параметра код режима точки доступа или совмещенного режима точка доступа и клиента. Это будет либо:

esp_wifi_set_mode (WIFI_MODE_AP);

или

esp_wifi_set_mode (WIFI_MODE_APSTA);

Затем нам нужно предоставить информацию о конфигурации. Мы делаем это, заполняя экземпляр wifi_ap_config_t. wifi_ap_config_t содержит:

  • ssid – The WiFi ssid name upon which we will listen for connecting stations.
  • ssid_len – The length in bytes of the ssid if not NULL terminated.
  • password – The password used for station authentication.
  • channel – The channel we will use for networking.
  • authmode – How we wish stations to authenticate (if at all). The choices are
    • open
    • wep
    • wpa
    • wpa2
    • wpa_wpa2
  • ssid_hidden – Should we broadcast our ssid.
  • max_connection – The number of concurrent stations. The default and maximum

is 4.

  • beacon_interval – Unknown. 100.

Пример структуры инициализации:

wifi_config_t apConfig = {
   .ap = {
      .ssid="<access point name>",
      .ssid_len=0,
      .password="<password>",
      .channel=0,
      .authmode=WIFI_AUTH_OPEN,
      .ssid_hidden=0,
      .max_connection=4,
      .beacon_interval=100
    }
};

Когда структура заполнена, мы вызываем esp_wifi_set_config() … доя примера:

esp_wifi_set_config(WIFI_IF_AP, &apConfig);

Наконец, мы называем esp_wifi_start().

Вот фрагмент кода, который можно использовать для настройки, и ESP32 в качестве точки доступа:

#include "freertos/FreeRTOS.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "nvs_flash.h"
#include "tcpip_adapter.h"
esp_err_t event_handler(void *ctx, system_event_t *event)
{
   //....
   return ESP_OK;
}
int app_main(void)
{
   nvs_flash_init();
   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_AP));
   wifi_config_t sta_config = {
      .ap = {
         .ssid="test_ap",
         .ssid_len=0,
         .password="test_test", // 8 digit minimum
         .channel=0,
         .authmode=WIFI_AUTH_OPEN,
         .ssid_hidden=0,
         .max_connection=4,
         .beacon_interval=100
      }
   };   
   ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &sta_config));
   ESP_ERROR_CHECK(esp_wifi_start());
   return 0;
}

Когда мы становимся точкой доступа, событие ESP32 WiFi создается из типа SYSTEM_EVENT_AP_START. Обратите внимание, что нет данных о полезной нагрузке, связанных с этим событием.

Как только ESP32 начнет прослушивать подключения к станции, будучи точкой доступа, мы захотим проверить, что это работает. Вы можете использовать любое устройство или систему для сканирования и подключения. Лично я использую Raspberry PI 3 для тестирования, поскольку он обеспечивает отличную среду Linux и имеет встроенный адаптер WiFi. Вы также можете подключить отдельный WiFi-ключ к одному из дополнительных USB-портов. Один из первых инструментов, которые мы хотим запустить, называется «iwlist», который будет выполнять сканирование:

$ sudo iwlist wlan1 scan

В результате мы можем искать наш ESP32 ... например:

Cell 02 - Address: 18:FE:34:6A:94:EF
          ESSID:"ESP32"
          Protocol:IEEE 802.11bgn
          Mode:Master
          Frequency:2.412 GHz (Channel 1)
          Encryption key:off
          Bit Rates:150 Mb/s
          Quality=100/100 Signal level=100/100

Другой доступный инструментом, доступный в этой среде, называется «wpa_cli», который предоставляет множество опций для тестирования WiFi. Способ, который я использую, заключается в подключении к точке доступа из командной строки:

$ sudo wpa_cli
add_network
set_network <num> ssid "<SSID>"
set_network <num> key_mgmt NONE
enable_network <num>
status

Для подключения к точке доступа, вам придется выбрать

select_network <num>
reconnect

или

reasociate

для отключения от точки доступа используйте команду:

disconnect

ifname – покажет текущий интерфейс

interface <name> - выберет текущий интерфейс

Для выполнения сканирования выполните команду «scan». По завершении запустите «scan_results», чтобы просмотреть список.

Когда станция подключается, ESP32 будет поднимать событие SYSTEM_EVENT_AP_STACONNECTED. Когда станция отключается, мы увидим событие SYSTEM_EVENT_AP_DISCONNECTED.

Смотрите также:

  • Man (8) - wpa_cl i

Когда удаленная станция подключается к ESP32 в качестве точки доступа, мы увидим отладочное сообщение, написанное в UART1, которое может выглядеть примерно так:

station: f0:25:b7:ff:12:c5 join, AID = 1

Это содержит MAC-адрес нового клиента, соединяющей сеть. Когда клиент отключится, мы увидим соответствующее сообщение журнала отладки, которое может быть:

station: f0:25:b7:ff:12:c5 leave, AID = 1

Из ESP32 мы можем определить, сколько клиентов в настоящий момент к ней подключено вызовом wifi_softap_get_station_num (). Если нужно получить детали этих клиентов, мы можем вызвать wifi_softap_get_station_info (), которая вернет связанный список wifi_sta_list_t. Мы должны явно освободить хранилище, выделенное этим вызовом, выполнив wifi_softap_free_station_info ().

Ниже приведен пример фрагмента кода, в котором перечислены детали подключенных станций:

uint8 stationCount = wifi_softap_get_station_num();
os_printf("stationCount = %d\n", stationCount);
wifi_sta_list_t *stationInfo = wifi_softap_get_station_info();
if (stationInfo != NULL) {
   while (stationInfo != NULL) {
      os_printf("Station IP: %d.%d.%d.%d\n", IP2STR(&(stationInfo->ip)));
      stationInfo = STAILQ_NEXT(stationInfo, next);
   }
   wifi_softap_free_station_info();
}

Когда ESP32 действует как точка доступа, это позволяет другим устройствам подключаться к нему и формировать соединение WiFi. Однако представляется, что два устройства, подключенные к одному ESP32, действующему как точка доступа, не могут напрямую взаимодействовать друг с другом. Например, представьте, что два устройства подключаются к ESP32 в качестве точки доступа. Им могут быть выделены IP-адреса 192.168.4.2 и 192.168.4.3. Мы можем предположить, что 192.168.4.2 может выполнять проверку 192.168.4.3 и наоборот, но это запрещено. Похоже, что разрешено только прямое сетевое подключение между вновь подключенными клиентами и точкой доступа (ESP32).

Это, по-видимому, ограничивает применимость ESP32 в качестве точки доступа. Основная цель ESP32 в качестве точки доступа - разрешить мобильным устройствам (например, вашему телефону) подключаться к ESP32 и вести беседу с приложением, которое работает на нем.

See also:

  • esp_wifi_set_config
  • esp_wifi_set_mode

Работа с подключенными клиентами

Когда наш ESP32 является точкой доступа, мы говорим, что хотим разрешить клиенту подключаться к нему. Это приводит к необходимости управления этими клиентами. Обычными вещами, которые мы хотели бы сделать, являются:

  • Определите, когда подключается новый клиент
  • Определите, когда уходит ранее подключенный клиент
  • Список подключенных в данный момент клиентов
  • Отключите одну или несколько подключенных в настоящее время клиентов

Мы можем зарегистрировать обработчик событий для обнаружения новых соединений клиентов и существующих отключений клиентов. Обработчик события получит SYSTEM_EVENT_AP_STACONNECTED, когда клиент подключится, и SYSTEM_EVENT_AP_STADISCONNECTED, что клиент отключится.

Мы можем получить список подключенных в данный момент клиентов, используя функцию esp_wifi_get_station_list(). Хранилище для этого списка выделено для нас, и мы должны указать, что мы больше не нуждаемся в нем, вызывая esp_wifi_free_station_list() по завершении.

Если по какой-то причине логика в нашей среде хочет принудительно отключить текущую подключенную станцию, мы можем использовать вызов esp_wifi_kick_station().

See also:

  • Handling WiFi events
  • esp_wifi_free_station_list
  • esp_wifi_get_station_list
  • esp_wifi_kick_station

WiFi at boot time

ESP32 может хранить информацию о запуске WiFi во флэш-памяти. Это позволяет выполнять свои функции при запуске без необходимости запрашивать у пользователя какую либо информацию. Эта возможность контролируется функциями esp_wifi_set_auto_connect () и esp_wifi_get_auto_connect().

Значениями параметров, используемых для автоматического подключения, являются значения, сохраненные во флэш-памяти при помощи функции esp_wifi_set_config().

See also: • esp_wifi_set_auto_connect • esp_wifi_get_auto_connect • esp_wifi_set_storage

DHCP клиент

Когда ESP32 подключается к точке доступа в качестве станции, он также запускает DHCP-клиент для подключения к серверу DHCP, который он предполагает, также доступен в точке доступа. Оттуда станция получает свой IP-адрес, адрес шлюза и сетевую маску. Однако есть моменты, когда мы хотим предоставить наши собственные значения для этих данных. Мы можем сделать это, вызвав tcpip_adapter_set_ip_info () во время установки. Это выглядит следующим образом:

tcpip_adapter_init();
tcpip_adapter_dhcpc_stop();
tcpip_adapter_set_ip_info();
esp_wifi_init();
esp_wifi_set_mode();
esp_wifi_set_config();
esp_wifi_start();
esp_wifi_config();

(Note that the parameters are omitted in the above).

Настройка для вызова tcpip_adapter_set_ip_info () может быть следующей:

tcpip_adapter_ip_info_t ipInfo;
IP4_ADDR(&ipInfo.ip, 192,168,1,99);
IP4_ADDR(&ipInfo.gw, 192,168,1,1);
IP4_ADDR(&ipInfo.netmask, 255,255,255,0);
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);

Альтернатива, используя строки, мы имеем:

tcpip_adapter_ip_info_t ipInfo;
inet_pton(AF_INET, "192.168.1.99", &ipInfo.ip);
inet_pton(AF_INET, "192.168.1.1", &ipInfo.gw);
inet_pton(AF_INET, "255.255.255.0", &ipInfo.netmask);
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);

See also:

  • tcpip_adapter_set_ip_info
  • tcpip_adapter_dhcpc_start
  • tcpip_adapter_dhcpc_stop
  • tcpip_adapter_dhcpc_get_status
  • tcpip_adapter_dhcpc_option
  • inet_pton

DHCP сервер

Когда ESP32 выполняет роль точки доступа, вполне вероятно, что вы захотите, чтобы он также вел себя как DHCP-сервер, чтобы подключенным клиентам мог быть автоматически назначен IP-адрес и переданы их маски подсети и шлюзы.

DHCP-сервер можно запустить и остановить в устройстве с помощью API, называемых wifi_softap_dhcps_start () и wifi_softap_dhcps_stop (). Текущее состояние (запущен или остановлено) DHCP-сервера можно найти с помощью вызова wifi_softap_dhcps_status().

Диапазон IP-адресов по умолчанию, предлагаемый сервером DHCP, составляет 192.168.4.1 вверх.

Первый адрес присваивается самому ESP32. Важно понимать, что этот диапазон адресов не является тем же самым диапазоном адресов, что и ваша ЛВС, где вы можете быть за работой. ESP32 сформировал собственное сетевое адресное пространство, и хотя они могут отображаться с одинаковыми номерами (192.168.x.x), они являются изолированными и независимыми сетями. Если вы запустите точку доступа на ESP32 и подключитесь к ней со своего телефона, не удивляйтесь, когда вы пытаетесь выполнить ping с вашего компьютера, подключенного к Интернету, и не получите ответа.

See also:

  • Error: Reference source not found

Текущий IP адрес, маска и шлюз

Если нам это нужно, мы можем запросить среду для текущего IP-адреса, сетевой маски и шлюза. Значения этих параметров обычно устанавливаются для нас сервером DHCP, когда мы подключитесь к точке доступа. Функция tcpip_adapter_get_ip_info () возвращает наше текущее значение. Поскольку ESP32 может иметь два IP-интерфейса (один для точки доступа и один для станции), мы предоставляем интерфейс, который мы хотим получить.

Когда мы подключаемся к точке доступа и выбираем использовать DHCP, когда нам присваивается IP-адрес, генерируется событие, которое может использоваться как указание на то, что у нас теперь есть действительный IP-адрес.

See also:

  • Handling WiFi events
  • Error: Reference source not found
  • tcpip_adapter_get_ip_info

WiFi Protected Setup – WPS

ESP32 поддерживает функцию WiFi Protected Setup в режиме станции. Это означает, что если точка доступа поддерживает его, ESP32 может подключиться к точке доступа без представления пароля. В настоящее время реализуется только «кнопочный режим» соединения. Используя этот механизм, физическая кнопка нажата на точку доступа, и в течение двух минут любая станция в диапазоне может присоединиться к сети с использованием протоколов WPS. Примером использования может быть нажата кнопка WPS точки доступа, а затем устройство ESP32, вызывающее wifi_wps_enable (), а затем wifi_wps_start (). Затем ESP32 подключился к сети.

See also:

  • wifi_wps_enable
  • wifi_wps_start
  • wifi_set_wps_cb
  • Simple Questions: What is WPS (WiFi Protected Setup)
  • Wikipedia: WiFi Protected Setup

Алгоритм инициализации WiFi

Представьте, что мы создали проект с использованием ESP32, который хочет подключиться к сети. Чтобы это произошло, мы хотим, чтобы ESP32 подключался к существующей точке доступа. Это работает, потому что ESP32 может быть Wi-Fi-клиентом. Для того, чтобы ESP32 соединился с точкой доступа, он должен знать два важных элемента. Он должен знать, к какой сети присоединиться (SSID), и ему нужно будет знать пароль для подключения к этой сети, поскольку большинство сетей требуют аутентификации. И есть головоломка. Если ESP32 перенесен в физически новую среду, как он «узнает», к какой сети подключиться и какой пароль использовать? Мы должны предположить, что ESP32 не имеет прикрепленного к нему экрана. Если бы это было так, мы могли бы запросить у пользователя информацию. Одним из решений является то, что ESP32 первоначально «будет» точкой доступа. Если бы это была точка доступа, мы могли бы использовать наш телефон для связи с ним, спросить, какие WiFi-сети он видит, предоставить пароль для сети и разрешить ему подключаться.

Пока (не сделано) {
   если (мы знаем наш ssid и пароль) {
      попытаемся подключиться к точке доступа; 
      Если (нам удалось установить связь) {
         return; 
      }
   }
   Сами становятся точкой доступа; 
   Слушать входящие запросы браузера; 
   Дождаться ввода пары SSID / password; 
}

Нам также необходимо обработать случай, когда мы считаем, что у нас есть SSID и пароль, используемые для подключения к точке доступа, но либо те, которые были изменены, либо мы находимся в другом месте. В этом случае мы также должны вернуться к точке доступа и ждать новых инструкций. Мы можем использовать энергонезависимое хранилище для сохранения нашего SSID и пароля. Возможно, мы захотим сохранить не одну пару SSID / пароль, а, возможно, сохранить упорядоченный список. Таким образом, когда мы учим наше устройство, как подключиться к точке доступа, а затем научим его подключаться к другому, мы можем вернуться к первому. Например, представьте, что вы используете ESP32 дома с одной сетью и тем же ESP32 при работе с другой сетью. Мы также можем сохранить информацию о статическом интерфейсе, если у нас либо нет, либо нет необходимости использовать службы DHCP-сервера при запуске в качестве станции.

См. Также: • Нелетучее хранение