ESP32: Создание Wi-Fi Менеджера (библиотека AsyncWebServer)

В этом руководстве вы создадите и настроите Wi-Fi менеджер с библиотекой ESPAsyncWebServer, который можно модифицировать для использования с вашими проектами веб-серверов или с любым проектом, которому требуется подключение к сети Wi-Fi. Wi-Fi менеджер позволяет подключать плату ESP32 к различным точкам доступа (сетям) без жёсткого кодирования сетевых учётных данных (SSID и пароль) и загрузки нового кода на плату. Ваш ESP автоматически подключится к последней сохранённой сети или настроит точку доступа, которую вы сможете использовать для настройки сетевых учётных данных.

ESP32: Создание простого Wi-Fi менеджера (библиотека AsyncWebServer)

Для лучшего понимания того, как работает этот проект, рекомендуем ознакомиться со следующими руководствами:

Мы также используем этот подход Wi-Fi менеджера в следующем проекте:

Как это работает

Посмотрите на следующую диаграмму, чтобы понять, как работает Wi-Fi менеджер, который мы создадим.

ESP32 ESP8266 Wi-Fi Manager Web Server как это работает
  • Когда ESP впервые запускается, он пытается прочитать файлы ssid.txt, pass.txt и ip.txt* ( 1);

  • Если файлы пустые ( 2) (при первом запуске платы файлы пустые), ваша плата настраивается как точка доступа ( 3);

  • Используя любое устройство с поддержкой Wi-Fi и браузером, вы можете подключиться к вновь созданной точке доступа (имя по умолчанию ESP-WIFI-MANAGER);

  • После установления соединения с ESP-WIFI-MANAGER вы можете перейти на IP-адрес по умолчанию 192.168.4.1, чтобы открыть веб-страницу, которая позволяет настроить SSID и пароль ( 4);

  • SSID, пароль и IP-адрес, введённые в форме, сохраняются в соответствующих файлах: ssid.txt, pass.txt и ip.txt ( 5);

  • После этого плата ESP перезагружается ( 6);

  • На этот раз, после перезагрузки, файлы не пустые, поэтому ESP попытается подключиться к сети в режиме станции (station mode), используя настройки, которые вы ввели в форме ( 7);

  • Если соединение установлено, процесс завершён успешно, и вы можете получить доступ к главной странице веб-сервера, которая может делать всё, что вам нужно (считывать показания датчиков, управлять выходами, отображать текст и т.д.) ( 9). В противном случае будет настроена точка доступа ( 3), и вы сможете перейти по IP-адресу по умолчанию (192.168.4.1), чтобы добавить другую комбинацию SSID/пароль.

* мы также создали поле gateway и файл gateway.txt для сохранения IP-адреса шлюза (это не показано на диаграмме).

Чтобы показать, как настроить Wi-Fi менеджер, мы настроим веб-сервер, управляющий одним выходом (GPIO2 — встроенный светодиод). Вы можете применить Wi-Fi менеджер к любому проекту веб-сервера, построенному с библиотекой ESPAsyncWebServer, или к любому проекту, требующему подключения ESP к сети Wi-Fi.

Необходимые условия

Мы будем программировать плату ESP32 с помощью Arduino IDE. Убедитесь, что у вас установлено дополнение для плат ESP32.

Если вы хотите программировать ESP32 с помощью VS Code + PlatformIO, следуйте следующему руководству:

Установка библиотек (Arduino IDE)

Мы построим веб-сервер, используя следующие библиотеки:

Вы можете установить эти библиотеки через Arduino Library Manager. Откройте Library Manager, нажав на значок библиотеки на левой боковой панели.

Найдите ESPAsyncWebServer и установите ESPAsyncWebServer от ESP32Async.

Установка ESPAsyncWebServer ESP32 Arduino IDE

Затем установите библиотеку AsyncTCP. Найдите AsyncTCP и установите AsyncTCP от ESP32Async.

Установка AsyncTCP ESP32 Arduino IDE

Плагин загрузки файловой системы

Перед продолжением вам необходимо установить плагин ESP32 Uploader в вашу Arduino IDE.

Организация файлов

Для поддержания порядка в проекте и облегчения понимания мы создадим четыре различных файла для построения веб-сервера:

  • Скетч Arduino, который обрабатывает веб-сервер;

  • index.html: для определения содержимого веб-страницы в режиме станции для управления выходом (или любая другая веб-страница, которую вы хотите создать);

  • style.css: для стилизации веб-страниц;

  • wifimanager.html: для определения содержимого веб-страницы Wi-Fi менеджера, когда ESP находится в режиме точки доступа.

ESP32 ESP8266 Wi-Fi Manager файлы проекта

Вы должны сохранить HTML и CSS файлы внутри папки с именем data внутри папки скетча Arduino, как показано на предыдущей диаграмме. Мы загрузим эти файлы в файловую систему ESP32 (LittleFS).

Вы можете скачать все файлы проекта:

Создание HTML файлов

Для этого проекта вам нужны два HTML файла. Один для построения главной страницы, управляющей выходом (index.html), и другой для построения страницы Wi-Fi менеджера (wifimanager.html).

index.html

Вот текст, который вы должны скопировать в файл index.html.

<!DOCTYPE html>
<html>
  <head>
    <title>ESP WEB SERVER</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="style.css">
    <link rel="icon" type="image/png" href="favicon.png">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  </head>
  <body>
    <div class="topnav">
      <h1>ESP WEB SERVER</h1>
    </div>
    <div class="content">
      <div class="card-grid">
        <div class="card">
          <p class="card-title"><i class="fas fa-lightbulb"></i> GPIO 2</p>
          <p>
            <a href="on"><button class="button-on">ON</button></a>
            <a href="off"><button class="button-off">OFF</button></a>
          </p>
          <p class="state">State: %STATE%</p>
        </div>
      </div>
    </div>
  </body>
</html>

Просмотреть исходный код

Мы не будем объяснять, как работает этот HTML-файл, потому что это не цель данного руководства. Цель данного руководства — объяснить части, связанные с Wi-Fi менеджером.

wifimanager.html

Веб-страница Wi-Fi менеджера выглядит так:

ESP32 ESP8266 Wi-Fi Manager поля

Скопируйте следующий код в файл wifimanager.html. Это создаст веб-страницу с формой, содержащей три поля ввода и кнопку Submit.

<!DOCTYPE html>
<html>
<head>
  <title>ESP Wi-Fi Manager</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <div class="topnav">
    <h1>ESP Wi-Fi Manager</h1>
  </div>
  <div class="content">
    <div class="card-grid">
      <div class="card">
        <form action="/" method="POST">
          <p>
            <label for="ssid">SSID</label>
            <input type="text" id ="ssid" name="ssid"><br>
            <label for="pass">Password</label>
            <input type="text" id ="pass" name="pass"><br>
            <label for="ip">IP Address</label>
            <input type="text" id ="ip" name="ip" value="192.168.1.200"><br>
            <label for="gateway">Gateway Address</label>
            <input type="text" id ="gateway" name="gateway" value="192.168.1.1"><br>
            <input type ="submit" value ="Submit">
          </p>
        </form>
      </div>
    </div>
  </div>
</body>
</html>

Просмотреть исходный код

В этом HTML-файле мы создаём HTML-форму, которая отправит HTTP POST-запрос с данными, введёнными на сервер.

<form action="/" method="POST">

Форма содержит три поля ввода и соответствующие метки: SSID, пароль и IP-адрес.

Это поле ввода для SSID:

<label for="ssid">SSID</label>
<input type="text" id ="ssid" name="ssid"><br>

Это поле ввода для пароля.

<label for="pass">Password</label>
<input type="text" id ="pass" name="pass"><br>

Есть поле ввода для IP-адреса, который вы хотите присвоить ESP в режиме станции. По умолчанию мы установили его на 192.168.1.200 (вы можете установить другой IP-адрес по умолчанию, или вы можете удалить параметр value — у него не будет значения по умолчанию).

<input type="text" id ="ip" name="ip" value="192.168.1.200">

Наконец, есть поле ввода для адреса шлюза. Если IP-адрес по умолчанию 192.168.1.200, то шлюз по умолчанию может быть 192.168.1.1.

<input type="text" id ="gateway" name="gateway" value="192.168.1.1"><br>

CSS файл

Скопируйте следующие стили в файл style.css. Мы не будем объяснять, как работают эти стили. Мы уже объясняли, как работают подобные стили в других проектах ESP веб-серверов.

html {
  font-family: Arial, Helvetica, sans-serif;
  display: inline-block;
  text-align: center;
}

h1 {
  font-size: 1.8rem;
  color: white;
}

p {
  font-size: 1.4rem;
}

.topnav {
  overflow: hidden;
  background-color: #0A1128;
}

body {
  margin: 0;
}

.content {
  padding: 5%;
}

.card-grid {
  max-width: 800px;
  margin: 0 auto;
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.card {
  background-color: white;
  box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
}

.card-title {
  font-size: 1.2rem;
  font-weight: bold;
  color: #034078
}

input[type=submit] {
  border: none;
  color: #FEFCFB;
  background-color: #034078;
  padding: 15px 15px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  width: 100px;
  margin-right: 10px;
  border-radius: 4px;
  transition-duration: 0.4s;
  }

input[type=submit]:hover {
  background-color: #1282A2;
}

input[type=text], input[type=number], select {
  width: 50%;
  padding: 12px 20px;
  margin: 18px;
  display: inline-block;
  border: 1px solid #ccc;
  border-radius: 4px;
  box-sizing: border-box;
}

label {
  font-size: 1.2rem;
}
.value{
  font-size: 1.2rem;
  color: #1282A2;
}
.state {
  font-size: 1.2rem;
  color: #1282A2;
}
button {
  border: none;
  color: #FEFCFB;
  padding: 15px 32px;
  text-align: center;
  font-size: 16px;
  width: 100px;
  border-radius: 4px;
  transition-duration: 0.4s;
}
.button-on {
  background-color: #034078;
}
.button-on:hover {
  background-color: #1282A2;
}
.button-off {
  background-color: #858585;
}
.button-off:hover {
  background-color: #252524;
}

Просмотреть исходный код

Настройка веб-сервера

Если вы используете VS Code с расширением PlatformIO, вам нужно отредактировать файл platformio.ini, чтобы он выглядел, как показано ниже. Если вы используете Arduino IDE, можете это пропустить.

platformio.ini ESP32:

[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
monitor_speed=115200
lib_deps = ESP Async WebServer

Скопируйте следующий код в Arduino IDE или в файл main.cpp, если вы используете VS Code.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete instructions at https://RandomNerdTutorials.com/esp32-wi-fi-manager-asyncwebserver/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
#include <Arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
#include "LittleFS.h"

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Search for parameter in HTTP POST request
const char* PARAM_INPUT_1 = "ssid";
const char* PARAM_INPUT_2 = "pass";
const char* PARAM_INPUT_3 = "ip";
const char* PARAM_INPUT_4 = "gateway";

//Variables to save values from HTML form
String ssid;
String pass;
String ip;
String gateway;

// File paths to save input values permanently
const char* ssidPath = "/ssid.txt";
const char* passPath = "/pass.txt";
const char* ipPath = "/ip.txt";
const char* gatewayPath = "/gateway.txt";

IPAddress localIP;
//IPAddress localIP(192, 168, 1, 200); // hardcoded

// Set your Gateway IP address
IPAddress localGateway;
//IPAddress localGateway(192, 168, 1, 1); //hardcoded
IPAddress subnet(255, 255, 0, 0);

// Timer variables
unsigned long previousMillis = 0;
const long interval = 10000;  // interval to wait for Wi-Fi connection (milliseconds)

// Set LED GPIO
const int ledPin = 2;
// Stores LED state

String ledState;

// Initialize LittleFS
void initLittleFS() {
  if (!LittleFS.begin(true)) {
    Serial.println("An error has occurred while mounting LittleFS");
  }
  Serial.println("LittleFS mounted successfully");
}

// Read File from LittleFS
String readFile(fs::FS &fs, const char * path){
  Serial.printf("Reading file: %s\r\n", path);

  File file = fs.open(path);
  if(!file || file.isDirectory()){
    Serial.println("- failed to open file for reading");
    return String();
  }

  String fileContent;
  while(file.available()){
    fileContent = file.readStringUntil('\n');
    break;
  }
  return fileContent;
}

// Write file to LittleFS
void writeFile(fs::FS &fs, const char * path, const char * message){
  Serial.printf("Writing file: %s\r\n", path);

  File file = fs.open(path, FILE_WRITE);
  if(!file){
    Serial.println("- failed to open file for writing");
    return;
  }
  if(file.print(message)){
    Serial.println("- file written");
  } else {
    Serial.println("- write failed");
  }
}

// Initialize WiFi
bool initWiFi() {
  if(ssid=="" || ip==""){
    Serial.println("Undefined SSID or IP address.");
    return false;
  }

  WiFi.mode(WIFI_STA);
  localIP.fromString(ip.c_str());
  localGateway.fromString(gateway.c_str());

  if (!WiFi.config(localIP, localGateway, subnet)){
    Serial.println("STA Failed to configure");
    return false;
  }
  WiFi.begin(ssid.c_str(), pass.c_str());
  Serial.println("Connecting to WiFi...");

  unsigned long currentMillis = millis();
  previousMillis = currentMillis;

  while(WiFi.status() != WL_CONNECTED) {
    currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      Serial.println("Failed to connect.");
      return false;
    }
  }

  Serial.println(WiFi.localIP());
  return true;
}

// Replaces placeholder with LED state value
String processor(const String& var) {
  if(var == "STATE") {
    if(digitalRead(ledPin)) {
      ledState = "ON";
    }
    else {
      ledState = "OFF";
    }
    return ledState;
  }
  return String();
}

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);

  initLittleFS();

  // Set GPIO 2 as an OUTPUT
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  // Load values saved in LittleFS
  ssid = readFile(LittleFS, ssidPath);
  pass = readFile(LittleFS, passPath);
  ip = readFile(LittleFS, ipPath);
  gateway = readFile (LittleFS, gatewayPath);
  Serial.println(ssid);
  Serial.println(pass);
  Serial.println(ip);
  Serial.println(gateway);

  if(initWiFi()) {
    // Route for root / web page
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
      request->send(LittleFS, "/index.html", "text/html", false, processor);
    });
    server.serveStatic("/", LittleFS, "/");

    // Route to set GPIO state to HIGH
    server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request) {
      digitalWrite(ledPin, HIGH);
      request->send(LittleFS, "/index.html", "text/html", false, processor);
    });

    // Route to set GPIO state to LOW
    server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request) {
      digitalWrite(ledPin, LOW);
      request->send(LittleFS, "/index.html", "text/html", false, processor);
    });
    server.begin();
  }
  else {
    // Connect to Wi-Fi network with SSID and password
    Serial.println("Setting AP (Access Point)");
    // NULL sets an open Access Point
    WiFi.softAP("ESP-WIFI-MANAGER", NULL);

    IPAddress IP = WiFi.softAPIP();
    Serial.print("AP IP address: ");
    Serial.println(IP);

    // Web Server Root URL
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
      request->send(LittleFS, "/wifimanager.html", "text/html");
    });

    server.serveStatic("/", LittleFS, "/");

    server.on("/", HTTP_POST, [](AsyncWebServerRequest *request) {
      int params = request->params();
      for(int i=0;i<params;i++){
        const AsyncWebParameter* p = request->getParam(i);
        if(p->isPost()){
          // HTTP POST ssid value
          if (p->name() == PARAM_INPUT_1) {
            ssid = p->value().c_str();
            Serial.print("SSID set to: ");
            Serial.println(ssid);
            // Write file to save value
            writeFile(LittleFS, ssidPath, ssid.c_str());
          }
          // HTTP POST pass value
          if (p->name() == PARAM_INPUT_2) {
            pass = p->value().c_str();
            Serial.print("Password set to: ");
            Serial.println(pass);
            // Write file to save value
            writeFile(LittleFS, passPath, pass.c_str());
          }
          // HTTP POST ip value
          if (p->name() == PARAM_INPUT_3) {
            ip = p->value().c_str();
            Serial.print("IP Address set to: ");
            Serial.println(ip);
            // Write file to save value
            writeFile(LittleFS, ipPath, ip.c_str());
          }
          // HTTP POST gateway value
          if (p->name() == PARAM_INPUT_4) {
            gateway = p->value().c_str();
            Serial.print("Gateway set to: ");
            Serial.println(gateway);
            // Write file to save value
            writeFile(LittleFS, gatewayPath, gateway.c_str());
          }
          //Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
        }
      }
      request->send(200, "text/plain", "Done. ESP will restart, connect to your router and go to IP address: " + ip);
      delay(3000);
      ESP.restart();
    });
    server.begin();
  }
}

void loop() {

}

Просмотреть исходный код

Давайте рассмотрим код и разберём, как работает Wi-Fi менеджер.

Следующие переменные используются для поиска SSID, пароля, IP-адреса и шлюза в HTTP POST-запросе, отправляемом при отправке формы.

// Search for parameter in HTTP POST request
const char* PARAM_INPUT_1 = "ssid";
const char* PARAM_INPUT_2 = "pass";
const char* PARAM_INPUT_3 = "ip";
const char* PARAM_INPUT_4 = "gateway";

Переменные ssid, pass, ip и gateway сохраняют значения SSID, пароля, IP-адреса и шлюза, отправленные через форму.

//Variables to save values from HTML form
String ssid;
String pass;
String ip;
String gateway;

SSID, пароль, IP-адрес и шлюз при отправке сохраняются в файлах в файловой системе ESP. Следующие переменные указывают пути к этим файлам.

// File paths to save input values permanently
const char* ssidPath = "/ssid.txt";
const char* passPath = "/pass.txt";
const char* ipPath = "/ip.txt";
const char* gatewayPath = "/gateway.txt";

IP-адрес станции и шлюз отправляются через форму Wi-Fi менеджера. Маска подсети жёстко закодирована, но вы можете легко модифицировать этот проект, добавив ещё одно поле для ввода маски подсети, если это необходимо.

IPAddress localIP;
//IPAddress localIP(192, 168, 1, 200); // hardcoded

// Set your Gateway IP address
IPAddress localGateway;
//IPAddress localGateway(192, 168, 1, 1); //hardcoded
IPAddress subnet(255, 255, 0, 0);

Функция initWiFi() возвращает булево значение (true или false), указывающее, успешно ли плата ESP подключилась к сети.

bool initWiFi() {
  if(ssid=="" || ip==""){
    Serial.println("Undefined SSID or IP address.");
    return false;
  }

  WiFi.mode(WIFI_STA);
  localIP.fromString(ip.c_str());

  if (!WiFi.config(localIP, gateway, subnet)){
    Serial.println("STA Failed to configure");
    return false;
  }
  WiFi.begin(ssid.c_str(), pass.c_str());
  Serial.println("Connecting to WiFi...");

  unsigned long currentMillis = millis();
  previousMillis = currentMillis;

  while(WiFi.status() != WL_CONNECTED) {
    currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      Serial.println("Failed to connect.");
      return false;
    }
  }

  Serial.println(WiFi.localIP());
  return true;
}

Сначала она проверяет, пусты ли переменные ssid и ip. Если да, подключиться к сети не получится, поэтому возвращается false.

if(ssid=="" || ip==""){

Если это не так, мы попытаемся подключиться к сети, используя SSID и пароль, сохранённые в переменных ssid и pass, и установим IP-адрес.

WiFi.mode(WIFI_STA);
localIP.fromString(ip.c_str());

if (!WiFi.config(localIP, gateway, subnet)){
  Serial.println("STA Failed to configure");
  return false;
}
WiFi.begin(ssid.c_str(), pass.c_str());
Serial.println("Connecting to WiFi...");

Если не удаётся подключиться к Wi-Fi в течение 10 секунд (переменная interval), функция вернёт false.

unsigned long currentMillis = millis();
previousMillis = currentMillis;

while(WiFi.status() != WL_CONNECTED) {
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    Serial.println("Failed to connect.");
    return false;
  }

Если ни одно из предыдущих условий не выполнено, это означает, что ESP успешно подключился к сети в режиме станции (возвращает true).

return true;

В функции setup() начинаем чтение файлов для получения ранее сохранённых SSID, пароля, IP-адреса и шлюза.

ssid = readFile(LittleFS, ssidPath);
pass = readFile(LittleFS, passPath);
ip = readFile(LittleFS, ipPath);
gateway = readFile (LittleFS, gatewayPath);

Если ESP успешно подключается в режиме станции (функция initWiFi() возвращает true), мы можем установить команды для обработки запросов веб-сервера (или любой другой код, требующий подключения ESP к интернету):

if(initWiFi()) {
  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(LittleFS, "/index.html", "text/html", false, processor);
  });
  server.serveStatic("/", LittleFS, "/");

  // Route to set GPIO state to HIGH
  server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request) {
    digitalWrite(ledPin, HIGH);
    request->send(LittleFS, "/index.html", "text/html", false, processor);
  });

  // Route to set GPIO state to LOW
  server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request) {
    digitalWrite(ledPin, LOW);
    request->send(LittleFS, "/index.html", "text/html", false, processor);
  });
  server.begin();
}

Если это не так, функция initWiFi() возвращает false. ESP настроит точку доступа:

else {
  // Connect to Wi-Fi network with SSID and password
  Serial.println("Setting AP (Access Point)");
  // NULL sets an open Access Point
  WiFi.softAP("ESP-WIFI-MANAGER", NULL);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

Для настройки точки доступа мы используем метод softAP() и передаём в качестве аргументов имя точки доступа и пароль. Мы хотим, чтобы точка доступа была открытой, поэтому установили пароль в NULL. Вы можете добавить пароль, если хотите. Чтобы узнать больше о настройке точки доступа, прочитайте следующее руководство:

Когда вы подключаетесь к точке доступа, отображается веб-страница для ввода сетевых учётных данных в форме. Поэтому ESP должен отправить файл wifimanager.html, когда получает запрос на корневой URL /.

// Web Server Root URL
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(LittleFS, "/wifimanager.html", "text/html");
});

Мы также должны обработать то, что происходит при отправке формы через HTTP POST-запрос. Следующие строки сохраняют отправленные значения в переменных ssid, pass и ip и записывают эти переменные в соответствующие файлы.

server.on("/", HTTP_POST, [](AsyncWebServerRequest *request) {
  int params = request->params();
  for(int i=0;i<params;i++){
    AsyncWebParameter* p = request->getParam(i);
    if(p->isPost()){
      // HTTP POST ssid value
      if (p->name() == PARAM_INPUT_1) {
        ssid = p->value().c_str();
        Serial.print("SSID set to: ");
        Serial.println(ssid);
        // Write file to save value
        writeFile(LittleFS, ssidPath, ssid.c_str());
      }
      // HTTP POST pass value
      if (p->name() == PARAM_INPUT_2) {
        pass = p->value().c_str();
        Serial.print("Password set to: ");
        Serial.println(pass);
        // Write file to save value
        writeFile(LittleFS, passPath, pass.c_str());
      }
      // HTTP POST ip value
      if (p->name() == PARAM_INPUT_3) {
        ip = p->value().c_str();
        Serial.print("IP Address set to: ");
        Serial.println(ip);
        // Write file to save value
        writeFile(LittleFS, ipPath, ip.c_str());
      }
     // HTTP POST gateway value
      if (p->name() == PARAM_INPUT_4) {
        gateway = p->value().c_str();
        Serial.print("Gateway set to: ");
        Serial.println(gateway);
        // Write file to save value
        writeFile(LittleFS, gatewayPath, gateway.c_str());
      }
      //Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
    }
  }

После отправки формы отправляем ответ с текстом, чтобы мы знали, что ESP получил данные формы:

request->send(200, "text/plain", "Done. ESP will restart, connect to your router and go to IP address: " + ip);

Через три секунды перезагружаем плату ESP с помощью ESP.restart():

delay(3000);
ESP.restart();

Это краткое описание того, как работает код.

Вы можете применить эту идею к любому из других проектов веб-серверов, построенных с библиотекой ESPAsyncWebServer.

Загрузка кода и файлов

Загрузите файлы из папки data на ваш ESP32. В Arduino IDE нажмите [ Ctrl] + [ Shift] + [ P] на Windows или [ Cmd] + [ Shift] + [ P] на MacOS, чтобы открыть палитру команд. Найдите команду Upload LittleFS to Pico/ESP8266/ESP32 и нажмите на неё.

Загрузка LittleFS на Pico ESP8266 ESP32 Arduino IDE

Если у вас нет этой опции, значит вы не установили плагин загрузки файловой системы. Ознакомьтесь с этим руководством.

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

Если вы используете VS Code с расширением PlatformIO, следуйте следующему руководству, чтобы узнать, как загружать файлы на ваши платы:

После успешной загрузки файлов загрузите код на плату.

Arduino IDE 2 кнопка загрузки

Демонстрация

После успешной загрузки всех файлов и скетча вы можете открыть Serial Monitor. Если код запускается впервые, он попытается прочитать файлы ssid.txt, pass.txt и ip.txt, и это не удастся, потому что эти файлы ещё не были созданы. Поэтому будет запущена точка доступа.

ESP Wi-Fi Manager устанавливает точку доступа Serial Monitor

На вашем компьютере или смартфоне перейдите в настройки сети и подключитесь к точке доступа ESP-WIFI-MANAGER.

Подключение к точке доступа ESP32 Wi-Fi Manager

Затем откройте браузер и перейдите на 192.168.4.1. Должна открыться веб-страница Wi-Fi менеджера.

ESP32 ESP8266 Wi-Fi Manager поля

Введите данные вашей сети: SSID и пароль, а также доступный IP-адрес в вашей локальной сети.

После этого вы будете перенаправлены на следующую страницу:

ESP32 ESP8266 подключён к станции успешно Wi-Fi Manager

В то же время ESP должен вывести в Serial Monitor информацию, указывающую, что введённые параметры были успешно сохранены в соответствующих файлах.

Через несколько секунд ESP перезагрузится. И если вы ввели правильный SSID и пароль, он запустится в режиме станции:

ESP32 ESP8266 успешно подключён к Wi-Fi станции

На этот раз откройте браузер в вашей локальной сети и введите IP-адрес ESP. Вы должны получить доступ к веб-странице для управления выходами:

ESP32 ESP8266 управление выходами веб-сервер

Заключение

В этом руководстве вы узнали, как настроить Wi-Fi менеджер для ваших проектов веб-серверов или для любого другого проекта, требующего подключения ESP к интернету. С Wi-Fi менеджером вы можете легко подключать ваши платы ESP к различным сетям без необходимости жёсткого кодирования сетевых учётных данных. Вы можете применить Wi-Fi менеджер к любому проекту веб-сервера, построенному с библиотекой ESPAsyncWebServer.

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

Если вы хотите узнать больше о создании веб-серверов с платами ESP32 и ESP8266, обязательно ознакомьтесь с электронной книгой:

Надеемся, что это руководство было для вас полезным.

Спасибо за чтение.

Источник: :doc:`ESP32: Create a Wi-Fi Manager (AsyncWebServer library) <../esp32-wi-fi-manager-asyncwebserver/index>` by Rui Santos & Sara Santos - Random Nerd Tutorials