ESP8266 NodeMCU: создание Wi-Fi менеджера (библиотека AsyncWebServer)

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

ESP8266 NodeMCU создание Wi-Fi менеджера с библиотекой AsyncWebServer

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

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

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

ESP32 ESP8266 Wi-Fi менеджер веб-сервер как это работает
  • Когда 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 попытается подключиться к сети в режиме станции, используя настройки, которые вы ввели в форму (7);

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

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

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

Предварительные требования

Мы будем программировать плату ESP8266 с использованием Arduino IDE. Поэтому убедитесь, что у вас установлено дополнение для плат ESP8266.

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

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

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

Вы можете установить эти библиотеки с помощью менеджера библиотек Arduino. Перейдите в Sketch > Include Library > Manage Libraries и найдите библиотеки по их названиям.

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

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

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

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

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

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

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

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

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

ESP32 ESP8266 Wi-Fi менеджер файлы проекта

Вы должны сохранить HTML- и CSS-файлы внутри папки с названием data внутри папки скетча Arduino, как показано на предыдущей диаграмме. Мы загрузим эти файлы в файловую систему ESP8266 (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 менеджер поля ввода

Скопируйте следующий код в файл 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" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <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 ESP8266:

[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino
monitor_speed = 115200
lib_deps = ESP Async WebServer
board_build.filesystem = littlefs

Код

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

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete instructions at https://RandomNerdTutorials.com/esp8266-nodemcu-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 <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncTCP.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;

boolean restart = false;

// Initialize LittleFS
void initFS() {
  if (!LittleFS.begin()) {
    Serial.println("An error has occurred while mounting LittleFS");
  }
  else{
    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, "r");
  if(!file || file.isDirectory()){
    Serial.println("- failed to open file for reading");
    return String();
  }

  String fileContent;
  while(file.available()){
    fileContent = file.readStringUntil('\n');
    break;
  }
  file.close();
  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, "w");
  if(!file){
    Serial.println("- failed to open file for writing");
    return;
  }
  if(file.print(message)){
    Serial.println("- file written");
  } else {
    Serial.println("- frite failed");
  }
  file.close();
}

// 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...");
  delay(20000);
  if(WiFi.status() != WL_CONNECTED) {
    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);

  initFS();

  // 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, LOW);
      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, HIGH);
      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());
        }
      }
      restart = true;
      request->send(200, "text/plain", "Done. ESP will restart, connect to your router and go to IP address: " + ip);
    });
    server.begin();
  }
}

void loop() {
  if (restart){
    delay(5000);
    ESP.restart();
  }
}

Просмотр исходного кода

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

Давайте рассмотрим код и посмотрим, как работает 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()

Функция 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());
  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...");
  delay(20000);
  if(WiFi.status() != WL_CONNECTED) {
    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());
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...");

Если не удаётся подключиться к Wi-Fi в течение 20 секунд, функция возвращает false.

delay(20000);
if(WiFi.status() != WL_CONNECTED) {
  Serial.println("Failed to connect.");
  return false;
}

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

return true;

setup()

В 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, LOW);
    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, HIGH);
    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 /.

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

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

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

Устанавливаем переменную restart в true.

restart = true;

В loop() мы проверяем значение переменной restart и действуем соответствующим образом.

void loop() {
  if (restart){
    delay(5000);
    ESP.restart();
  }
}

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

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

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

Загрузите файлы из папки data на ваш ESP8266.

Нажмите [Ctrl] + [Shift] + [P] на Windows или [Cmd] + [Shift] + [P] на MacOS, чтобы открыть палитру команд. Найдите команду Upload LittleFS to Pico/ESP8266/ESP32 и нажмите на неё.

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

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

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

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

Arduino 2.0 кнопка загрузки

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

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

ESP Wi-Fi менеджер настраивает точку доступа монитор порта

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

Подключение к точке доступа ESP32 ESP8266 Wi-Fi менеджер

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

ESP32 ESP8266 Wi-Fi менеджер поля ввода

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

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

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

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

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

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

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

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

Заключение

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

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

Узнайте больше об ESP8266 из наших ресурсов:

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

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