ESP8266:Прошивки/Arduino/Библиотеки/Библиотека ESP8266WiFi/Класс сервера/Сервер, обслуживающий веб-страницу
Сервер, обслуживающий веб-страницу[1]
Настройка веб-сервера на ESP8266 на удивление проста, т.к. требует очень небольшого скетча. Это простота обеспечивается за счет универсальности библиотеки ESP8266WiFi.
Цель этого скетча-примера – подготовить веб-страницу, чтобы ее можно было открыть веб-браузером. Страница будет показывать текущее значение аналогового входного контакта ESP8266.
Объект
Начнем с создания экземпляра класса WiFiServer:
WiFiServer server(80);
Сервер отвечает клиентам (в данном случае – браузерам) на порте 80, который является стандартным портом, через который браузеры «общаются» с веб-серверами.
Страница
Теперь давайте напишем короткую функцию prepareHtmlPage(), которая будет возвращать переменную типа String, содержащую содержимое веб-страницы. Мы передадим эту переменную серверу, чтобы тот передал ее клиенту.
String prepareHtmlPage()
{
String htmlPage =
String("HTTP/1.1 200 OK\r\n") +
"Content-Type: text/html\r\n" +
"Connection: close\r\n" + // после отправки ответа
// соединение будет закрыто
"Refresh: 5\r\n" + // автоматически обновляем
// страницу каждые 5 секунд
"\r\n" +
"<!DOCTYPE HTML>" +
"<html>" +
"Analog input: " + String(analogRead(A0)) +
"</html>" +
"\r\n";
return htmlPage;
}
Эта функция не делает ничего выдающегося. Просто собирает вместе текстовый заголовок и HTML-содержимое страницы.
Сначала заголовок
Заголовок информирует клиента, какой тип контента последует и как его будут выдавать:
Content-Type: text/html
Connection: close
Refresh: 5
В нашем примере типом контента является text/html, после ответа соединение будет закрыто, а контент будет запрашиваться клиентом каждые 5 секунд. В конце заголовка будут стоять символы пустой строки («\r\n»). Они нужны для того, чтобы отделить заголовок от контента, который последует дальше.
<!DOCTYPE HTML>
<html>
Analog input: [Value]
</html>
Этот контент содержит два базовых HTML-тега. Один – для описания типа HTML-документа (<!DOCTYPE HTML>), а второй – чтобы отметить начало (''') и конец (''') документа. Внутри – необработанное значение входного аналогового контакта ESP8266, считанное функцией analogRead(A0) и преобразованное в тип данных String.
String(analogRead(A0))
Выдача страницы
Выдача веб-страницы выполняется в блоке loop(), где сервер ждет подключения нового клиента и получения данных с запросом.
void loop()
{
WiFiClient client = server.available();
if (client)
{
// у нас новый клиент, отправивший запрос
}
}
Когда подключится новый клиент, сервер прочтет его запрос, а затем напечатает его в мониторе порта.
while (client.connected())
{
if (client.available())
{
String line = client.readStringUntil('\r');
Serial.print(line);
}
}
Запрос от клиента помечен символом новой строки. Дойдя до этого символа, сервер должен отправить обратно веб-страницу, а затем выйти из цикла while() при помощи оператора break.
if (line.length() == 1 && line[0] == '\n')
{
client.println(prepareHtmlPage());
break;
}
Весь этот процесс завершается закрытием соединения с клиентом.
client.stop();
Скетч целиком
Ниже весь этот скетч представлен в полном виде:
#include <ESP8266WiFi.h>
const char* ssid = "********";
const char* password = "********";
WiFiServer server(80);
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.printf("Connecting to %s ", ssid);
// "Подключение к "
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" connected");
// " подключено"
server.begin();
Serial.printf("Web server started, open %s in a web browser\n", WiFi.localIP().toString().c_str());
// "Веб-сервер запущен, открываем %s в веб-браузере"
}
// подготавливаем веб-страницу для отправки клиенту (браузеру):
String prepareHtmlPage()
{
String htmlPage =
String("HTTP/1.1 200 OK\r\n") +
"Content-Type: text/html\r\n" +
"Connection: close\r\n" + // после отправки ответа
// соединение будет закрыто
"Refresh: 5\r\n" + // автоматически обновляем
// страницу каждые 5 секунд
"\r\n" +
"<!DOCTYPE HTML>" +
"<html>" +
"Analog input: " + String(analogRead(A0)) +
"</html>" +
"\r\n";
return htmlPage;
}
void loop()
{
WiFiClient client = server.available();
// ждем подключения клиента (браузера):
if (client)
{
Serial.println("\n[Client connected]");
// "Клиент подключен"
while (client.connected())
{
// считываем запрос клиента (браузера) строчка за строчкой:
if (client.available())
{
String line = client.readStringUntil('\r');
Serial.print(line);
// ждем конца запроса, помеченного пустой строкой:
if (line.length() == 1 && line[0] == '\n')
{
client.println(prepareHtmlPage());
break;
}
}
}
delay(1); // даем браузеру время получить данные
// закрываем соединение:
client.stop();
Serial.println("[Client disonnected]");
// "Клиент отключен"
}
}
Запускаем скетч
Меняем в скетче строчки с ssid и password на SSID и пароль к своей точке доступа. Загружаем скетч на ESP8266 и открываем монитор порта. Сначала в мониторе порта должно появиться подтверждение того, что модуль подключен к точке доступа, а веб-сервер – запущен.
Connecting to sensor-net ........ connected
Web server started, open 192.168.1.104 in a web browser
Вводим в адресную строку браузера показанный IP-адрес. В результате должна появиться страница, обслуживаемая ESP8266.
Эта страница будет обновляться каждые 5 секунд. С каждым новым обновлением в мониторе порта должен появляться новый запрос от клиента:
[Client connected]
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 192.168.1.104
DNT: 1
Connection: Keep-Alive
[client disonnected]
Что дальше?
Этот скетч отчасти похож на «обратный» клиентский скетч – в том, из чего состоит протокол. Во-первых, он начинается с заголовка, содержащего информацию о коммуникации. Во-вторых, содержит информацию об одобренном типе контента (вроде text/html). В-третьих, сообщает, останется ли соединение открытым, когда монитор порта закончит показывать заголовок, или будет закрыто. В-четвертых, содержит идентификатор отправителя вроде User-Agent: Mozilla/5.0 (Windows NT 6.1). Также включает информацию о языке, IP-адресе и т.д.
Итого
Этот пример демонстрирует, что в настройке веб-сервера на базе ESP8266 нет ничего сложного. Такой сервер может принимать запросы от мощных устройств и программ вроде ПК и веб-браузера. По этой ссылке можно почитать о других классах вроде ESP8266WebServer, благодаря которым свой веб-серверный скетч можно сделать еще более функциональным.
Если вы хотите попробовать другой скетч, использующий класс сервера, обратите внимание на WiFiWebServer.ino, позволяющий включать/выключать GPIO-контакт прямо из браузера.
Полный список функций для работы с классом сервера смотрите по [ссылка этой ссылке].