Программирование ARM ESP-IDF: обзор технологии Captive Portal Sat, August 01 2026  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


ESP-IDF: обзор технологии Captive Portal Печать
Добавил(а) microsin   

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

[Основной принцип работы]

Большинство решений для captive portal в ESP-IDF работают по следующему сценарию:

1. Попытка подключения: при загрузке устройство пытается подключиться к сохраненной в энергонезависимой памяти (NVS) Wi-Fi сети в режиме станции (STA).
2. Запуск точки доступа: если подключение не удалось или данных нет, устройство переключается в режим точки доступа (SoftAP) и создает собственную Wi-Fi сеть.
3. Перехват трафика: запускается DNS-сервер, который отвечает на все запросы IP-адресом самого устройства. Это заставляет операционные системы (Android, iOS, Windows) распознать наличие captive portal и автоматически открыть окно для входа.
4. Настройка через веб-интерфейс: пользователь подключается к точке доступа устройства, его автоматически перенаправляет на встроенную веб-страницу. На этой странице он выбирает свой домашний Wi-Fi из списка и вводит пароль.
5. Сохранение и перезагрузка: введенные данные сохраняются в NVS, и устройство перезагружается, чтобы подключиться к указанной сети уже в режиме станции.

[Обзор доступных решений]

Вот несколько проверенных компонентов и примеров, которые можно использовать в проекте.

Название / Решение Ключевые особенности Способ установки / Примечания
Официальный пример ESP-IDF Базовый пример, демонстрирующий работу DNS и HTTP серверов для captive portal. Хорошая отправная точка для понимания принципов. Входит в состав ESP-IDF. Ищите в папке examples/ каталога установки ESP-IDF (например ~/esp/v5.4.1/esp-idf/examples/protocols/http_server/captive_portal/).
nordesems/esp-captive-portal Минималистичный компонент для перехвата запросов от всех основных ОС (iOS, Android, Windows). Требует только одного вызова функции и не имеет внешних зависимостей. Устанавливается через компонентный менеджер: idf.py add-dependency "nordesems/esp-captive-portal^1.0.0".
MichMich/esp-idf-wifi-provisioner Полноценный менеджер с автоматическим переключением между режимами, богатыми настройками через menuconfig (текст страниц, таймауты) и возможностью менять конфигурацию во время выполнения. Устанавливается через компонентный менеджер.
tuanpmt/esp_wifi_manager Очень функциональное решение с поддержкой нескольких сетей, веб-интерфейсом на Preact (~10КБ), REST API и даже BLE для настройки. Устанавливается через компонентный менеджер. Поддерживает mDNS для доступа по локальному имени.
Dwarf1er/esp-wifi-provisioning Решение на языке Rust, построенное на базе esp-idf-svc. Отличный вариант, если проект разрабатывается на Rust для ESP32. Устанавливается через cargo.

Выбор зависит от требований вашего проекта:

● Для обучения и простого проекта: начните с официального примера ESP-IDF. Он поможет разобраться в деталях реализации.
● Для быстрой интеграции минимального функционала: используйте nordesems/esp-captive-portal — он легковесен и максимально прост в подключении.
● Для типового IoT-продукта: отличным выбором будет MichMich/esp-idf-wifi-provisioner или tuanpmt/esp_wifi_manager. Они предоставляют готовый пользовательский интерфейс, надежную логику работы и гибкие настройки.
● Для проекта на Rust: стоит обратить внимание на esp-wifi-provisioning.

Все эти решения используют стандартные компоненты ESP-IDF и предоставляют удобный способ внедрить удобную настройку Wi-Fi в ваше устройство.

[Запуск стандартного http_server/captive_portal]

Здесь по шагам описан процесс запуска официального примера ESP-IDF из каталога ~/esp/v5.4.1/esp-idf/examples/protocols/http_server/captive_portal/.

Шаг 1. Скопируйте пример в папку с вашими проектами (например, это папка ~/myproj).

cp -r ~/esp/v5.4.1/esp-idf/examples/protocols/http_server/captive_portal ~/myproj

Шаг 2. Выберите целевой процессор для проекта (например ESP32-S3).

cd ~/myproj/captive_portal
. $HOME/esp/v5.4.1/esp-idf/export.sh
idf.py set-target esp32s3

Шаг 3. Настройте проект (командой idf.py menuconfig - опционально).

При необходимости вы можете изменить параметры точки доступа и портала через меню конфигурации. Обычно они находятся в разделе Example Configuration. Запустите конфигуратор командой:

idf.py menuconfig

Перейдите в раздел Example Configuration. Здесь вы сможете настроить параметры точки доступа.

example app Captive Portal menuconfig options

Шаг 4. Сборка и прошивка проекта.

idf.py build flash monitor -p /dev/ttyACM0

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

example app Captive Portal browser

[Проблема Captive Portal на некоторых OS]

На устройстве Android при подключении к точке доступа esp32_ssid автоматически открылся браузер со стартовой страницей:

ESP Captive Portal
Hello World, this is ESP32!

Но на операционной системе Kubuntu 24.04 при подключении к точке доступа браузер не запустился, пришлось вручную вбивать в строке адреса http://192.168.4.1, только после этого открылась та же страница. То же самое на Ubuntu 24.04.4 LTS. Почему?

Наблюдаемое поведение связано не с ошибкой в вашем ESP32, а с различиями в том, как операционные системы и браузеры обнаруживают captive-порталы. Android настроен на автоматическое открытие страницы входа, а Kubuntu — нет. Вот почему это происходит.

Когда Android подключается к новой Wi-Fi сети, он автоматически отправляет запрос на специальный проверочный URL-адрес, например http://connectivitycheck.gstatic.com/generate_204.

Ожидаемый ответ: если сеть имеет доступ в интернет, этот URL должен вернуть HTTP-статус `204 No Content`.

Обнаружение портала: ваш ESP32 перехватывает этот запрос (так как он является шлюзом для этой сети) и возвращает не `204`, а либо страницу входа (код `200`), либо перенаправление (код `302`) на страницу `http://192.168.4.1`.

Реакция системы: Android распознает этот неожиданный ответ как сигнал о том, что за этим Wi-Fi скрывается captive-портал, и автоматически открывает браузер для прохождения аутентификации.

Почему Kubuntu не делает этого автоматически: ваша система Kubuntu, скорее всего, использует NetworkManager с окружением рабочего стола KDE Plasma. Механизм автоматического открытия порталов в таких дистрибутивах работает иначе и часто менее надежно.

Основная причина в том, как работает проверка соединения в Kubuntu:

1. Проверочный URL: вместо generate_204 ваша система может использовать другой URL для проверки интернета, например http://connectivity-check.ubuntu.com/ (для Ubuntu) или специальный .txt-файл для вашего дистрибутива.

2. Проблема с перехватом: некоторые версии NetworkManager, особенно в связке с KDE, при обнаружении портала пытаются открыть не IP-адрес шлюза (192.168.4.1), а тот же самый проверочный URL-адрес, с которым возникла проблема. Так как ESP32 часто настроен на перехват и перенаправление только определенных, "стандартных" URL-адресов (например, `generate_204`), он может не обработать запрос к `connectivity-check.ubuntu.com` должным образом. В итоге, проверка соединения не запускает автоматическое открытие браузера.

Кроме того, плазма-апплет KDE может использовать для открытия портала URL, который оканчивается на `.txt` (например, для Arch Linux — `https://ping.archlinux.org/nm-check.txt`). Многие реализации серверов для captive-порталов, включая ваш ESP32, не обрабатывают перенаправления для запросов к `.txt`-файлам так, как для обычных веб-страниц, что также мешает автоматическому открытию.

Как это исправить в Kubuntu. Проблема на стороне вашей ОС, и ее можно решить несколькими способами.

1. Ручное открытие: способ, который вы уже пробовали — вручную ввести в браузере адрес http://192.168.4.1 — является самым простым и универсальным решением.

2. Скрипт NetworkManager (рекомендуемое решение): можно создать скрипт, который будет автоматически открывать браузер на ссылке `http://192.168.4.1`, как только NetworkManager обнаружит состояние `PORTAL`. Это стандартное решение для Linux.

Как это сделать:

● Создайте файл скрипта, например, с помощью команды:

sudo nano /etc/NetworkManager/dispatcher.d/90-open_captive_portal

● Вставьте в этот файл следующий код (это адаптированная версия скрипта с [Arch Wiki](https://wiki.archlinux.org/title/NetworkManager#Captive_portals)):

#!/bin/sh -e
# Скрипт для обработки событий NetworkManager

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

if [ -x "/usr/bin/logger" ]; then
logger="/usr/bin/logger -s -t captive-portal"
else logger=":"
fi
wait_for_process() {
PNAME=$1
while [ -z "$(/usr/bin/pgrep $PNAME)" ]; do
sleep 3
done
}
start_browser() {
local user="$1"
local display="$2"
export DISPLAY="$display"
wait_for_process nm-applet
export XAUTHORITY="/home/$user/.Xauthority"
$logger "Запуск браузера для пользователя '$user' с дисплеем '$display' для входа в captive-портал"
# Открываем IP-адрес шлюза, который почти всегда является адресом портала
sudo -u "$user" --preserve-env=DISPLAY,XAUTHORITY -H xdg-open http://192.168.4.1 2>&1 > /dev/null
}

case "$2" in
connectivity-change)
$logger -p user.debug "Скрипт запущен из-за изменения подключения: $CONNECTIVITY_STATE"
if [ "$CONNECTIVITY_STATE" = "PORTAL" ]; then
who | awk '$NF ~ /\(:[0-9]+\)/ { print $1 " " substr($NF, 2, length($NF)-2) };' | \
while read user display; do
start_browser $user $display || $logger -p user.err "Не удалось \
для пользователя: '$user' дисплей: '$display'"
done
fi
;;
*)
exit 0
;;
esac

● Сделайте файл исполняемым:

sudo chmod +x /etc/NetworkManager/dispatcher.d/90-open_captive_portal

● Перезапустите NetworkManager или перезагрузите систему:

sudo systemctl restart NetworkManager

После этого, при подключении к вашему ESP32, браузер должен открываться автоматически.

Заключение: ваш ESP32 работает корректно, автоматически открывая портал для Android. Отсутствие такой же реакции в Kubuntu — особенность его системы обнаружения порталов. Создание простого скрипта-обработчика NetworkManager решит эту проблему и сделает работу с порталом на Linux такой же удобной, как на Android.

[Ссылки]

1. ESP-IDF HTTP Server.

 

Добавить комментарий


Защитный код
Обновить

Top of Page