Технология ESP-NOW — это упрощенный протокол связи WiFi с передачей коротких пакетов между парами сопряженных устройств, разработанный и выпущенный Espressif в 2016.07 для микроконтроллеров ESP8266 и ESP32. При этом дополнительные процедуры, связанные с поддержкой протокола WiFi не используются, что ускоряет процесс обмена пакетами.
ESP-NOW может применяться в Интернете Вещей для управления интеллектуальными источниками света, реле, розетками, другими устройствами дистанционного управления, получения информации от датчиков и других приложений.
ESP-NOW поддерживает следующие функции
- Зашифрованная и незашифрованная связь между сопряженными парами устройств.
- Смешанные зашифрованная и незашифрованная связь между сопряженными устройствами.
- Передача до 250 байт полезной информации.
- Настройка функции обратного вызова для информирования прикладного уровня, в частности, об успешности или сбое передачи.
ESP-NOW также имеет следующие особенности и ограничения
- Скорость передачи — не более 1 мбит/с на частоте 2,4гГц, т.е. ESP-NOW работает на той же частоте и каналах, что и ваш роутер WiFi.
- Протокол WiFi не используется
- Аналогичен протоколу с низким энергопотреблением, используемому в беспроводной мыши 2,4 ГГц.
- Требуется только начальное сопряжение.
- После сопряжения соединение не разрывается.
- Широковещательная передача не поддерживается — только множественная раздача сопряженным парам устройств.
- Максимум 20 пар, включая зашифрованные, поддерживаются на одном устройстве, включая зашифрованные пары.
- Максимум 10 зашифрованных пар поддерживаются в режиме Station.
- Максимум 6 в режиме SoftAP или SoftAP + Station.
- Шифрование многоадресной рассылки не поддерживается.
Безопасность
ESP-NOW применяет технологию фреймов IEEE802.11 Action Vendor вместе с функцией IE, разработанной Espressif, и технологией шифрования CCMP, реализуя безопасное коммуникационное решение без установления соединения. Устройство с Wi-Fi поддерживает основной мастер-ключ (PMK) и несколько локальных мастер-ключей (LMK)
- PMK используется для шифрования LMK с помощью алгоритма AES-128.
- LMK сопряженного устройства используется для шифрования пользовательской информации методом CCMP. Максимальное количество разных LMK — 6. Если LMK для сопряженного устройства не задан, пользовательские данные шифроваться не будут.
Базовый уровень
На нижнем уровне протокола ESP_NOW поддерживается связанный список, содержащий информацию о локальном устройстве и о сопряженном устройстве, в том числе MAC-адреса и ключи. ESP-NOW также хранит часто используемые данные для прикладного уровня, чтобы избежать накладных расходов на повторную обработку связанного списка. Информация об устройствах используется для отправки и получения данных и включает в себя
Информацию о локальном устройстве:
- PMK: 16 байт — основной мастер-ключ, который используется для шифрования ключа на присоединенном устройстве (KOK в API) ESP_NOW поддерживает PMK по умолчанию, поэтому настройка не требуется. Если необходимо, можно убедиться, что значение PMK совпадает с локальным устройством.
- Режим: 1 байт — режим локального устройства определяющий передающий WiFi интерфейс (SoftAP или STA) ESP-NOW. Режим сопряженного устройства не влияет на какую-либо функцию, а только сохраняет информацию о режиме для прикладного уровня. В режиме STA WiFi применим только Station и SoftAP WiFi — только SoftAP.
Режимы ESP_NOW работы локального устройства
Режим Состояние Приоритет WiFi IDLE не определено передача данных не разрешена CONTROLLER главный STA SLAVE подчиненный SoftAP COMBO главный&подчиненный SoftAP
Информацию о сопряженном устройстве в паре (включая часто используемую информацию и другую пользовательскую информацию):
- LMK: 16 байт — локальный мастер-ключ, который используется для шифрования ключа полезной информации во время связи в данной паре.
- MAC-адрес: 6 байт — адрес сопряженного устройства, совпадает с адресом отправителя. Например, если пакет отправляется со Station, MAC-адрес должен совпадать с адресом Station.
- Режим: 1 байт — режим локального устройства определяющий передающий интерфейс (SoftAP или STA) ESP-NOW.
- Канал: 1 байт — канал, через который обмениваются данными устройства, соединенные в пару.Может иметь значение 0..255. Канал не влияет ни на какую функцию, а только сохраняет информацию о канале для прикладного уровня. Значение определяется прикладным уровнем. Например, 0 означает, что канал не определен; 1 ~ 14 означает действительные каналы; всем остальным значениям могут быть назначены функции, которые определены прикладным уровнем.
Espressif не рекомендует использовать продолжительные операции в функциях обратного вызова при посылке/отправке пакетов, что связано, предположительно, с реализацией алгоритмов, использующих механизм прерываний. В пользу этого предположения так же говорят и проблемы, связанные с динамическим выделением памяти в функциях обратного вызова, что решается предпочтительным использованием статических переменных, а так же неоднозначность применения механизма исключений MicroPython.
Реализация асинхронности процессов запуска/завершения, установки связи в паре, получении/передачи пакетов Espressif не описывается, что так же не облегчает применение идеологии asyncio MicroPython.
Формат пакета ESP-NOW
- Заголовок MAC: 24 байта.
- Категория: 1 байт, указывающий на категорию создателя пакета. Установлено значение (127).
- ID организации: 3 байта, содержит уникальный идентификатор, который является первыми тремя байтами MAC-адреса, примененного Espressif. Установлено значение (0x18fe34)
- Случайное значение: 4 байта, используется для защиты данных.
- Данные создателя пакета: 7-255байт
Данные создателя пакета содержат следующие поля:
- ID: 1 байт, Установлено значение (221).
- Длина: 1 байт, общая длина ID организации, типа, версии и пользовательских данных.
- ID организации: 3 байта, содержит уникальный идентификатор, который является первыми тремя байтами MAC-адреса, примененного Espressif. Установлено значение (0x18fe34)
- Тип: 1 байт, протокол ESP-NOW. Установлено значение (4)
- Версия: 1 байт, текущая версия ESP-NOW. Установлено (1)
- Содержимое: 0-250 байт пользовательские данные.
- FCS: 4 байта, контрольная сумма
Так как ESP-NOW не использует протокол WiFi, заголовок MAC немного отличается от заголовка стандартных пакетов. Биты FromDS и ToDS поля FrameControl равны 0. В первом поле адреса задан адрес назначения. Во втором поле адреса указан адрес источника. Третье поле адреса установлено как широковещательный адрес (0xff: 0xff: 0xff: 0xff: 0xff: 0xff).
Основной алгоритм применения
Начало и завершение
Перед началом использования ESP-NOW рекомендуется установить интерфейс Wi-Fi в нужном режиме. Обычно интерфейс Station устанавливается для CONTROLLER, интерфейс SoftAP для SLAVE и COMBO. Так же целесообразно остановить Wi-Fi после завершения использования ESP-NOW.
Для начала работы ESP-NOW вызвать esp_now_init() и esp_now_deinit() для завершения. Когда вызывается esp_now_deinit(), вся информация о сопряженных устройствах удаляется.
Привязка функций обратных вызовов
Функция обработки вызова при отправке пакета esp_now_register_send_cb() может использоваться для информирования прикладного уровня отправляющей стороны в паре об успешности или неудаче передачи, например, если информация на подуровне MAC передана успешно.
При использовании esp_now_register_send_cb() следует учитывать:
В связанной паре:
- Если прикладной уровень не получил пакет, но функция обратного вызова вернула «success», причиной может быть:
— атаки от мошеннического устройства
— ошибки установки зашифрованного ключа
— потери пакетов на прикладном уровне Espressif - Если прикладной уровень получил пакет, но функция обратного вызова возвращает ошибку, причиной может быть:
— Канал занят, и ACK не получен.
При множественной связи со всеми парами локального устройства:
- Если функция обратного вызова возвращает «success», это означает, что пакет был отправлен успешно.
- Если функция обратного вызова возвращает ошибку, это означает, что пакет не был успешно отправлен.
Функция обработки вызова при получении пакета esp_now_register_receive_cb() возвращает информацию, включающую в себя MAC-адрес отправляющего устройства в паре и полезную информацию. Так же может использоваться для информирования прикладного уровня отправляющего устройства в паре от принимающего о том, что пакет был успешно принят.
Добавление пары сопряженных устройств
Прежде чем отправлять данные необходимо добавить устройство в список пар сопряженных устройств вызовом esp_now_add_peer(). Перед отправкой данных группе установленных пар необходимо добавить устройство с групповым MAC-адресом. Диапазон канала сопряженных устройств составляет от 0 до 14. Если канал установлен на 0, данные будут отправляться по текущему каналу. В противном случае канал должен быть установлен как канал, на котором находится локальное устройство.
Безопасность
Если ключ необходимо зашифровать, для настройки можно вызвать esp_now_set_pmk(), чтобы установить PMK. Если PMK не установлен, будет использоваться PMK по умолчанию и выбрать один и тот же ключ для всех устройств. Так же для выбранных пар установить LMK.
Отправка данных пакетами ESP-NOW
Для отправки данных ESP-NOW используется esp_now_send (). При этом функция, установленная ранее в esp_now_register_send_cb() вернет ESP_NOW_SEND_SUCCESS при отправке функции обратного вызова, если данные были успешно приняты на уровне MAC. В противном случае вернется ESP_NOW_SEND_FAIL. Несколько причин могут привести к тому, что ESP-NOW не сможет отправить данные. В частности,
- целевое устройство не существует;
- каналы устройств не совпадают;
- данные теряются при передаче.
Не гарантируется, что прикладной уровень обязательно примет данные. При необходимости можно отправить подтверждение при получении данных ESP-NOW. При возникновении тайм-аута при подтверждении, передачу данных ESP-NOW следует повторить. Порядковый номер также может быть назначен для данных ESP-NOW для удаления дубликатов данных.
При отправке данных ESP-NOW через esp_now_send() следует учитывать, что за один раз можно отправлять не более 250 байтов информации.
ВНИМАНИЕ! Слишком короткий интервал между отправкой двух пакетов ESP-NOW может привести к ошибкам исполнения функции обратного вызова, в связи с чем рекомендуется отправлять следующий пакет данных ESP-NOW после того, как функция обратного вызова при обработке предыдущей отправки успешно завершилась. Функция обратного вызова отправляется из высокоприоритетной задачи Wi-Fi. Поэтому не рекомендуется выполнять продолжительные операции в функции обратного вызова. Вместо этого можно разместить необходимые данные в статическую очередь и обработать их из процессом с более низким приоритетом.
Если функция отправки возвращает MAC-адрес, то он будет отправлен на устройство с этим MAC-адресом. Если функция отправки возвращает NULL, то пакет будет отправлен всем устройствам, присоединенным к отправляющему, что может привести к сбою передачи или задержке из-за перегрузки сети.
Получение данных пакетами ESP-NOW
Функция обратного вызова также запускается из задачи Wi-Fi. Поэтому не рекомендуется выполнять продолжительные операций в функции обратного вызова. Вместо этого можно разместить необходимые данные в статическую очередь и обработать их процессом с более низким приоритетом.
В заключение изложенного
Мой опыт сборки Espressif IDE и MicroPython с ESP-NOW, описывающий ошибки, с которыми столкнулся при сборке и варианты их исправления собираюсь выложить после достижения устойчивого результата. Тогда же сделаю и описание библиотеки ESP-NOW на MicroPython с обнаруженными ошибками, способами их устранения. К сожалению, в связи с тем, что исходный код ESP-NOW закрыт и распространяется только в бинарном виде, понимание алгоритмов протокола ESP-NOW эмпирическое и существует ряд уже выявленных проблем, по которым не всегда находятся варианты их логичного преодоления, но в целом ESP-NOW успешно применяется в сообществе как C-пользователей, так и Питонистов исходя из более 300 применений, представленных на GitHub.
Описание библиотеки ESP-NOW на С от Espressif
Описание и открытые источники ESP-NOW на MicroPython
Автор: Андрей Золотарев