Найти в Дзене
Паяльник и код

ESP32 (ESP8266) асинхронный веб-сервер. Версия 3

Рассмотрим программу скелет для микроконтроллера ESP32 (ESP8266), которую в дальнейшем можно будет использовать для своих проектов. Программа выполняет условия: 1. Выбор WiFi сети
2. Подключение к WiFi сети
2. Управление через веб сервер
3. Одновременный доступ с разных устройств
4. Текущее состояние в реальном времени отображается на всех устройствах
5. Проверка подключения к сети Для примера будем включать/отключать встроенный светодиод на плате ESP32-C3 supermini pro и регулировать его яркость через веб сервер Рассмотрим части кода, которые внесли изменения по сравнению с предыдущими статьями: Первое это обновление библиотек асинхронного веб-сервера. Теперь всё находится по адресу Инициализация библиотек происходит в зависимости от платы #include <Arduino.h>
#if defined(ESP32) || defined(LIBRETINY)
#include <AsyncTCP.h>
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_R

Рассмотрим программу скелет для микроконтроллера ESP32 (ESP8266), которую в дальнейшем можно будет использовать для своих проектов. Программа выполняет условия:

1. Выбор WiFi сети
2. Подключение к WiFi сети
2. Управление через веб сервер
3. Одновременный доступ с разных устройств
4. Текущее состояние в реальном времени отображается на всех устройствах
5. Проверка подключения к сети

Для примера будем включать/отключать встроенный светодиод на плате ESP32-C3 supermini pro и регулировать его яркость через веб сервер

Синий светодиод
Синий светодиод

Рассмотрим части кода, которые внесли изменения по сравнению с предыдущими статьями:

Первое это обновление библиотек асинхронного веб-сервера. Теперь всё находится по адресу

GitHub - ESP32Async/ESPAsyncWebServer: Async Web Server for ESP32

Инициализация библиотек происходит в зависимости от платы

#include <Arduino.h>
#if defined(ESP32) || defined(LIBRETINY)
#include <AsyncTCP.h>
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#elif defined(TARGET_RP2040) || defined(TARGET_RP2350) || defined(PICO_RP2040) || defined(PICO_RP2350)
#include <RPAsyncTCP.h>
#include <WiFi.h>
#endif
#include <ESPAsyncWebServer.h>

Т.е. это или ESP32, или ESP8266, или семейство Pico. Последних я что-то не встречал с wifi модулем

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

Пояснение

Например, в нашем случае есть два параметра. Вкл/выкл светодиод и задать его яркость

<p><big>Лампочка1:</big>&nbsp;&nbsp;<input type="checkbox" onchange="update_value(this)" id="value_1"></p>
<p><big>Яркость:</big>&nbsp;&nbsp;<input type="range" onchange="update_value(this)" id="value_2" min="0" max="255" value="255"></p>

Имена id="value_1" и id="value_2"

На сервере функция state передаёт на клиент строку с параметрами, разделенную точкой запятой

server.on("/state", HTTP_GET, [] (AsyncWebServerRequest *request) {
String s;
if(ledState == LOW)s+="1;";
else s+="0;";
s+=String(brightness)+";";
request->send(200, "text/plain", s);
});

На клиенте обрабатывается эта строка

function set_value(inputString) {
const ArrayValue = inputString.split(";");
if (ArrayValue[ArrayValue.length - 1] == "") {
ArrayValue.pop();
}
if(ArrayValue[0] == "1") document.getElementById("value_1").checked = true;
else document.getElementById("value_1").checked = false;
document.getElementById("value_2").value = resultArray[1];
}

Каждый элемент кладется в массив. Потом по порядковому номеру присваиваются значения

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

setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
set_value(this.responseText);
}};
xhttp.open("GET", "/state", true);
xhttp.send();
}, 1000);

Дальше если на клиенте происходит изменения какого-нибудь параметра, то на сервер уходит строка

function update_value(element) {
var xhr = new XMLHttpRequest();
var s = "/update?value=";
if (document.getElementById("value_1").checked) s= s + "1;";
else s= s + "0;";
s = s + document.getElementById("value_2").value+";";
xhr.open("GET", s, true);
xhr.send();
}

Которая обрабатывается уже на стороне сервера

server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
if (request->hasParam("value")) {
inputMessage = request->getParam("value")->value();
int startIndex = 0;
int endIndex = 0;
endIndex = inputMessage.indexOf(';', startIndex);
if ((inputMessage.substring(startIndex, endIndex)).toInt() == 1) ledState = LOW;
else ledState = HIGH;
digitalWrite(LED, ledState);
startIndex = endIndex + 1;
endIndex = inputMessage.indexOf(';', startIndex);
brightness = (inputMessage.substring(startIndex, endIndex)).toInt();
if(ledState == LOW) analogWrite(LED,255-brightness);
else analogWrite(LED,255);
}
else {
inputMessage = "No message sent";
}
request->send(200, "text/plain", "OK");
});

Таким образом, чтоб увеличить количество элементов на странице сервера добавляем их на страницу и увеличиваем на значения этих элементов в строке ответа и запроса.

Масштабируемость проекта стала легче

Остальные части кода остались, как и в предыдущих версиях

Исходный код

ESPAsyncWebServer.zip — Яндекс Диск
-3