В уроке 19 мы написали проект, который обеспечивает соединение с точкой доступа. То есть мы настроили наш модуль для работы по беспроводной сети в режиме станции. Только при условии исчезновения соединения с точкой доступа вследствие временного отключения последней или из-за каких-то других причин нам пришлось столкнуться с рядом трудностей, хотя с помощью неких костылей они всё же были преодолены, но это не совсем так, как хотелось бы. Поэтому на данном уроке мы постараемся немного усовершенствовать наш проект, так сказать, заставить нашу станцию быть немного умнее.
Схема остаётся такая же — отладочная плата, подключенная к USB компьютера
И проект мы также сделаем из проекта того же урока с именем WIFI_STA и назовём его WIFI_STA_SMART.
Откроем наш проект в Espressif IDE и в функции app_main файла main.c удалим бесконечный цикл совсем вместе с телом.
Вот эта переменная нам также не потребуется
wifi_ap_record_t info;
Создадим цикл событий по умолчанию
Перейдём в файл wifi.c и в объявлении функции инициализации wifi_init_sta добавим возвращаемый параметр
esp_err_t wifi_init_sta(void)
Поправим также и прототип в заголовочном файле.
В теле данной функции объявим переменную такого же типа
Дальнейший код в теле удалим совсем, так как изменений будет очень много и легче его заново написать.
Функцию event_handler удалим вместе с телом.
Вот эти глобальные вещи также удалим
static int s_retry_num = 0;static EventGroupHandle_t s_wifi_event_group;#define WIFI_CONNECTED_BIT BIT0#define WIFI_FAIL_BIT BIT1
Сегодня мы будем работать с семафором, а не с событиями.
Объявим глобальный семафор, назначение которого мы узнаем позже
В функции wifi_init_sta проверим существование нашего семафора
А если мы не выйдем из-за какой-нибудь ошибки, то вернём успешный статус
Выше добавим функцию, которая будет запускать нашу сеть
Вызовем её в функции wifi_init_sta
Объявим глобальную переменную, которая будет считать количество сетевых интерфейсов
Выше добавим функцию, останавливающую соединение, в которой пока только уменьшим на 1 количество сетевых интерфейсов
В функции wifi_init_sta зарегистрируем данную функцию в качестве обработчика событий
Выше функции net_start добавим функцию в форме указателя, которая будет запускать беспроводной модуль
Объявим и проинициализируем переменную типа структуры управления настройками WiFi, такими так буфер RX/TX, структура WiFi NVS и т. д, после чего инициализируем WiFi данными настройками
Объявим глобальный указатель на контейнер с информацией об интерфейсе
В функции net_start вызовем функцию wifi_start присвоив указатель на контейнер нашему указателю
В функции wifi_start объявим указатель на символьный массив для хранения текстового описания сетевого интерфейса
Объявим переменную типа структуры для хранения свойств интерфейса и проинициализируем её параметрами по умолчанию с помощью специального макроса, а затем текстовое описание дескриптора дополним именем нашего модуля, взятого из массива TAG и присвоим полю обратно
Назначим интерфейсу приоритет
Инициализируем интерфейс WiFi
Освободим память, зарезервированную под символьный массив
Установим обработчики по умолчанию
У нас будет отдельный обработчик для завершения соединения.
Поэтому выше добавим функцию для данного обработчика, а также функцию для обработчика событий получения адреса
Вернемся в функцию wifi_start и зарегистрируем наши обработчики
В качестве хранилища установим память
В файле Kconfig.projbuild внизу добавим пункт для выбора способа сканирования сети
Также добавим пункты для выбора методов сортировки имён точек доступа, установки порога мощности, режима порога и выбора метода шифрования
В конфигураторе выберем тип шифрования
Пункт ESP_MAXIMUM_RETRY можно удалить.
Сохраним конфигурацию и пересоберём проект.
Теперь в файле wifi.c добавим макросы, которые будут зависеть от настроек в конфигураторе
В функции wifi_start объявим и проинициализируем переменную типа структуры для свойств станции
Отобразим попытку подключения в терминале, взяв имя точки доступа из поля структуры
Установим режим станции, нормальный режим работы WiFI без энергосбережения и применим конфигурационные установки для нашей станции
Запустим станцию, попытаемся соединиться с точкой доступа и возвратим интерфейс
В функции-обработчике on_got_ip получим указатель на структуру события
Выше добавим функцию, которая будет узнавать тип интерфейса
Вернемся в функцию on_got_ip и отобразим в терминале имя интерфейса, и, если это интерфейс типа IPV4, то отобразим и адрес
Объявим глобальный указатель на сетевой адрес
Вернемся в функцию on_got_ip, скопируем информацию в нашу переменную из поля структуры, зажжем светодиод и отдадим семафор
В функции-обработчике on_wifi_disconnect погасим светодиод и выведем о попытке разрыва соединения соответствующее сообщение в терминал
Попытаемся заново соединиться с точкой доступа, если невозможно, то выйдем из функции, в другом случае отобразим код ошибки, вдруг у нас какая-то другая ошибка
В функции net_start увеличим количество интерфейсов на 1
И здесь же мы создаём счётный семафор с количеством элементов, равным количеству интерфейсов
Теперь займёмся остановкой интерфейса, для чего выше добавим ещё одну функцию
Также ещё выше добавим функцию, которая будет вычислять интерфейс по имени
Здесь всё просто и объяснений, я думаю, никаких не требуется.
Вернёмся в функцию wifi_stop и получим наш интерфейс
Разрегистрируем обработчики событий
Попытаемся остановить WiFi
Деинициализируем WiFi
Очистим обработчики по умолчанию и уничтожим соответствующие объекты
Уничтожим объект esp_netif
Очистим ссылку на интерфейс
Перейдём в функцию net_stop и вызовем только что написанную нами функцию
Осталось нам только завершить кое-какие процедуры в функции инициализации wifi_init_sta. Сначала попытаемся забрать наши семафоры
В данном цикле мы будем находиться до тех пор, пока не заберём все семафоры, то есть пока все наши интерфейсы не соединятся.
Зажжем светодиод и объявим указатель на интерфейс
Объявим переменную типа структуры для сетевого адреса нашей станции
Добавим цикл с количеством итераций, равных количеству интерфейсов, в котором получим дескриптор очередного интерфейса
Отобразим в терминале информацию о соединении
В функции app_main файла main.c добавим возврат параметра в вызов функции инициализации wifi
ret = wifi_init_sta();
Ниже выведем в терминал код ошибки
Также произведём инициализацию сетевого интерфейса немного выше
Ну и наконец-то пришло время нам всё это проверить.
Прошьём контроллер и посмотрим информацию в терминале
Отлично! Вроде везде нолики, значит ошибок возвращённых нет.
Проверим пинг
Теперь попробуем отключить точку доступа на какое-то время.
Попытки соединиться с точкой доступа теперь происходят постоянно
Включим точку доступа и увидим, что соединение снова удачно установилось
Итак, на данном уроке нам удалось усовершенствовать нашу WiFi-станцию, в результате чего мы добились того, что нам уже не нужно в бесконечном цикле постоянно вызывать функцию инициализации, если превышено количество попыток соединения.
Всем спасибо за внимание!
Оригинал статьи находится здесь.
<<Предыдущий урок | Следующий урок>>
Недорогие отладочные платы ESP32 можно купить здесь
Видео в RuTube
Видео в Дзен
Видео в Youtube