Технологии беспроводной связи традиционно ассоциируются с сетями WiFi и мобильной связью. Однако, в последнее время все большую популярность в промышленных сетях и Интернет вещей (IoT) набирает беспроводной протокол ZigBee. В этой статье мы поговорим о построении сетей на основе протокола ZigBee.
Итак, Zigbee это спецификация сетевых протоколов уровня приложений и сетевого уровня — использующих сервисы уровня управления доступом к среде MAC и физического уровня. Zigbee и стандарт IEEE 802.15.4 описывают беспроводные персональные сети (WPAN).
Спецификация Zigbee ориентирована на приложения, требующие гарантированной безопасной передачи данных при относительно небольших скоростях и возможности длительной работы сетевых устройств от автономных источников питания.
Кто есть кто
В сети ZigBee есть 3 типа устройств — координатор, маршрутизаторы и конечные устройства. Разберемся с каждым из них.
Координатор ZigBee это центральное устройство в сети, которое отвечает за инициализацию и управление сетью. В каждой сети может быть только один узел координатор. Также, в соответствии с спецификацией Zigbee LightLink возможна работа без координатора Zigbee.
Маршрутизаторы ZigBee которые также называют ретрансляторами, передают данные другим устройствам. Такие устройства Zigbee обычно питаются от сети, поэтому они всегда доступны.
Маршрутизаторы и координатор обеспечивают транзитную передачу данных между различными узлами сети.
Конечные устройства могут только отправлять или получать данные на/от маршрутизаторов, они не могут выступать в качестве транзитных узлов. Обычно конечные устройства работают от аккумуляторов.
Сеть ZigBee может быть ячеистой сетью, в которой несколько устройств могут общаться напрямую, не проходя через координатор.

В целом, сеть ZigBee достаточно стандартизирована. В ней нет жесткой привязки к оборудованию одного вендора. Существует ряд открытых проектов (zigbee2mqtt, SLS, sprut), которые позволяют объединять устройства разных производителей в единую сеть.
Теперь, когда мы разобрались с базовыми понятиями ZigBee рассмотрим принципы работы этой сети более подробно.
Архитектура устройства Zigbee
ZigBee основана на стандарте IEEE 802.15.4. Часть PHY описывает физический уровень сети — как передаются биты и байты по радиоканалу. Микроконтроллер сам отслеживает радиообстановку и передает данные, когда радиоканал свободен. Все это происходит без участия приложения, работающего в прошивке нашего устройства.
MAC‑уровень IEEE 802.15.4 занимается передачей пакетов данных между отдельными узлами сети, а также отправляет обратно подтверждение о правильной доставке данных. В принципе, нам не придется погружаться на этот уровень, если только там не появится какая‑то ошибка. Для нас это просто транспорт — отправьте эти байты (не более 100 байт за раз) другому устройству.

Сетевой уровень ZigBee (NWK) фактически обслуживает сеть ZigBee — назначает сетевые адреса устройствам, строит маршруты передачи пакетов данных между не связанными напрямую узлами, позволяет передавать данные различными способами (одноадресная или широковещательная рассылка). Здесь мы тоже не будем углубляться, но нам будут интересны некоторые события, происходящие на этом уровне.
Для нас наиболее интересным будет уровень приложений (Application Layer, APL). Этот уровень управляет взаимодействием устройства с сетью Zigbee, описывает поведение устройства в целом, а также реализует его отдельные функции.
Application Framework
Полезные функции реализуются в блоке Application Framework (AF), а точнее, они реализуются в сущностях, называемых конечными точками. Конечная точка — это логическая группа команд и атрибутов, которые описывают одну функцию устройства.
Для того, чтобы понять о чем идет речь давайте рассмотрим несколько примеров. Допустим, мы создаем многоканальный релейный переключатель с управлением ZigBee. Тогда, каждый канал в этом устройстве будет отдельной конечной точкой — каждое реле сможет включаться и выключаться независимо, и, возможно, измерять некоторые параметры, например ток или мощность. А все конечные точки вместе уже определяют устройство в целом.
Другой пример, ночник с функцией термометра. Ночник и термометр — это совершенно отдельные функции, каждая из которых может управляться независимо, а значит, они реализуются разными конечными точками.
Двухкнопочный интеллектуальный выключатель также реализуется с двумя конечными точками, каждая из которых управляется своей кнопкой и независимо от нее управляет своим реле‑переключателем.
Конечные точки предназначены для идентификации того, какая часть устройства была источником сообщения или какой части целевого устройства адресована команда.
При этом, мы можем напрямую связывать конечные точки разных устройств. Например, одна из клавиш переключателя может управлять отдельным переключателем реле в многоканальном реле из примера выше, причем делает это без участия координатора.
Кластер ZigBee
Кластер ZigBee — это стандартизированный набор функций. Кластер объединяет несколько атрибутов и команд, которые логически связаны с функциональностью кластера. Так, для лампы атрибутами могут быть яркость, цветовая температура или цвет RGB, а для датчика климата атрибутами могут быть температура, влажность и давление. Лампа будет иметь команды включения и выключения или установки цветового режима, в то время как климатический датчик не будет иметь никаких команд вообще — это датчик, а не исполнительное устройство.
Конечная точка может состоять из нескольких кластеров, но кластеры в одной конечной точке не должны повторяться. Если вам нужно устройство с несколькими одинаковыми кластерами, их нужно распределить по разным конечным точкам (именно поэтому двухкнопочный переключатель реализуется как минимум двумя конечными точками).
Хотя устройство может реализовать в принципе любую функциональность, разработчики ZigBee заметили, что некоторые типы функциональности повторяются в разных устройствах и реализуются схожим образом. Многие устройства реализуют что‑то вроде выключателя, термометра, счетчика электроэнергии, лампы, датчика движения, термостата или чего‑то еще. Каждый из этих типов функциональности называется кластером, стандартизирован и подробно описан в спецификации.
Разработчики стека ZigBee пошли еще дальше и реализовали для нас API для работы с каждым кластером, назвав его ZigBee Cluster Library (ZCL). Таким образом, нам не придется иметь дело с низкоуровневыми пакетами для передачи температуры или яркости лампы. Вместо этого мы будем использовать достаточно высокоуровневый API.
Каждый кластер может быть как клиентом, так и сервером (или одним из них). Например, беспроводная кнопка будет клиентом только в кластере On/Off — у нее нет части релейного переключателя, и она может посылать сигнал только при нажатии кнопки. Релейный переключатель ZigBee также будет реализовывать кластер On / Off, но будет только сервером — он будет выполнять команды на включение и выключение, но не сможет генерировать эти команды каким‑либо образом. Конечно, есть устройства, которые реализуют и клиент, и сервер (например, выключатель Xiaomi, в котором есть и кнопки, и реле).
ZigBee Device Object
ZigBee Device Object (ZDO) — это специальная конечная точка #0, которая используется для идентификации устройства. Когда устройство присоединяется к сети, координатор ничего не знает о нем. Используя процесс опроса, координатор может отправлять запросы на конечную точку ZDO устройства с просьбой описать себя. В свою очередь, устройство сообщит координатору различную информацию, такую как модель и имя устройства, версию прошивки, источник питания и многие другие атрибуты.
ZDO также может описывать функции устройства, отправляя дескрипторы устройства и конечных точек. Дескрипторы — это специальные структуры данных, которые описывают, какие кластеры реализованы в устройстве и как они сгруппированы по конечным точкам, какие из кластеров являются серверными или клиентскими.
Хотя устройство может реализовать собственную логику присоединения к сети, SDK предоставляет функциональность Base Device Behavior (BDB), которая реализует типичное поведение устройства как сетевого узла, такое как присоединение, повторное присоединение в случае потери сети и выход из сети. Она также предоставляет возможности для включения предварительно сконфигурированных сетей.
Асинхронная работа
Итак, этого достаточно, чтобы понять базовую архитектуру. Но прежде чем мы пойдем дальше, стоит упомянуть еще одну важную вещь, которая оказывает существенное влияние на архитектуру прошивки — обмен данными идет в асинхронном, и главными действующими лицами в этой системе являются события и сообщения.
В ZigBee узлы общаются друг с другом с помощью коротких сообщений. Если узел не может достичь адресата напрямую, сообщение будет доставлено через несколько промежуточных узлов. На каждом этапе пакет подтверждается принимающим узлом на уровне IEEE 802.15.4 MAC. Конечный получатель может отправить ответ, при этом на каждом этапе пакет также будет подтвержден.
Однако радио — не очень надежная среда передачи, и некоторые пакеты могут просто не дойти до адресата. В этом случае по истечении некоторого времени отправителю необходимо организовать повторную передачу, а возможно, и поиск нового маршрута. А пока отправитель ждет ответа, в сети может происходить миллион других вещей — какие‑то узлы будут общаться друг с другом, какой‑то узел захочет присоединиться к сети, координатор может прийти с запросом, или соседнее конечное устройство проснется и начнет передавать данные через наше устройство. С точки зрения классического, «линейного» программирования, все это превращается в жуткий хаос.
Однако, на самом деле все не так плохо. Происходящее в сети превращается в некий поток событий, для которого нам нужно будет написать обработчики. То есть, если приходит входящее сообщение, оно будет обработано в обработчике. Если сеть падает — устройство переподключается и сообщает об этом событием. Если нужно отправить какие‑то важные данные — отправляем их по сети и запускаем таймер ожидания ответа. Таким образом, прошивка превращается в набор обработчиков конкретного события. Но в случае сложной коммуникации эти обработчики должны быть сгруппированы в более крупную структуру, возможно, в машину состояний.

Пакеты данных
Если нам нужно передать байты по сети, мы не можем просто взять и отправить их в радиоканал — приемники не поймут, что это за пакет, кому он адресован, нужно ли его обрабатывать, или он должен быть передан по сети какому‑то другому узлу. Поэтому умные люди придумали модель OSI и наделили каждый уровень своим назначением. Каждый уровень имеет свой собственный формат пакета и добавляет в него свои служебные данные. Давайте посмотрим на рисунок.

Предположим, приложение хочет отправить блок данных. Оно передает этот блок на следующий (сетевой) уровень, который добавляет к пакету заголовок. Этот заголовок описывает, кто является отправителем пакета и какому сетевому устройству он адресован. Конечный получатель может находиться довольно далеко от отправителя, и пакет фактически будет отправлен через промежуточный узел. Поэтому MAC‑уровень добавляет свой собственный заголовок, устанавливая промежуточный узел в качестве получателя данного конкретного пакета, и просит повторно передать этот пакет дальше. Уровень PHY также добавляет некоторые собственные данные. Таким образом, наши байты полезной нагрузки обернуты в несколько оберток, каждая из которых имеет свое собственное назначение.
При получении пакета распаковка происходит противоположным образом — каждый следующий уровень отрезает его заголовки и хвосты и передает на следующий уровень только полезную нагрузку. Только байты данных полезной нагрузки, без всяких оберток, попадают на прикладной уровень устройства назначения.
Заключение
В этой статье мы рассмотрели архитектуру и основные принципы работы сетей ZigBee. Использование этого протокола позволяет существенно упростить работу с IoT и промышленными устройствами. Также множество разработчиков поддерживают ZigBee, благодаря чему проект продолжает активно развиваться.
Освоить навыки сетевого инженера с акцентом на траблшутинг с нуля можно на специализации "Network Engineer".
Сетевые технологии часто оказываются слабым звеном в IoT и разработке. Если вы сталкивались с проблемами настройки или масштабирования сетевых решений, пора разобраться, как все это работает на более глубоком уровне.
Если хотите улучшить свои навыки в сетевых протоколах и Docker, эти открытые уроки помогут вам избежать типичных ошибок и повысить эффективность работы:
nixel
Кажется, сейчас имеет смысл начинать курить Matter over Thread. По крайней мере для новых установок.