Свой веб-сервер на ESP32: управление из браузера

Превращаем плату в маленький сайт, которым управляют с телефона.

Веб-сервер на ESP32 — программа, которая слушает входящие HTTP-запросы и отдаёт HTML-страницу, позволяя управлять устройством прямо из браузера.

Идея

Плата подключена к домашней сети и имеет IP-адрес. Если на ней запустить сервер, можно открыть этот адрес в браузере телефона и нажимать кнопки — включать свет, читать датчики. Не нужно отдельное приложение: интерфейс — обычная веб-страница.

Минимальный сервер на сокетах

import socket
from machine import Pin

led = Pin(2, Pin.OUT)

html = """<!DOCTYPE html>
<html><head><title>Умный дом</title></head>
<body><h1>Управление LED</h1>
<a href="/on">Включить</a> | <a href="/off">Выключить</a>
</body></html>"""

s = socket.socket()
s.bind(("0.0.0.0", 80))
s.listen(5)
print("Сервер запущен")

while True:
    conn, addr = s.accept()
    request = conn.recv(1024).decode()
    if "/on" in request:
        led.on()
    elif "/off" in request:
        led.off()
    conn.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")
    conn.send(html)
    conn.close()

Открыв в браузере http://IP-платы/, вы увидите страницу со ссылками, а нажатия будут включать и выключать светодиод.

Разбор пути запроса — на чистом Python

Логику «какой путь запросили» можно проверить в браузере без железа:

def handle(request_line):
    # request_line вида: GET /on HTTP/1.1
    parts = request_line.split()
    path = parts[1] if len(parts) > 1 else "/"
    if path == "/on":
        return "LED включён"
    if path == "/off":
        return "LED выключен"
    return "Главная страница"

for line in ["GET /on HTTP/1.1", "GET /off HTTP/1.1", "GET / HTTP/1.1"]:
    print(line, "->", handle(line))

Вывод:

GET /on HTTP/1.1 -> LED включён
GET /off HTTP/1.1 -> LED выключен
GET / HTTP/1.1 -> Главная страница

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

Сервер создаёт сокет, привязывает его к порту 80 и «слушает». Когда браузер открывает адрес, он шлёт текстовый HTTP-запрос (первая строка — метод и путь). accept() принимает соединение, recv() читает запрос, мы анализируем путь, выполняем действие и отправляем ответ: статусную строку, заголовки и тело-HTML. Браузер рисует страницу. Всё это синхронно — пока обрабатываем один запрос, другие ждут.

Частые ошибки

  • Не закрывать соединение. Без conn.close() новые клиенты зависнут.
  • Блокировка на одном клиенте. Простой сервер обслуживает по одному; для нескольких нужен асинхронный подход.
  • Сырые < в HTML-строке. Внутри Python-строки это нормально, но в учебных примерах теги экранируют для показа.

Итог

  • ESP32 может сам отдавать веб-страницу — управление без отдельного приложения.
  • Сервер слушает порт 80, принимает запрос, разбирает путь, отвечает HTML.
  • Действие выбирают по пути запроса (/on, /off).
  • Каждое соединение нужно закрывать; простой сервер однопоточный.
Проверьте себя
1. Зачем поднимать веб-сервер прямо на ESP32?
AЧтобы плата работала быстрее
BЧтобы управлять устройством из браузера без отдельного приложения
CЧтобы отключить Wi-Fi
DЭто обязательно для любого кода
2. На каком порту обычно слушает HTTP-сервер?
A22
B80
C443
D8080 всегда
3. Как сервер понимает, какое действие выполнить?
AПо цвету страницы
BПо пути в строке запроса (например /on или /off)
CПо времени суток
DПо IP роутера