Русские Блоги
Подробное объяснение режима работы AP и STA беспроводного модуля Wifi
Подробное объяснение режима работы AP и STA беспроводного модуля Wifi
Модуль Wi-Fi включает в себя два режима работы AP и STA. Благодаря поддержке этих двух режимов продукт беспроводной передачи изображения может реализовать функцию отправки одного и получения большего количества. Давайте начнем с основных концепций AP и STA.
1. Основные понятия AP и STA
AP: точка беспроводного доступа является создателем беспроводной сети и центральным узлом сети. Беспроводной маршрутизатор, используемый в обычных домах или офисах, является точкой доступа.
STA: каждый терминал, подключенный к беспроводной сети (например, ноутбуки, КПК и другое пользовательское оборудование, подключенное к сети), можно назвать сайтом.
2. Описание режимов работы AP и STA
1. Работа в режиме AP
Работая в режиме AP, мобильные телефоны, PAD, компьютеры и другие устройства могут быть напрямую подключены к модулю, который может легко управлять пользовательским оборудованием (Рисунок 2-1).
Рисунок 2-1 Работа в режиме AP
2. Работа в режиме STA
Это основной сетевой метод, состоящий из AP и множества STA, как показано на следующем рисунке. Характеристика состоит в том, что AP находится в центральном положении, и взаимная связь между STA завершается посредством пересылки AP. В этом режиме модуль WIFI работает в режиме STA (CLIENT). При правильных настройках данные COM и данные сети WIFI конвертируются друг в друга. (Рисунок 2-2)
Записки IT специалиста
Работа оборудования Mikrotik в режиме беспроводной станции (клиента)
- Автор: Уваров А.С.
- 04.11.2021
Режим беспроводной станции (клиента) используется в Mikrotik гораздо реже, чем режим точки доступа, но часто, когда возникает в этом потребность, администраторы сталкиваются с различного рода затруднениями. Во многом это происходит из-за недостаточного понимания особенностей работы беспроводного оборудования в данном режиме. Поэтому в рамках данной статьи мы решили познакомить читателей с теорией и практикой применения роутеров данного производителя в качестве беспроводной станции и ответить на часто задаваемые вопросы.
Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном курсе по администрированию MikroTik. Автор курса, сертифицированный тренер MikroTik Дмитрий Скоромнов, лично проверяет лабораторные работы и контролирует прогресс каждого своего студента. В три раза больше информации, чем в вендорской программе MTCNA, более 20 часов практики и доступ навсегда.
Начнем с того, что с беспроводным оборудованием далеко не все так просто. Существует набор стандартов IEEE 802.11, более известный как Wi-Fi, который описывает требования для беспроводных сетей передачи данных и наличие его поддержки гарантирует совместимость устройств различных производителей. Проще говоря если у вас на точке доступа и на клиентском устройстве написано, что они поддерживают стандарт 802.11n, то они будут работать вместе, иначе — нет.
На самом деле устройства поддерживают не один, а целую группу стандартов для целей обратной совместимости и поэтому можно с уверенностью говорить, что любое купленное устройство с заявленной поддержкой Wi-Fi будет работать с другим таким же устройством в рамках протоколов 802.11.
Но кроме обязательной поддержки стандарта многие производители реализуют собственные проприетарные решения для беспроводных устройств, при этом мы даже не будем касаться таких протоколов как Nstream и NV2, достаточно несоответствующих стандарту возможностей в рамках протокола 802.11. Следует понимать, что такие возможности поддерживаются только оборудованием определенного производителя и будут работать с другими устройствами. Это не хорошо и не плохо, но вы всегда должны четко знать, что именно из предоставляемых оборудованием функций соответствует стандарту 802.11, а что добавлено от производителя.
И, наконец, даже у одного производителя могут быть различные линейки или режимы работы беспроводного оборудования, имеющие ограниченную совместимость даже с собственными решениями. У Mikrotik это программный контроллер беспроводной сети CAPsMAN. И если вы применяете подобные решения, то также требуется принимать во внимание их особенности и ограничения.
Режимы работы беспроводной станции в Mikrotik
Оборудование Mikrotik предоставляет достаточно богатый набор режимов для беспроводной станции, часть из них являются стандартными, другая часть содержит проприетарные расширения, поэтому мы подготовили небольшую таблицу совместимости, позволяющую быстро оценить применимость того или иного режима.
802.11 | RouterOS | CAPsMAN | |
---|---|---|---|
station | + | + | + |
station-bridge | + | ||
station-pseudobridge | + | + | + |
station-pseudobridge-clone | + | + | + |
station-wds | + |
Колонка 802.11 показывает возможность работы беспроводной станции со стандартным оборудованием других производителей, RouterOS — совместимость с точками доступа Mikrotik в обычном режиме, а CAPsMAN — в режиме программного контроллера. Совместимость с протоколами Nstream и NV2 нами не рассматривается, так как далеко выходит за рамки данной статьи.
Режим station
Самый простой режим работы, при котором беспроводной модуль устройства выполняет роль обычного Wi-Fi адаптера, подключаясь к точке доступа как клиентское устройство. Режим полностью совместим с 802.11, что позволяет подключаться клиентом к оборудованию других производителей, также поддерживается работа с точками доступа управляемыми CAPsMAN.
Но в данном режиме беспроводной интерфейс не является прозрачным для L2 трафика, даже если вы поместите его в мост и объединить сети на канальном уровне таким образом не получится. Для того, чтобы устройства сегмента LAN2 на схеме ниже могли получить доступ к сегменту LAN1 или интернету вам потребуется маршрутизатор (роутер) один из сетевых интерфейсов которого будет работать в режиме беспроводной станции.
Какие-либо сложности при настройке данного режима отсутствуют, вам нужно указать SSID сети, рабочую частоту (канал), ширину канала и режим работы. Для поиска доступных к подключению беспроводных сетей можно воспользоваться кнопкой Scan, параметры безопасности задаются выбором соответствующего Security Profile, также не забудьте указать режим использования частотного диапазона в Frequency Mode, наиболее правильным решением будет использование варианта regulatory-domain — использование ограничений в соответствии с национальными требованиями. Здесь же указываем нужный региональный шаблон, для России сегодня это russia3.
Для чего можно использовать данный режим? Прежде всего для подключения к оборудованию сторонних производителей, например, если провайдер предоставляет вам доступ по радиоканалу или вам нужно подключиться к публичной сети. Второй вариант — подключение к собственному оборудованию Mikrotik в тех случаях, когда требуется разделить подключаемые сегменты, наличие маршрутизатора между сетями позволяет гибко настроить ограничения и фильтровать по заданным правилам проходящий трафик.
Режим station-bridge
Это проприетарный режим прозрачной станции, поддерживаемый только точками доступа Mikrotik и несовместимый с CAPsMAN. Основным ее отличием от простой станции является поддержка режима моста L2 для трафика устройств находящихся за станцией, в данном случае вы можете добавить беспроводной интерфейс в мост и все устройства сегмента LAN2 получат прозрачный доступ на канальном уровне в сегмент LAN1 как-бы находясь с ними в единой сети.
Фактически беспроводной канал используется в режиме моста, но со стандартными настройками точки доступа, которая может продолжать принимать подключения от обычных клиентов. Данный режим обычно используется для объединения собственных сетей, когда иного варианта доступа, нежели беспроводной канал, нет.
Каких-либо особенностей или отличий в настройках беспроводного модуля от режима station нет.
Режим station-pseudobridge
Достаточно интересный режим псевдопрозрачного моста, к плюсам которого можно отнести совместимость с оборудованием сторонних производителей и CAPsMAN. Но на этом плюсы заканчиваются, далее идут многочисленные и очень серьезные ограничения. В режиме псевдомоста станция заменяет исходные MAC-адреса кадров на собственный адрес и ведет таблицу сопоставления MAC — IPv4 для обратной трансляции, для протоколов отличных от IPv4 выполнить сопоставление невозможно и для обратной замены используется MAC-адрес первого полученного кадра с отличным от IPv4 содержимым.
Таким образом прозрачный доступ на канальном уровне будет иметь только одно устройство, чей кадр был получен первым, остальные узлы сети будут иметь ограниченный доступ на уровне служб IPv4.
Производитель советует по возможности избегать этого режима и использовать только тогда, когда иные возможности создания L2 моста недоступны или за станцией находится только одно сетевое устройство. На практике данный режим следует использовать исключительно для прозрачного доступа единственного экземпляра оборудования в беспроводную сеть на оборудовании стороннего производителя или управляемую CAPsMAN при отсутствии иных возможностей подключения.
Режим station-pseudobridge-clone
Еще один вариант псевдопрозрачного моста, но в данном случае станция заменяет MAC-адреса источника на адрес одного из узлов сети, который либо задан в настройках, либо был получен из первого перенаправленного кадра. Со стороны точки доступа это будет выглядеть как будто к ней непосредственно присоединился данный узел. Фактически данный режим дает возможность прозрачного моста для единственного выбранного устройства, а возможность явно задать нужный MAC-адрес исключает элемент случайности.
Для указания MAC-адреса клиента перейдите на закладку Advanced беспроводного интерфейса и заполните поле Station Bridge Clone MAC.
Используя данный режим будьте осторожны, так как у вас появляется два устройства с одинаковым MAC-адресом и при одновременном подключении их к сети вы можете получить самые неожиданные последствия.
Режим station-wds
Также является проприетарным и поддерживается только точками доступа под управлением RouterOS, не работает с CAPsMAN. Мы сейчас не будем подробно разбирать режим WDS (Wireless Distribution System) — это устаревшая технология расширения покрытия беспроводной сети, в данном случае от WDS сохранилось больше название и общие принципы, сама технология значительно переработана Mikrotik.
Это единственный режим, поддержку которого нужно включать со стороны точки доступа. Но в чем его преимущества и какие возможности он дает? Основное отличие данного режима в том, что между точкой доступа и беспроводной станцией создается соединение точка-точка и отдельный WDS-интерфейс для него. Это позволяет точке раздельно направлять данные к WDS-клиентам, а наличие отдельных интерфейсов позволяет использовать фильтрацию трафика, маршрутизацию и т.д. и т.п. При этом соединение остается прозрачным для L2 трафика, но добавляет возможность работы с Bridge Firewall.
Для использования режима WSD его потребуется включить на точке доступа, для этого на закладке WDS беспроводного интерфейса установите параметр WDS Mode в dynamic для динамического создание WDS-интерфейсов, или static если вы будете создавать их вручную. Опция WDS Default Bridge определяет мост, к которому по умолчанию будут подключаться WDS-интерфейсы.
Со стороны станции настройки ничем не отличаются от стандартных. Но теперь при подключении станции на точке доступа будет автоматически создан новый интерфейс и включен в указанный в настройках мост.
При ручном создании WDS интерфейса вам следует перейти в Wireless — Wi-Fi Interfaces и нажатием на «плюс» создать новый WDS, в настройках которого на одноименной вкладке в поле Master Interface следует выбрать желаемый беспроводной интерфейс, а в поле WDS Address следует указать MAC-адрес беспроводного интерфейса клиентской станции.
Говорить о практическом использовании режима station-wds можно долго, благодаря наличию отдельного сетевого интерфейса для каждого клиента вырисовываются перспективы построения достаточно сложных сетевых конфигураций. Но не забывайте о рациональности, не следует усложнять там, где это не нужно и если вам нужен просто беспроводной L2-мост, то лучше использовать station-bridge.
Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном курсе по администрированию MikroTik. Автор курса, сертифицированный тренер MikroTik Дмитрий Скоромнов, лично проверяет лабораторные работы и контролирует прогресс каждого своего студента. В три раза больше информации, чем в вендорской программе MTCNA, более 20 часов практики и доступ навсегда.
Wifi station что это
Artwork by Hanzheng Tang
В данной статье я хочу рассмотреть наиболее простые примеры для работы с сетью средствами SDK. При работе с сетью, SDK использует неблокирующее программирование. В связи с этим, программирование сводиться к написанию коллбек-функций, которые будут вызываться из SDK при наступлении того или иного события. Это затрудняет чтение и разбор алгоритма программы, поэтому в статье я всега стараюсь говорить, что за чем следует.
Статья по структуре будет напоминать предыдущую: «ESP8266: подключение, прошивка и работа с AT-командами», за тем исключением, что в этот раз все будет делаться с помощью программирования через ESP8266-NONOS-SDK.
Конфигурация WiFi сети будет, опять же, состоять из двух компонентов: а) точки доступа на роутере с прошивкой OpenWRT; б) и собственно ESP8266 выступающего в роли клиента. На стороне роутера запущен web-сервер для обслуживания ESP8266. Для передачи и получения данных от роутера, ESP8266 будет использовать GET — запросы.
В качестве «транспорта» для работы с TCP/IP я буду использовать штатный интерфейс espconn, который описан в ESP8266 Non-OS SDK API Reference.
Для захвата и анализа трафика между ESP8266 и точкой доступа на OpenWRT, я буду использовать программы tcpdump и Wireshark. Все примеры статьи используют SDK версии 2.1.0.
- Список используемой документации:
- ESP8266EX Resources | Espressif Systems Страница с доступными ресурсами по ESP8266 на сайте производителя.
- ESP8266 Non-OS SDK API Reference ESP8266 Non-OS SDK API Reference версия 2.2
- ESP8266 Low Power Solutions
- Статья Михаила Григорьева на хабре: Работа с ESP8266: Собираем компилятор и пишем первую прошивку
- Книга Kolban’s Book on ESP8266
- Если вы как и я НЕ учились по специальности «компьютерные сети», то вам скорее всего понадобиться какой-нибудь мануал с описанием разных сетевых протоколов. Я лично использую «В. Олифер, Н. Олифер «Компьютерные сети. Принципы, технологии, протоколы.», часть IV: Сети TCP/IP. Это недорогой понятный учебник без лишней воды.
- Создание базового проекта
- Установка WiFi соединения в режиме клиента
- Работа с TCP соединением используя espconn
- Использование режима энергосбережения «deep sleep»
- Реализация команды ping
- Получение даты и времени из сети по протоколу SNTP
Посмотреть исходники, сборочные файлы, скачать скомпилированные прошивки, можно с портала GITLAB https://gitlab.com/flank1er/esp8266_sdk_examples
1) Создание базового проекта
Для на начала нужно будет создать базовый проект, который мы будем постепенно развивать. Отталкиваться при этом будем от последнего проекта предыдущей статьи. Итак:
Создаем структуру каталогов:
Переходим в созданную директорию 06_basic_project, и в каталоге inc создаем пустой заголовочный файл «user_config.h«:
После этого копируем файл «espmissingincludes.h«:
В главной директории создаем Makefile следующего содержания:
Осталось добавить «main.c» c исходником простой мигалки:
После компиляции и прошивки, светодиод на плате должен начать мигать с интервалом одну секунду.
Если сравнивать данный пример с примерами из предыдущей статьи, то можно заметить, что код мигалки реализован через таймер. Кроме того, добавлены две новые функции: user_rf_cal_sector_set() и user_rf_pre_init(). Что это за функции? В самом начале документа к ESP8266 Non-OS SDK API Reference можно увидеть следующие строки:
Здесь говорится, что указанные функции должны быть добавлены в один исходник с user_init(). Самостоятельно вызывать их не надо, они вызываются из SDK. Код функций был взят примера ESP8266_NONOS_SDK/examples/IOT_Demo/user/user_main.c.
У функции user_rf_cal_sector_set() имеется описание:
- Функция user_rf_cal_sector_set() должна быть добавлена в приложение, но она НЕ должна вызываться. Её вызов происходит из самого SDK.
- Так как область системных параметров (четыре сектора флеш-памяти) уже используется, то параметры RF_CAL будут сохраняться в секторе заданом user_rf_cal_sector_set. Поскольку система не знает какой сектор является доступным, пользователю необходимо задать свободный сектор для хранения RF_CAL в функции user_rf_cal_sector_set.
- Если функцию user_rf_cal_sector_set() не была добавлена в приложение, компиляция закончится ошибкой на этапе линковки.
- Загрузите blank.bin для инициализации сектора хранящего параметры RF_CAL . Или загрузите esp_init_data.bin на флеш, когда система нуждается в инициализации или повторной калибровке параметров радио-модуля RF.
Думаю, не сложно заметить, что код из примера используется в вышеприведенной программе.
Итак, если светодиод на плате NodeMCU благополучно мигает и вопросов по коду больше нет, тогда переходим к установке WiFi соединения.
2) Установка WiFi соединения в режиме клиента
Как бы это не показалось странным (подводные камни, да), но первая функция которая нам понадобится для работы с wifi — это функция проверки статуса соединения wifi_station_get_connect_status():
wifi_station_get_connect_status()
Назначение функции Получить статус WiFi соединения ESP8266, работающего в режиме клиента, с точкой доступа. Прототип uint8 wifi_station_get_connect_status(void) Параметры Отсутствуют. Возвращаемое значение enum < STATION_IDLE = 0 , STATION_CONNECTING, STATION_WRONG_PASSWORD, STATION_NO_AP_FOUND, STATION_CONNECT_FAIL, STATION_GOT_IP >; Примечание В частном случае, если вы вызываете wifi_station_set_reconnect_policy для отключения автоматического переподключения (реконнекта), и при этом не вызываете wifi_set_event_handler_cb для установки обработчика изменения статуса WiFi соединения, то вызов функции wifi_station_get_connect_status() будет бесполезным и вы будет получать некорректный результат. ESP8266 Non-OS SDK API Reference
На основе функции wifi_station_get_connect_status() напишем функцию печати через UART статуса wifi-соединения, и добавим ее вызов в blink(). В целом программа будет выглядеть так:
Для наглядности я еще добавил печать IP-адреса в случае если ESP8266 устанавливает соединение с точкой доступа. Для получения IP используется функция wifi_get_ip_info(STATION_IF, &ipConfig):
wifi_get_ip_info
Назначение функции Получение структуры ip_info в режиме клиента или Soft-AP. Прототип bool wifi_set_ip_info( uint8 if_index, struct ip_info *info ) Параметры uint8 if_index: интерфейс для получения IP адреса: 0x00 для STATION_IF и 0х01 для SOFTAP_IF .
struct ip_info *info: указатель на возвращаемую структуру ip_info.Возвращаемое значение True: успешное выполнение;
False: ошибка при выполнении.Примечание Данное API доступно после инициализации, не вызывайте его из user_init(). ESP8266 Non-OS SDK API Reference
При этом структура ip_info определена в заголовочном файле ip_addr.h, и имеет следующий вид:
Макрос IP2STR для печати IP — определен там же:
Итак, после компиляции прошивки ESP8266, в терминале последовательного порта можно будет увидеть такую картинку:
Т.е. можно видеть, что esp8266 УЖЕ установила соединение с точкой доступа, без всяких телодвижений с нашей стороны.
КАК ТАКОЕ ВОЗМОЖНО?!
Здесь можно только предполагать. В прошлой статье я упоминал о подводном камне, когда прошивка esp_open_sdk начинает работать только после того как ESP8266 предварительно прошить прошивкой с интерпретатором АТ-команд. Теперь вспоминаем. Когда мы через этот интерпретатор устанавливаем соединение с точкой доступа, то после перезагрузки ESP8266, это соединение устанавливается уже автоматически. Т.е. на флешке УЖЕ хранится режим работы WIFI-модуля, SSID точки отступа и парольная фраза. Имея эту информацию, sdk автоматически при старте устанавливает соединение, вне зависимости от того, записан ли AT-интерпретатор или программа esp-open-sdk. Само-собой, в дальнейшем мы будем самостоятельно через функции SDK устанавливать соединение с нужной точкой доступа, но про этот нюанс забывать не стоит.
Печать статуса соединения с определенным интервалом не совсем корректный подход к работе c SDK. Более корректно будет использование wifi_set_event_handler_cb() для установки обработчика изменения статуса соединения:
wifi_set_event_handler_cb
Назначение функции Установка обработчика событий WiFi Прототип void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb) Параметры wifi_event_handler_cb_t cb : callback-функция Возвращаемое значение Отсутствует. Пример ESP8266 Non-OS SDK API Reference
Смысл обработчика событий WiFi состоит в том, что при любом изменении статуса WiFi-соединения вызывается данный обработчик. Именно в нём и следует размещать печать статуса соединения.
Теперь приводим программу к следующему виду:
В случае успешной компиляции и прошивки, в терминале мы должны получть следующую картинку:
Здесь у нас получается уже небольшой лог, по которому можно видеть, что после загрузки WiFi модуль сначала переходит в режим клиента, потом он по о всей видимости сканирует доступные точки доступа, затем устанавливает соединение с своей точкой доступа, и через DHCP получает IP адрес.
Теперь, когда мы представляем в каком состоянии изначально находится WiFi модуль, мы можем осуществить переподключение к нужной нам точке доступа. Для это нам понадобятся следующие функции SDK:
Функция подключения к точке доступа:
wifi_station_connect
Назначение функции Подключение WiFi модуля находящегося в режиме клиента (station) к точке доступа (AP). Прототип void wifi_station_clear_username (void) Параметры Отсутствуют. Возвращаемое значение True: успешное выполнение;
False: ошибка при выполнении.Примечание Если ESP8266 уже подключен к роутеру, то перед вызовом wifi_station_connect нужно будет вызвать функцию wifi_station_disconnect().
Вызов данной функции должен происходить после инициализации, а ESP8266 должен находится в режиме клиента (station).ESP8266 Non-OS SDK API Reference
Функция отключения от точки доступа:
wifi_station_disconnect
Назначение функции Отключение WiFi модуля находящегося в режиме клиента (station) от точки доступа (AP). Прототип void wifi_station_clear_username (void) Параметры Отсутствуют. Возвращаемое значение True: успешное выполнение;
False: ошибка при выполнении.Примечание Не вызывайте данную функцию в user_init(). Ее вызов должен происходить после инициализации, а ESP8266 должен находится в режиме клиента (station). ESP8266 Non-OS SDK API Reference
Функция установки режима работы WiFi модуля:
- uint8 opmode : режим работы WiFi модуля:
- 0x01 : Station mode;
- 0x02 : SoftAP mode;
- 0x03 : Station + SoftAP mode.
Функция задания массива настроек WiFi модуля в режиме клиента (station):
Если функция wifi_station_set_config вызывается из user_init() , тогда отпадает необходимость в последующем вызове wifi_station_connect . Подключение к точке доступа (AP) произойдет автоматически. В противном случае, последующий вызов wifi_station_connect будет необходим.
Как правило, station_config.bssid_set необходимо сбрасывать в 0, чтобы избежать проверки MAC адреса (BSSID) точки доступа. Иначе, подключение к точке доступа произойдет только при совпадении SSID и MAC адреса (BSSID).
где структура station_config определена в заголовочном файле user_interface.h и имеет следующий вид:
Процедура подключения к точке доступа в режиме клиента состоит из двух шагов: а) переход в режим клиента; б) установка структуры station_config. Структуру можно либо создать во время инициализации, заполнив нужные поля своими значениями, либо получить текущую структуру с помощью функции wifi_station_get_config() и изменив нужные поля, передать её обратно в ESP8266.
С учетом всего вышесказанного, окончательный вариант user_init() для установки соединения с точной доступа, примет следующий вид:
При этом, в заголовочном файле user_config.h должны находится данные для подключения к точке доступа:
3) Работа с TCP соединением используя espconn
После того, как мы установили соединение с точкой доступа, следует разобраться с установкой TCP-соединения, чтобы иметь возможность передавать и принимать данные с сервера.
Работа с TCP соединением в SDK ESP8266 осуществляется с помощью механизма espconn. Насколько понимаю, это проприетарный форк LwIP — библиотеки реализации TCP/IP стека для встраиваемых устройств. В SDK входит и сам LwIP, но мне, для начала, хотелось бы разобрать работу со штатной библиотекой. В руководстве ESP8266 Non-OS SDK API Reference она описана в качестве набора функций в главе 4 «TCP/UDP APIs». К сожалению, в данном руководстве ничего не было сказано про порядок работы с данным API. Поэтому за примерами пришлось лезть на github.com. В принципе, далеко ходить не пришлось, и на небезызвестном github.com/esp8266 был найден простой пример связи с dweet.io и передачи данных в JSON формате. Другой пример, который мне показался полезным, можно найти в examples SDK под названием «at_espconn».
Для начала, мне хотелось бы разобрать пример подключения по HTTP протоколу с использованием GET запроса. Попробуем просто скачать HTML-станицу со своего сервера, т.е. реализуем программными средствами пример из ноябрьской статьи: «13) Получение web-страницы или текстового файла от сервера на OpenWRT».
Итак, работа с TCP соединением через espconn производится через коллбэк-функции. Т.е. вы пришите свои функции на открытие TCP соединения, закрытие TCP соединения, на прием и передачу данных и т.е. Совсем не обязательно писать все коллбэк-функции, пишите только те, что вам необходимо. Очевидно, что перед созданием TCP соединения необходимо будет задать адрес и порт. Т.о., отталкиваясь от предыдущего примера, делаем следующее:
Добавляем заголовочные файлы с объявлением функций espconn и функций для работы с памятью:
Добавляем ip-адрес и порт целевого сервера:
Добавляем буфер, в котором будут храниться передаваемые и получаемые данные:
Если ваши данные небольшие по размеру, то буфер можно задать статично, как показано выше. Иначе имеет смысл использовать динамическое выделение памяти под массив.
Добавляем объявление коллбэк-функций:
И теперь собственно пишем функцию установки TCP-соединения:
Принцип работы походит на установку WiFi-соединения. Сначала создается структура типа espconn, далее заполняются ее поля, регестрируются коллбэк функции, после чего структура «скармливается» функции espconn_connect в качестве значения.
Вызов функции send_data() добавим в коллбэк-функцию void wifi_handle_event_cb(System_Event_t *evt)
Т.е. функция send_data() будет вызвана сразу после подключения к точке доступа WiFi.
Коллбэк функции: tcp_connected(void *arg), data_received_cb(void *arg, char *pdata, unsigned short len) и tcp_disconnected_cb(void *arg) выглядят следующим образом.
Функция tcp_connected(void *arg):
Эта функция будет вызываться первой, в начале установки TCP соединения. Здесь строка: os_printf(«%s\n», __FUNCTION__ ) выполняет отладочную роль, она будет печатать имя функции, т.е. tcp_connected. Далее: os_sprintf(buffer, «GET / HTTP/1.1\r\n\r\n») — копирует строку c GET-запросом в буфер. Строка: os_printf(«Sending: %s\n», buffer) — выполняет опять же отладочную функцию, отображает содержимое буфера. И собственно: espconn_sent(conn, buffer, os_strlen(buffer)) передает содержимое буфера на удаленный сервер.
Коллбэк-функция data_received_cb() обрабатывает ответ уделенного сервера:
Через указатель на массив *pdata передается сам ответ, который функция os_printf( «%s: %s\n», __FUNCTION__, pdata) передает на последовательный порт. После этого, с помощью espconn_disconnect(conn) TCP-соединение разрывается.
В момент разрыва TCP-соединения вызывается коллбэк-функция tcp_disconnected_cb:
Она разрывает соединение с точкой доступа с помощью вызова функции SDK: wifi_station_disconnect().
Таким образом, алгоритм работы программы выглядит так:
- После старта ESP8266, сразу же устанавливается соединение с точкой доступа с режиме клиента (station mode);
- После установки соединения c точкой доступа, вызывается функция send_data() которая устанавливает TCP-соединение с удаленным сервером.
- При установке TCP-соединения с удаленным сервером, функция tcp_connected() посылает GET-запрос веб-серверу.
- После получения ответа, функция data_received_cb() распечатает его через UART, и разрывает TCP-соединение.
- После разрыва TCP-соединения, функция tcp_disconnected_cb() разрывает соединение с точкой доступа.
Полный текст программы можно просмотреть под спойлером:
После компиляции и прошивки esp8266, лог работы программы будет выглядеть так:
Здесь хочу обратить внимание на то, что в качестве ответа веб-сервера мы получаем лишь 200-ий код ответа.
Теперь напомню, как выглядела TCP-сессия с помощью AT-команд:
Здесь ответ приходил двумя «чанками», после чего сервер САМОСТОЯТЕЛЬНО закрывал TCP-соединение. Т.е. если мы закомментируем строку с «espconn_disconnect(conn);», то получим полный ответ сервера:
Для контроля, в Wireshark можно посмотреть лог трафика генерируемого esp8266 в течении сессии:
Каких-либо ошибок не наблюдается. Отмечу, что в Wireshark трафик отфильтрован по порту веб-сервера. В данном случае это 8010.
4) Использование режима энергосбережения «deep sleep»
Теперь попробуем адаптировать алгоритм нашей программы ближе к реальной задаче. Для этого, ее работа должна выглядеть следующем образом: 1) esp8266 стартует, соединяется с точкой доступа, передает или принимает какие-то данные, после чего отключается от точки доступа. 2) после выполнения первой задачи, пусть esp8266 уходит в спящий режим, по выходу их которого он будет «дергать» RESET, в результате чего esp8266 перезагрузится и все начнётся заново.
Для осуществления этой задачи нам придется выкинуть из программы мигалку на светодиоде. Т.к. большую часть времени esp8266 будет находиться в режиме пониженного энергопотребления, в котором мигать чем либо уже не получиться. Кроме того, светодиод мигалки находиться на GPIO16 который принадлежит RTC, и он нам понадобится для пробуждения из спящего режима.
Работа eps8266 в режиме энергосбережении описана в следующем руководстве: ESP8266 Low Power Solutions
Согласно пункту 4.5 этого руководства, чтобы перевести esp8266 в режим пониженного энергосбережения deep_sleep, после завершения соединения с точкой доступа, достаточно будет добавить в CASE функции wifi_handle_event_cb(System_Event_t *evt) две сточки кода:
где system_deep_sleep_instant(60000*1000) — задает время пробуждения в микросекундах, а system_deep_sleep_set_option(2) — задает режим энергосбережения который не требует перекалибровки радочастотного модуля.
Полный текст обновленной программы можно посмотреть под спойлером:
Не забывайте, что из Makefile следует убрать сборку модуля gpio16.o. Кроме того, вывод D0/GPIO16 нужно будет соединить с RESET, чтобы esp8266 смог «проснуться»:
Есть еще один неприятный подводный камень при использовании режима пониженного энергопотребления deep_sleep. Проблема проявлется в невозможности прошить плату esp8266 nodemcu с помощью автоматической загрузки прошивки. Выглядит это как-то так:
В этом случае, чтобы прошить esp8266 нужно: а) отключить esp8266 от питания; б) зажать кнопку BOOT; в) подключить питание к esp8266 (кнопка BOOT при этом должна быть зажата); г) запустить прошивку esp8266, кнопку BOOT при этом можно освободить; д) после завершения прошивки, следует переподключить питание esp8266 (кнопка BOOT при этом должна быть свободной).
5) Реализация команды ping
Еще одной полезной возможностью мне показалась команда ping. Она имеется в AT командах, здесь же я хочу показать как она реализуется возможностями SDK.
Структуры и функции SDK для реализации команды ping объявлены в заголовочном файле ping.h, в папке с заголовочными файлами SDK. Описания в документации нет, т.е. они не документированы.
Рабочий пример реализации команды ping я встретил на форуме espressif: Ping_start function — ESP8266 Developer Zone. На всякий случай я скопирую его сюда:
Думаю, что если вы дочитали до этого места, то вопросов здесь возникнуть не должно. Я без изменений скопировал этот код в свою программу, заменил вызов функции send_data() на user_test_ping() и получил такой результат:
Здесь в качестве ip я указал ip точки доступа, т.е. 192.168.1.10.
Лог сетевого трафика в этом с случае выглядит так:
Однако данный вариант реализации команды ping требует указания IP целевого хоста, в то время как часто бывает нужно пропинговать хост по доменному имени. Функция SDK которая возвращает IP доменного имени назвается espconn_gethostbyname(). Наглядное использование этой функции имеется в приведенном выше примере.
Действуя по аналогии, поместим вызов этой функции в кейс функции wifi_handle_event_cb(System_Event_t *evt), который вызывается при установлении соединения с точкой доступа
Здесь: ping_conn — это структура espconn, ping_host — доменное имя, ping_ip — IP хоста которое следует найти, а dns_done — это коллбэк функция которая вызвается после получения IP хоста от DNS — сервера.
Функция dns_done() в таком случае примет такой вид:
Функция user_test_ping() незначительно меняется, она теперь принимает в качестве параметра IP-адрес:
Полный текст программы можно посмотреть под спойлером.
При работе программы, в терминале будет наблюдаться такой лог:
В Wireshark можно будет наблюдать два DNS пакета: запрос к DNS серверу, и последующий ответ от него:
6) Получение даты и времени из сети по протоколу SNTP
Последний пример, который мне хотелось бы привести — это синхронизация времени по протоколу SNTP. API для работы с протоколом SNTP приведено в части 3.13 руководства ESP8266 Non-OS SDK API Reference. Описание функций очень краткое, формальное. К счастью, там же есть рабочий пример использования этого API.
В качестве основы для портирования (красивое слово для банальной копипасты 😉 этого примера, я взял код из части 4 данной статьи, там где речь шла про установку TCP — соединения. Алгоритм пусть будет такой. После соединения с точкой доступа, производится инициализация SNTP. Во время инициализации указывается список SNTP-cерверов и регистрируется коллбек-функция вызываемая по таймеру. После этого запускается таймер этой функции.
На практике это будет выглядеть так. В кейс функции wifi_handle_event_cb(System_Event_t *evt) отвечающий за установку соединения с точкой доступа помещаем код из примера в части 3.13 руководства ESP8266 Non-OS SDK API Reference:
Здесь я немного изменил код в сравнении с оригиналом, т.к. функции ipaddr_aton() я не нашел, поэтому пришлось импровизировать. Указано IP моего домашнего сервера с OpenWRT, на котором установлен SNTP сервер. Также добавлена функция с установкой часового пояса. В данном случае устанавливается самарский часовой пояс. По умолчанию время синхронизируется по пекинскому часовому поясу, а не по Гринвичу, как следовало бы ожидать.
В области глобальный переменных нужно не забыть объявить таймер:
Коллбек-функция копируется практически без изменений:
Здесь, в случае успешного получения текущего времени отключается таймер, и управление передается функции send_data().
Полный текст программы можно посмотреть под спойлером:
Лог работы программы:
Если посмотреть на лог трафика, то можно увидеть DNS запросы на резовлинг домена 0.ru.pool.ntp.org с последующим обращением к ним по NTP протоколу:
В теле ответа NTP сервера можно увидеть дату и время которую мы в итоге получили.
На этом пока все. Я не стал рассматривать в статье UDP запросы, работу в режиме сервера, LwIP, web-сокеты, внутренний RTC и другие интересные вещи в надежде найти для этого полезные практические примеры, а не ограничиваться голой теорией. Надеюсь, что следующая статья будет более интересной с практической точки зрения.
ESP8266 Урок 14. Wi-Fi. Режим STA (Станция)
Ну вот, наконец-то, дошли мы до той темы, к которой стремились и ради чего начинался цикл уроков по контроллерам ESP8266 — это приём и передача данных при помощи возможностей ESP8266 по беспроводной сети Wi-Fi.
Я думаю, что все знают, что это за тип сети и для чего она применяется.
Напомню лишь, что Wi-Fi — это протокол передачи данных, осуществляемой без применения проводов, физического уровня.
Как именно передаются данные по сети и как они подготавливаются, как заворачиваются в протоколы различного уровня, мы также очень хорошо знаем. Кто не помнит, напомню — смотрите уроки 40, 41, 44, 45, 46, 47, 48, 49, 50, 51, 52 по программированию контроллеров AVR, а также аналогичные уроки по контроллерам STM32. В данных уроках мы очень подробно рассмотрели многие протоколы всех уровней модели OSI. Те же самые протоколы будут использоваться и здесь, причём нам особо не придётся их программировать вручную, но знать, как они устроены, для чего нужны, мы обязаны, чтобы избежать ошибок при передаче данных, а также, если они и возникнут, то оперативно их устранить. И рассмотренных нами протоколов нам не потребуется протокол физического уровня Ethernet, его заменит протокол Wi-Fi.
Мы пока подробно не будем изучать протокол Wi-Fi, так как с ним работает наш контроллер аппаратно, но режимы работы мы должны знать. И знакомится с их разновидностями мы будем постепенно.
А пока мы должны знать, что наш контроллер ESP8266 поддерживает три основных режима работы — станция (Station mode или кратко STA), программная точка доступа (SoftAP), а также смешанный — Station + SoftAP.
Самым простым из этих режимов является первый — режим станции.
Режим станции (STA) — это такой режим, в котором контроллер не создает собственную сеть, а подключается к любой существующей сети Wi-Fi, например, к существующей локальной сети или к другому устройству, работающему в режиме точки доступа (AP).
На данном уроке мы настроим режим станции и попробуем подключиться к существующей точке доступа, например к роутеру, который раздаёт Wi-Fi по дому. Роутер от просто точки доступа отличается тем, что трафик, идущий от станций, подключенных к нему, он транслирует во внешнюю сеть и наоборот.
Пока воспользуемся возможностями SDK, то есть не будем лезть глубоко в дебри аппаратной части. Всему своё время.
Схема у нас будет простейшая — отладочная плата, подключенная к USB компьютера
Весь процесс соединения с точкой доступа и вхождение в различные стадии соединения мы будем отслеживать с помощью терминальной программы с помощью UART.
Проект наш выполнен из проекта прошлого урока с именем OS_TIMER и назван WIFI_STA.