Создание простого веб-сервера на ESP8266 NodeMCU в Arduino IDE
За последние несколько лет ESP8266 стал восходящей звездой среди проектов, связанных с IoT или Wi-Fi. Это чрезвычайно эффективный по стоимости Wi-Fi модуль, который (с небольшими усилиями) может быть запрограммирован для создания автономного веб-сервера. Это круто!
Рассмотрим на простом примере, как в Arduino IDE создать на ESP8266 NodeMCU веб-сервер для мониторинга и управления различными устройствами через Wi-Fi.
Что такое веб-сервер и как он работает?
Веб-сервер – это место, где веб-страницы хранятся, обрабатываются и выдаются веб-клиентам. Веб-клиент – это не что иное, как веб-браузер на наших ноутбуках и смартфонах. Связь между клиентом и сервером осуществляется с помощью специального протокола под названием протокол передачи гипертекста (HTTP).
В этом протоколе клиент инициирует связь, отправляя с помощью HTTP запрос на определенную веб-страницу, а сервер отвечает содержимым этой веб-страницы или сообщением об ошибке, если невозможно предоставить эту страницу (например, известная ошибка 404). Страницы, доставляемые сервером, в основном являются HTML документами.
Режимы работы ESP8266
Одна из важнейших функций, которую обеспечивает ESP8266, заключается в том, что он может не только подключаться к существующей Wi-Fi сети и работать в качестве веб-сервера, но он также может устанавливать собственную сеть, позволяя другим устройствам подключаться непосредственно к нему и получать доступ к веб-страницам. Это возможно, потому что ESP8266 может работать в трех разных режимах: режим станции, режим точки доступа и оба первых режима одновременно. Это обеспечивает возможность построения ячеистых сетей.
Режим станции (STA)
ESP8266, который подключается к существующей сети W-iFi (созданной вашим беспроводным маршрутизатором), называется станцией (Station, STA).
В режиме STA ESP8266 получает IP адрес от беспроводного маршрутизатора, к которому подключен. С этим IP адресом он может настроить веб-сервер и выдавать веб-страницы на все подключенные к существующей Wi-Fi сети устройства.
Режим точки доступа (AP)
ESP8266, который создает свою собственную сеть Wi-Fi и действует как концентратор (точно так же как маршрутизатор Wi-Fi) для одной или нескольких станций, называется точкой доступа (Access Point, AP). В отличие от Wi-Fi роутера, он не имеет интерфейса к проводной сети. Такой режим работы называется Soft Access Point (soft-AP). Максимальное количество станций, которые могут к нему подключиться, ограничено пятью.
В режиме AP ESP8266 создает новую сеть Wi-Fi и устанавливает для нее SSID (имя сети) и присваивает себе IP адрес. По запросу на этот IP адрес он может выдавать веб-страницы всем подключенным к этой сети устройствам.
Схема. Подключение светодиодов к ESP8266 NodeMCU
Теперь, когда мы знаем основы работы веб-сервера, и в каких режимах ESP8266 может создавать веб-сервер, пришло время подключить к ESP8266 NodeMCU пару светодиодов, которыми мы хотим управлять через Wi-Fi.
Начните с установки NodeMCU на макетную плату, чтобы каждая сторона платы NodeMCU была на отдельной стороне макетной платы. Затем подключите два светодиода к цифровым GPIO выводам D6 и D7 через токоограничивающие резисторы 220 Ом.
Когда вы закончите, у вас должно получиться что-то похожее на рисунок ниже.
Концепция управления устройствами через веб-сервер ESP8266
Итак, вы можете подумать: «Как я собираюсь управлять устройствами через веб-сервер, который просто обрабатывает и выдает веб-страницы?» Ну, тогда вам нужно понять, что происходит за кулисами.
Когда вы вводите URL адрес в веб-браузере и нажимаете клавишу ENTER, браузер отправляет на веб-сервер HTTP запрос (точнее GET запрос). Работа веб-сервера заключается в том, чтобы, сделав что-то, обработать этот запрос. Вы, возможно, уже поняли, что мы собираемся управлять устройствами, обращаясь к определенному URL. Например, предположим, что мы ввели в браузере URL адрес, например http://192.168.1.1/ledon (т.е. «включить светодиод»). Затем браузер отправляет HTTP запрос на ESP8266 для обработки. Когда ESP8266 читает этот запрос, он знает, что пользователь хочет включить светодиод. Таким образом, он включает светодиод и отправляет в браузер динамическую веб-страницу, отображающую состояние светодиода: LED status : ON. Всё просто!
ESP8266 в качестве HTTP сервера в режиме точки доступа Wi-Fi (AP)
Теперь перейдем к более интересному!
Как следует из заголовка, этот пример демонстрирует, как превратить ESP8266 в точку доступа (AP) и обрабатывать веб-страницы для любого подключенного клиента. Для начала подключите ESP8266 NodeMCU к компьютеру и загрузите скетч; и тогда мы рассмотрим его более подробно.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
/* Установите здесь свои SSID и пароль */
const char* ssid = "NodeMCU"; // SSID
const char* password = "12345678"; // пароль
/* Настройки IP адреса */
IPAddress local_ip(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
ESP8266WebServer server(80);
uint8_t LED1pin = D7;
bool LED1status = LOW;
uint8_t LED2pin = D6;
bool LED2status = LOW;
void setup()
{
Serial.begin(115200);
pinMode(LED1pin, OUTPUT);
pinMode(LED2pin, OUTPUT);
WiFi.softAP(ssid, password);
WiFi.softAPConfig(local_ip, gateway, subnet);
delay(100);
server.on("/", handle_OnConnect);
server.on("/led1on", handle_led1on);
server.on("/led1off", handle_led1off);
server.on("/led2on", handle_led2on);
server.on("/led2off", handle_led2off);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop()
{
server.handleClient();
if(LED1status)
digitalWrite(LED1pin, HIGH);
else
digitalWrite(LED1pin, LOW);
if(LED2status)
digitalWrite(LED2pin, HIGH);
else
digitalWrite(LED2pin, LOW);
}
void handle_OnConnect()
{
Serial.print("GPIO7 Status: ");
if(LED1status)
Serial.print("ON");
else
Serial.print("OFF");
Serial.print(" | GPIO6 Status: ");
if(LED2status)
Serial.print("ON");
else
Serial.print("OFF");
Serial.println("");
server.send(200, "text/html", SendHTML(LED1status,LED2status));
}
void handle_led1on()
{
LED1status = HIGH;
Serial.println("GPIO7 Status: ON");
server.send(200, "text/html", SendHTML(true,LED2status));
}
void handle_led1off()
{
LED1status = LOW;
Serial.println("GPIO7 Status: OFF");
server.send(200, "text/html", SendHTML(false,LED2status));
}
void handle_led2on()
{
LED2status = HIGH;
Serial.println("GPIO6 Status: ON");
server.send(200, "text/html", SendHTML(LED1status,true));
}
void handle_led2off()
{
LED2status = LOW;
Serial.println("GPIO6 Status: OFF");
server.send(200, "text/html", SendHTML(LED1status,false));
}
void handle_NotFound()
{
server.send(404, "text/plain", "Not found");
}
String SendHTML(uint8_t led1stat,uint8_t led2stat)
{
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>LED Control</title>\n";
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
ptr +=".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
ptr +=".button-on {background-color: #1abc9c;}\n";
ptr +=".button-on:active {background-color: #16a085;}\n";
ptr +=".button-off {background-color: #34495e;}\n";
ptr +=".button-off:active {background-color: #2c3e50;}\n";
ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
ptr +="<h1>ESP8266 Web Server</h1>\n";
ptr +="<h3>Using Access Point(AP) Mode</h3>\n";
if(led1stat)
ptr +="<p>LED1 Status: ON</p><a class=\"button button-off\" href=\"/led1off\">OFF</a>\n";
else
ptr +="<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/led1on\">ON</a>\n";
if(led2stat)
ptr +="<p>LED2 Status: ON</p><a class=\"button button-off\" href=\"/led2off\">OFF</a>\n";
else
ptr +="<p>LED2 Status: OFF</p><a class=\"button button-on\" href=\"/led2on\">ON</a>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Доступ к веб-серверу в режиме AP
После загрузки скетча откройте монитор последовательного порта со скоростью 115200 бит/с и нажмите кнопку RESET на ESP8266. Если всё в порядке, будет показано сообщение о запуске HTTP сервера.
Затем найдите любое устройство, которое вы можете подключить к сети Wi-Fi – телефон, ноутбук и т.д. И найдите сеть под названием NodeMCU. Подключитесь к сети с паролем 123456789.
После подключения к сети AP NodeMCU откройте браузер и введите в нем адрес 192.168.1.1. NodeMCU должен отобразить веб-страницу с текущим состоянием светодиодов и две кнопки для управления ими. Если посмотрите в этот момент на монитор последовательного порта, вы можете увидеть состояние выводов GPIO платы NodeMCU.
Теперь нажмите кнопку ON светодиода 1, чтобы включить его, наблюдая за URL. После нажатия кнопки ESP8266 получает запрос на URL адрес /led1on. Затем он включает светодиод 1 и отображает веб-страницу с обновленным состоянием светодиодов. Одновременно он выводит состояние вывода GPIO в монитор последовательного порта.
Вы можете проверить кнопку светодиода 2 и убедиться, что она работает аналогичным образом.
Теперь давайте подробнее рассмотрим код, чтобы понять, как он работает, и чтобы вы могли изменить его в соответствии с требованиями вашего проекта.
Подробное объяснение кода
Скетч начинается с включения библиотеки ESP8266WiFi.h
. Данная библиотека предоставляет специальные методы ESP8266 для работы с Wi-Fi , которые мы вызываем для подключения к сети. После этого подключаем библиотеку ESP8266WebServer.h
, в которой доступно несколько методов, которые помогут нам настроить сервер и обрабатывать входящие HTTP запросы, не беспокоясь о низкоуровневых деталях реализации.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
Поскольку мы настраиваем ESP8266 NodeMCU в режим точки доступа (AP), он создаст сеть Wi-Fi. Следовательно, нам нужно установить SSID сети, пароль, IP адрес, маску подсети и IP шлюз.
/* Установите здесь свои SSID и пароль */
const char* ssid = "NodeMCU"; // SSID
const char* password = "12345678"; // пароль
/* Настройки IP адреса */
IPAddress local_ip(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
Затем объявляем объект библиотеки ESP8266WebServer
, чтобы получить доступ к ее функциям. Конструктор этого объекта в качестве параметра принимает номер порта (который сервер будет прослушивать). Так как 80 – это порт по умолчанию для HTTP, мы будем использовать это значение. Теперь вы можете получить доступ к серверу, не указывая порт в URL.
ESP8266WebServer server(80);
Далее объявляем выводы GPIO платы NodeMCU, к которым подключены светодиоды, и их начальное состояние.
uint8_t LED1pin = D7;
bool LED1status = LOW;
uint8_t LED2pin = D6;
bool LED2status = LOW;
Внутренности функции setup()
Перед запуском настраиваем HTTP сервер. Прежде всего, для отладки открываем последовательное соединение и устанавливаем порты GPIO на выход.
Serial.begin(115200);
pinMode(LED1pin, OUTPUT);
pinMode(LED2pin, OUTPUT);
Затем настраиваем программно включенную точку доступа для создания сети Wi-Fi, указав SSID, пароль, IP адрес, маску подсети и адрес шлюза.
WiFi.softAP(ssid, password);
WiFi.softAPConfig(local_ip, gateway, subnet);
delay(100);
Чтобы обрабатывать входящие HTTP запросы, нам нужно указать, какой код выполнять при введении определенного URL. Для этого мы используем метод on()
. Этот метод принимает два параметра. Первый – это URL путь, а второй – имя функции, которую мы хотим выполнить при входе на этот URL.
Например, первая строка приведенного ниже фрагмента кода указывает, что, когда сервер получает HTTP запрос по корневому пути (/), он запускает функцию handle_OnConnect()
. Обратите внимание, что указанный URL адрес представляет собой относительный путь.
Аналогичным образом нам нужно указать еще 4 URL для обработки двух состояний двух светодиодов.
server.on("/", handle_OnConnect);
server.on("/led1on", handle_led1on);
server.on("/led1off", handle_led1off);
server.on("/led2on", handle_led2on);
server.on("/led2off", handle_led2off);
Мы не указали, что должен делать сервер, если клиент запрашивает какой-либо URL, отличающийся от указанных в server.on()
. Он должен выдать ответ с HTTP статусом 404 (Not Found, «страница не найдена») и сообщением для пользователя. Помещаем эти действия в отдельную функцию и используем метод server.onNotFound()
, чтобы указать серверу, что он должен выполнить, когда получит запрос на URI, который не был задан с помощью server.on()
.
server.onNotFound(handle_NotFound);
Теперь, чтобы запустить сервер, вызываем метод begin()
для объекта server
.
server.begin();
Serial.println("HTTP server started");
Внутренности функции loop()
Чтобы обработать реальные входящие HTTP запросы, нам нужно вызвать метод handleClient()
объекта server
. Также согласно запросу меняем состояние светодиодов.
void loop()
{
server.handleClient();
if(LED1status)
digitalWrite(LED1pin, HIGH);
else
digitalWrite(LED1pin, LOW);
if(LED2status)
digitalWrite(LED2pin, HIGH);
else
digitalWrite(LED2pin, LOW);
}
Далее нам нужно создать функцию, которую мы прикрепили к корневому (/) URL с помощью server.on()
. Помните? В начале этой функции мы проверяем состояние обоих светодиодов и выводим его на монитор последовательного порта. Чтобы ответить на HTTP запрос, используем метод send()
. Хотя этот метод можно вызывать с другим набором аргументов, его самая простая форма состоит из HTTP кода ответа, типа контента и самого контента.
В нашем случае мы отправляем код 200 (один из кодов состояния HTTP), который соответствует ответу OK. Затем мы указываем тип контента как "text/html", и, наконец, мы вызываем пользовательскую функцию SendHTML()
, которая создает динамическую HTML страницу, содержащую состояние светодиодов.
void handle_OnConnect()
{
Serial.print("GPIO7 Status: ");
if(LED1status)
Serial.print("ON");
else
Serial.print("OFF");
Serial.print(" | GPIO6 Status: ");
if(LED2status)
Serial.print("ON");
else
Serial.print("OFF");
Serial.println("");
server.send(200, "text/html", SendHTML(LED1status,LED2status));
}
Аналогичным образом нам нужно создать четыре функции для обработки запросов на включение/выключение светодиодов и страницу ошибки 404.
void handle_led1on()
{
LED1status = HIGH;
Serial.println("GPIO7 Status: ON");
server.send(200, "text/html", SendHTML(true,LED2status));
}
void handle_led1off()
{
LED1status = LOW;
Serial.println("GPIO7 Status: OFF");
server.send(200, "text/html", SendHTML(false,LED2status));
}
void handle_led2on()
{
LED2status = HIGH;
Serial.println("GPIO6 Status: ON");
server.send(200, "text/html", SendHTML(LED1status,true));
}
void handle_led2off()
{
LED2status = LOW;
Serial.println("GPIO6 Status: OFF");
server.send(200, "text/html", SendHTML(LED1status,false));
}
void handle_NotFound()
{
server.send(404, "text/plain", "Not found");
}
Отображение веб-страницы HTML
Функция SendHTML()
отвечает за создание веб-страницы всякий раз, когда веб-сервер ESP8266 получает запрос от веб-клиента. Она просто объединяет HTML код в большую строку и возвращает ее в функцию server.send()
, которую мы обсуждали ранее. Данная функция в качестве параметров для динамического генерирования HTML контента принимает состояние светодиодов.
Первый текст, который вы всегда должны отправлять, - это объявление <!DOCTYPE>
, которое указывает, что мы отправляем HTML код.
String SendHTML(uint8_t led1stat,uint8_t led2stat)
{
String ptr = "<!DOCTYPE html> <html>\n";
Затем <meta>
элемент viewport
делает веб-страницу адаптивной в любом веб-браузере. Далее тег title
устанавливает заголовок страницы.
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>LED Control</title>\n";
Стилизация веб-страницы
Далее идет немного CSS кода для стилизации кнопок и внешнего вида веб-страницы. Мы выбираем шрифт Helvetica, определяем контент, который будет отображаться в виде inline-block и выровнен по центру.
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
Следующий код устанавливает цвет, шрифт и поля вокруг элементов body
, H1
, H3
и p
.
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
Некоторые стили со свойствами, такими как цвет, размер, поля и т.д., также применяются к кнопкам. Для эффекта нажатия у кнопки ON/OFF с помощью селектора :active
устанавливается другой цвет фона.
ptr +=".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
ptr +=".button-on {background-color: #1abc9c;}\n";
ptr +=".button-on:active {background-color: #16a085;}\n";
ptr +=".button-off {background-color: #34495e;}\n";
ptr +=".button-off:active {background-color: #2c3e50;}\n";
Установка заголовка на веб-странице
Далее устанавливаем заголовок на веб-странице; вы можете изменить этот текст на то, что подходит для вашего приложения.
ptr +="<h1>ESP8266 Web Server</h1>\n";
ptr +="<h3>Using Access Point(AP) Mode</h3>\n";
Отображение кнопок и соответствующего состояния
Для динамического создания кнопок и состояния светодиодов мы используем оператор if
. Таким образом, в зависимости от состояния выводов GPIO, отображается кнопка либо ON, либо OFF.
if(led1stat)
ptr +="<p>LED1 Status: ON</p><a class=\"button button-off\" href=\"/led1off\">OFF</a>\n";
else
ptr +="<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/led1on\">ON</a>\n";
if(led2stat)
ptr +="<p>LED2 Status: ON</p><a class=\"button button-off\" href=\"/led2off\">OFF</a>\n";
else
ptr +="<p>LED2 Status: OFF</p><a class=\"button button-on\" href=\"/led2on\">ON</a>\n";
Использование ESP8266 в качестве HTTP сервера в режиме Wi-Fi Station (STA)
Теперь давайте перейдем к следующему примеру, который демонстрирует, как переключить ESP8266 в режим Station (STA) и выдавать веб-страницы для любого клиента, подключенного к существующей сети.
Прежде чем приступить к загрузке скетча, чтобы он у вас заработал, необходимо внести некоторые изменения. Чтобы ESP8266 мог установить соединение с существующей сетью, вам необходимо изменить две следующие переменные с учетными данными вашей сети.
/* Установите здесь свои SSID и пароль */
const char* ssid = "YourNetworkName"; // SSID
const char* password = "YourPassword"; // пароль
Теперь можно загрузить скетч в ESP8266.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
/* Установите здесь свои SSID и пароль */
const char* ssid = "YourNetworkName"; // SSID
const char* password = "YourPassword"; // пароль
ESP8266WebServer server(80);
uint8_t LED1pin = D7;
bool LED1status = LOW;
uint8_t LED2pin = D6;
bool LED2status = LOW;
void setup()
{
Serial.begin(115200);
delay(100);
pinMode(LED1pin, OUTPUT);
pinMode(LED2pin, OUTPUT);
Serial.println("Connecting to ");
Serial.println(ssid);
// подключиться к вашей локальной wi-fi сети
WiFi.begin(ssid, password);
// проверить, подключился ли wi-fi модуль к wi-fi сети
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
server.on("/", handle_OnConnect);
server.on("/led1on", handle_led1on);
server.on("/led1off", handle_led1off);
server.on("/led2on", handle_led2on);
server.on("/led2off", handle_led2off);
server.onNotFound(handle_NotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop()
{
server.handleClient();
if(LED1status)
digitalWrite(LED1pin, HIGH);
else
digitalWrite(LED1pin, LOW);
if(LED2status)
digitalWrite(LED2pin, HIGH);
else
digitalWrite(LED2pin, LOW);
}
void handle_OnConnect()
{
Serial.print("GPIO7 Status: ");
if(LED1status)
Serial.print("ON");
else
Serial.print("OFF");
Serial.print(" | GPIO6 Status: ");
if(LED2status)
Serial.print("ON");
else
Serial.print("OFF");
Serial.println("");
server.send(200, "text/html", SendHTML(LED1status,LED2status));
}
void handle_led1on()
{
LED1status = HIGH;
Serial.println("GPIO7 Status: ON");
server.send(200, "text/html", SendHTML(true,LED2status));
}
void handle_led1off()
{
LED1status = LOW;
Serial.println("GPIO7 Status: OFF");
server.send(200, "text/html", SendHTML(false,LED2status));
}
void handle_led2on()
{
LED2status = HIGH;
Serial.println("GPIO6 Status: ON");
server.send(200, "text/html", SendHTML(LED1status,true));
}
void handle_led2off()
{
LED2status = LOW;
Serial.println("GPIO6 Status: OFF");
server.send(200, "text/html", SendHTML(LED1status,false));
}
void handle_NotFound()
{
server.send(404, "text/plain", "Not found");
}
String SendHTML(uint8_t led1stat,uint8_t led2stat)
{
String ptr = "<!DOCTYPE html> <html>\n";
ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>LED Control</title>\n";
ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
ptr +=".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
ptr +=".button-on {background-color: #1abc9c;}\n";
ptr +=".button-on:active {background-color: #16a085;}\n";
ptr +=".button-off {background-color: #34495e;}\n";
ptr +=".button-off:active {background-color: #2c3e50;}\n";
ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";
ptr +="<h1>ESP8266 Web Server</h1>\n";
ptr +="<h3>Using Station(STA) Mode</h3>\n";
if(led1stat)
ptr +="<p>LED1 Status: ON</p><a class=\"button button-off\" href=\"/led1off\">OFF</a>\n";
else
ptr +="<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/led1on\">ON</a>\n";
if(led2stat)
ptr +="<p>LED2 Status: ON</p><a class=\"button button-off\" href=\"/led2off\">OFF</a>\n";
else
ptr +="<p>LED2 Status: OFF</p><a class=\"button button-on\" href=\"/led2on\">ON</a>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}
Доступ к веб-серверу в режиме STA
После загрузки скетча откройте монитор последовательного порта со скоростью 115200 бит/с и нажмите кнопку RESET на ESP8266. Если всё в порядке, он выведет динамический IP адрес, полученный от вашего маршрутизатора, и покажет сообщение, что HTTP сервер запущен.
Затем загрузите браузер и введите IP адрес, указанный на мониторе последовательного порта. NodeMCU должен выдать веб-страницу, показывающую текущее состояние светодиодов и две кнопки для управления ими. Если в это время взглянуть на монитор последовательного порта, то можно увидеть состояние выводов GPIO NodeMCU.
Теперь нажмите кнопку ON светодиода 1, чтобы включить его, наблюдая за URL. После нажатия кнопки ESP8266 получает запрос на URL адрес /led1on. Затем он включает светодиод 1 и отображает веб-страницу с обновленным состоянием светодиодов. Одновременно он выводит состояние вывода GPIO в монитор последовательного порта.
Вы можете проверить кнопку светодиода 2 и убедиться, что она работает аналогичным образом.
Объяснение кода
Если вы сравните этот код вместе с предыдущим примером, единственное отличие состоит в том, что мы не настраиваем точку доступа, а вместо этого с помощью функции WiFi.begin()
подключаемся к существующей сети.
// подключиться к вашей локальной wi-fi сети
WiFi.begin(ssid, password);
Пока ESP8266 пытается подключиться к сети, мы проверяем состояние подключения с помощью функции WiFi.status()
.
// проверить, подключился ли wi-fi модуль к wi-fi сети
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.print(".");
}
Данная функция возвращает следующие статусы:
- WL_CONNECTED: возвращается при подключении к сети Wi-Fi;
- WL_NO_SHIELD: возвращается, когда Wi-Fi модуль не подключен;
- WL_IDLE_STATUS: временное состояние, возвращаемое при вызове
WiFi.begin()
, и остающееся активным до тех пор, пока не истечет количество попыток подключения (что приводит к WL_CONNECT_FAILED), или пока не будет установлено соединение (что приводит к WL_CONNECTED); - WL_NO_SSID_AVAIL: возвращается, когда нет доступных SSID;
- WL_SCAN_COMPLETED: возвращается, когда сканирование сетей завершено;
- WL_CONNECT_FAILED: возвращается при неудаче подключения после всех попыток;
- WL_CONNECTION_LOST: возвращается при потере соединения;
- WL_DISCONNECTED: возвращается при отключении от сети.
Как только ESP8266 будет подключен к сети, скетч печатает IP адрес, присвоенный для ESP8266, отображая значение WiFi.localIP()
в мониторе последовательного порта.
Serial.println("");
Serial.println("WiFi connected..!");
Serial.print("Got IP: "); Serial.println(WiFi.localIP());
Единственная разница между режимами AP и STA состоит в том, что один создает сеть, а другой подключается к существующей сети. Остальная часть кода для обработки HTTP запросов и выдачи веб-страниц в режиме STA такая же, как и в режиме AP, описанном выше. Это включает в себя:
- объявление выводов GPIO NodeMCU, к которым подключены светодиоды;
- определение нескольких методов
server.on()
для обработки входящих HTTP запросов; - определение метода
server.onNotFound()
для обработки HTTP ошибки 404; - создание пользовательских функций, которые выполняются при вводе определенного URL;
- создание HTML страницы;
- стилизация веб-страницы;
- создание кнопок и отображение их состояния.