Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Это третья часть перевода книги Мохаммада Афане “Intro to Bluetooth Low Energy”. Сегодня мы подробнее рассмотрим процесс подключения устройств и поговорим о сервисах.
Предыдущие части:
Про архитектуру BLE
Про типы устройств, адвертайзинг и сканирование
Благодаря сервисам происходит обмен как стандартными данными (уровень заряда батареи через Battery Service, текущее время устройства через Current Time Service и т.д.), так и кастомными, при помощи сервисов, созданных разработчиком устройства для удовлетворения специфических нужд. Например, для Atmotube Pro мы сделали два сервиса, в которые сгруппировали несколько характеристик для синхронизации истории, передачи данных о концентрации пыли и летучих органических соединений.
Эта часть получилась очень большой, извините. Я старался сократить ее, или разбить на несколько, однако это нарушило бы целостность восприятия, пожалуй, самой важной темы книги. В следующей части мы поговорим о нововведениях Bluetooth 5 и рассмотрим методы обеспечения безопасности соединения и пользовательских данных в BLE.
4. Соединения
Для того, чтобы два BLE устройства установили соединение, необходимо выполнить следующие шаги:
Периферийное устройство должно начать процесс адвертайзинга и не останавливать его до момента установки соединения.
Центральное устройство должно сканировать радиоэфир в поисках пакетов адвертайзинга.
Если центральное устройство прослушивает канал адвертайзинга в момент, когда периферийное устройство посылает по нему данные, то оно обнаруживает периферийное устройство.
Затем центральное устройство посылает пакет CONNECT_IND (также известный как запрос на соединение).
Периферийное устройство всегда прослушивает текущий канал адвертайзинга после отправки пакета. Это позволяет ему получить запрос на соединение от центрального устройства, что запускает процесс установки соединения между двумя устройствами.
После того как будут выполнены эти шаги, соединение будет считаться созданным, но еще не установленным. Соединение будет считаться установленным, после того как устройство получит пакет данных от своего партнера по соединению. После установления соединения центральное устройство возьмет на себя роль ведущего, а периферийное, в свою очередь, ведомого. Ведущее устройство будет отвечать за управление соединением, контроль параметров соединения и контроль временных интервалов между различными событиями.
4.1 События подключения
Во время событий подключения ведущий и ведомый отправляют друг другу данные до тех пор, пока не останется данных, требующих передачи. Есть несколько фактов о соединениях, которые очень важно знать:
События подключения происходят периодически до тех пор, пока соединение не будет закрыто или потеряно.
Событие подключения состоит как минимум из одного пакета посланного ведущим устройством.
Ведомое устройство всегда посылает отвечает отправкой пакета, если оно получает пакет от ведущего.
Если ведущий не получает ответный пакет от ведомого, он закрывает подключение - он возобновит посылку пакетов во время следующего события подключения.
Подключение может быть закрыто как ведущим, так и ведомым.
События подключения разнесены во времени на период интервала соединения.
4.2 Параметры соединения
Параметры, определяющие соединение:
Интервал соединения
Интервал соединения может принимать любое из значений между 7.5 мс и 4.0 секундами с шагом в 1.25 мс. Он задается центральным устройством в пакете запроса соединения. Центральное устройство может принять во внимание Предпочитаемые Параметры Соединения Периферийного Устройства (PPCP). Центральное устройство вправе принять их, модифицировать или отклонить.
Задержка ведомого (Slave Latency)
Параметр задержки ведомого позволяет периферийному устройству оставлять без ответа определенное количество событий соединения и не слушать центральное устройство во время этих событий без инвалидации соединения. Это позволяет периферийному устройству переходить в режим энергосбережения на более длительный срок. Задержка ведомого отображает количество событий соединения, которое периферийное устройство может пропустить.
Например, если установлена задержка три, то периферийное устройство может пропустить три последовательных события соединения, но затем оно должно будет выйти из режима энергосбережения, прослушать центральное устройство и ответить на следующее событие соединения.
Таймаут наблюдения (Supervision Timeout)
Таймаут наблюдения используется для определения потери соединения. Он определяется как максимальное время между двумя полученными пакетами данных, прежде чем соединение считается потерянным. Его значение может задаваться в диапазоне между 100 мс и 32 секундами с шагом 10 мс. Другое условие выглядит следующим образом:
Таймаут наблюдения > (1 + задержка ведомого) * интервал соединения * 2
Существует исключение, для которого таймаут наблюдения не применяется - в момент, когда соединение создано, но еще не установлено. В этом случае ведущее устройство примет решение о потере соединения, если не получит пакета от ведомого в течении 6 интервалов соединения.
Расширение длины данных (DLE)
Это опция, которая позволяет пакетам данных содержать большее количество полезной нагрузки (до 251 байта, в случае, когда эта настройка выключена, полезная нагрузка составляет 27 байт). Эта возможность введена в версии 4.2 спецификации Bluetooth.
Максимальная единица передачи (MTU)
Понятие максимальной единицы передачи используется в компьютерных сетях и определяет максимальный размер данных, которые можно передать по определенному протоколу. Максимальная единица передачи атрибута (в спецификации определена как ATT_MTU) это наибольший размер полезной нагрузки атрибута, который можно передать между клиентом и сервером.
Эффективный размер ATT_MTU определяется наименьшим значением максимальных ATT_MTU поддерживаемых ведущим и ведомым. Например, если ведущее устройство поддерживает ATT_MTU 100 байт и ведомое устройство сообщает, что оно поддерживает ATT_MTU 150 байт, то ведущий решает, что для этого соединения будет использоваться ATT_MTU 100 байт.
Примечание: Для достижения максимальной пропускной способности убедитесь, что включено расширение длины передаваемых данных (в случае, если вы используете Bluetooth 4.2 или новее). Это поможет снизить количество избыточно передаваемых служебных данных, таких как заголовки пакетов, за счет уменьшения числа пакетов.
4.3 Переключение между каналами
Как мы упоминали ранее в начале этой главы, существуют 37 радиоканалов, используемых для передачи пакетов данных в течении соединения. В то же время, не все 37 каналов необходимы для соединения. Используемые каналы определяются картой каналов, которая включена в пакет запроса соединения, отправляемый центральным устройством периферийному для установки соединения. Для каждого события соединения пакеты данных будут переданы по другому каналу в карте каналов.
Последовательность каналов, используемая для каждого события соединения определяется картой каналов и шагом прыжка (hop increment). Шаг прыжка, также как и карта каналов, включен в пакет запроса соединения. Комбинация карты каналов и шага прыжка определяет, какой канал будет использован для каждого интервала соединения.
Существует два алгоритма выбора каналов в BLE. Рассмотрение подробностей их работы лежит вне поля зрения этой книги. Для того, чтобы узнать больше об этих алгоритмах и принципах их работы, обратитесь к спецификации Bluetooth (version 5.0 | Vol 6, Part B, Section 4.5.8.2).
4.4 Белый список и фильтрация устройств
BLE поддерживает фильтрацию устройств для процедур, связанных с состояниями адвертайзинга, сканирования и стадией инициации (при установлении соединения).
Белый список – это список адресов и типов адресов определенных устройств. Он используется для определения того, в каких устройствах заинтересовано конкретное устройство. Запись для анонимного типа адреса устройства позволяет сопоставить все широковещательные пакеты, отправленные без адреса.
Фильтрация устройств происходит на канальном уровне контроллера (нижний уровень протокола Bluetooth), что позволяет сохранить время и не производить лишнюю работу на уровне хоста (на верхних уровнях протокола). Однако именно хост отвечает на конфигурацию белого списка.
Ниже приведен список различных правил фильтрации для каждого из состояний:
Правило фильтрации для состоянии адвертайзинга (периферийное устройство)
Эта политика фильтрации определяет, как периферийное устройство будет обрабатывать запросы сканирования и запросы на подключение. Она может быть сконфигурирована следующим образом:
Обрабатываются запросы сканирования и запросы на подключение только от устройств из белого списка.
Обрабатываются запросы от всех устройств (фильтрация не используется).
Обрабатываются запросы сканирования только от устройств из белого списка, обрабатываются запросы на подключение от всех устройств.
Обрабатываются запросы на подключение только от устройств из белого списка, обрабатываются запросы сканирования от всех устройств.
Правило фильтрации для состояния сканирования (центральное устройство)
Это правило фильтрации определяет, как сканирующее устройство будет обрабатывать пакеты адвертайзинга. Может быть сконфигурировано следующим образом:
Обрабатываются пакеты адвертайзинга от всех устройств (белый список не используется).
Обрабатываются пакеты адвертайзинга только от устройств, включенных в белый список.
Правило фильтрации для состояния инициации (центральное устройство)
Это правило определяет, как устройство, инициирующее соединение, будет обрабатывать пакеты адвертайзинга. Может быть сконфигурировано следующим образом:
Обрабатывать пакеты адвертайзинга и инициировать соединение только с устройствами, включенными в белый список.
Обрабатывать пакеты адвертайзинга и инициировать соединение только с устройствами, определенными хостом.
Обратите внимание, что это не опция для обработки пакетов и подключения к подключаемому периферийному устройству, которого нет в белом списке.
5. Сервисы и характеристики
Прежде чем начать рассказ о сервисах и характеристиках, мы должны рассмотреть два очень важных понятия: Общий профиль атрибутов (GATT) и Протокол атрибутов (ATT).
Для того, чтобы понять, что из себя представляет общий профиль атрибутов, необходимо сперва разобраться, что из себя представляет его нижний слой - протокол атрибутов. GATT вступает в игру только после того, как будет установлено соединение между двумя устройствами.
Примечание автора
если вы считаете GAP, GATT и ATT набором слишком похожих акронимов… не проклинайте меня… Я просто рассказчик! Тем не менее важно разделять их!
5.1 Протокол атрибутов (ATT)
АТТ определяет, в каком виде сервер представит свои данные клиенту и как эти данные будут структурированы. Существует две роли, связанные с АТТ:
Сервер:
Это устройство, которое предоставляет данные, которые оно содержит, или которыми управляет и, в некоторых случаях, другие аспекты поведения сервера, которые могут контролировать другие устройства. Это устройство, которое получает входящие команды от связанного устройства и отправляет ответы, уведомления и индикации.
Например, беспроводной термометр будет вести себя как сервер, когда он будет предоставлять температуру окружающей среды, единицу измерений, свой уровень заряда и, возможно, временные интервалы, с которыми термометр производит измерения и сохраняет их результаты. Он также может уведомлять клиент (объясним позже) об изменениях температуры для того, чтобы клиент не опрашивал его непрерывно в ожидании готовых к отправке данных.
Клиент:
Это устройство, которое взаимодействует с сервером с целью считать предоставляемые сервером данные и/или для того, чтобы контролировать его поведение. Это устройство, которое посылает команды и запросы и получает входящие уведомления и индикации. В предыдущем примере, мобильный телефон, который подключался к беспроводному термометру и считывал его показания температуры, действовал в роли клиента.
Данные, предоставляемые сервером, сгруппированы в атрибуты. Атрибут это общий термин для любых типов данных, предоставляемых сервером, он определяет структуру этих данных. Например, сервисы и характеристики (будут описаны позднее) являются атрибутами. Ниже состав атрибута:
Тип атрибута (универсальный уникальный идентификатор, UUID)
Это 16-битное (в случае стандартных атрибутов Bluetooth SIG) или 128-битное число (в случае атрибутов, определенных разработчиком устройства, vendor-specific UUID).
Например, UUID для одобренного консорциумом атрибута значения температуры 0x2A1C. Одобренные консорциумом типы атрибутов имеют один общий (за исключением 16 бит) специальный 128-битный UUID:
0000XXXX-0000-1000-8000-00805F9B34FB
16-битный UUID будет подставлен вместо символов ХХХХ в базовом UUID.
Собственный UUID может быть любым 128-битным числом, не совпадающим ни с одним из одобренных Bluetooth-SIG базовых UUID. Например, разработчик может создать свой собственный UUID для показаний температуры, такой как:
F5A1287E-227D-4C9E-AD2C-11D0FD6ED640
Одно из преимуществ использования стандартных UUID состоит в уменьшении размера пакета, так как UUID может быть передан в виде 16-битного числа, вместо передачи полного 128-битного числа.
Дескриптор атрибута
Это 16-битное число, которое сервер присваивает каждому из своих атрибутов. Это число используется клиентом как ссылка на конкретный атрибут, и сервер гарантирует, что эта ссылка будет уникальной для атрибута, которому она присвоена, в течении всего времени существования соединения между устройствами. Дескриптор может иметь любое значение в диапазоне 0x0001-0xFFFF, значение 0х0000 зарезервировано.
Права атрибута
Права определяют, может ли атрибут быть прочитан или записан, может ли он посылать уведомления или индикации, и какие уровни доступа требуются для каждой из этих операций. Эти права не определяются протоколом атрибутов (АТТ) и не могут быть прочитаны через него, они определяются на верхнем уровне (GATT или уровне приложения).
5.2 Общий профиль атрибутов (GATT)
Теперь, когда мы рассмотрели концепцию атрибутов, познакомимся с другими тремя важными понятиями в BLE, с которыми вам придется постоянно сталкиваться.
Сервисы
Характеристики
Профили
Эти понятия введены для того, чтобы обеспечить возможность иерархического представления данных, предоставляемых сервером. Сервисы и характеристики это атрибуты, служащие для определенной цели. Характеристики это низкоуровневые атрибуты в базе данных атрибутов. Сервисы служат для группировки характеристик по функциональному признаку. Профили немного отличаются и не обнаруживаются на сервере - мы расскажем о них позже в этой главе.
GATT определяет формат сервисов и их характеристик, а также процедуры, используемые для взаимодействия с этими атрибутами, такие как обнаружение сервисов, чтение и запись характеристик, уведомления и индикации.
GATT выполняет ту же роль, что и протокол атрибутов (АТТ). Роли устанавливаются не для устройств, они определяются во время транзакций (такие как запрос ⟷ ответ, индикация ⟷ подтверждение, уведомление). Таким образом, устройство может действовать как сервер, предоставляющий данные клиентам, и в то же время быть в роли клиента, получая данные, подготовленные другими серверами одновременно.
5.3 Сервисы и характеристики
5.3.1 Сервисы
Сервисы это группа из одного или большего числа атрибутов, некоторые из которых являются характеристиками. Он предназначен для группировки связанных атрибутов, удовлетворяющих специфической функциональности сервера. Например, одобренный SIG сервис батареи содержит одну характеристику под названием “уровень заряда”.
Сервисы также содержат другие атрибуты, которые помогают структурировать данные сервиса, такие как объявления сервера, объявления характеристик и другие.
Вот что из себя представляют сервисы:
На рисунке мы видим различные атрибуты, составляющие сервис:
Один или несколько включенных сервисов
Одна или несколько характеристик
Свойства характеристики
Ее значение
Дескрипторы характеристики
Включение сервисов позволяет сервису ссылаться на другие сервисы как на включенные в него. Существует два типа сервисов:
Первичный сервис: предоставляет основную функцию устройства или одну из них.
Вторичный сервис: предоставляет дополнительную функциональность устройства и включен в как минимум один первичный сервис на устройстве (вторичные сервисы очень редко применяются, и еще реже возникает необходимость в них – они не будут более подробно рассматриваться в этой книге).
5.3.2 Характеристики
Характеристика всегда является частью сервиса и предоставляет часть тех данных, которые сервер хочет предоставить клиенту. Например, характеристика уровня заряда батареи показывает оставшийся уровень заряда батареи в устройстве, который может быть прочитан клиентом. Характеристика содержит набор атрибутов, которые облегчают работу с содержащимися в характеристике данными:
Свойства: представлены набором бит, определяющих то, каким образом значение характеристики может использоваться. Пример свойств: чтение, запись, запись без ответа, уведомление, индикация.
Дескрипторы: используются для хранения информации, связанной со значением характеристики. Примеры использования: расширенные свойства, пользовательское описание, поля, используемые для подписки на уведомления и индикации, поля, описывающие представление характеристики, такие как формат или единица измерения.
Понимание этих концепций важно, однако вы, как разработчик приложения, будете в основном взаимодействовать с API, предоставленным операционной системой или SDK чипсета, которые абстрагируют вас от многих этих понятий.
Например, вы можете иметь API для включения уведомлений для некоторых характеристик, который вы просто вызываете и вам нет необходимости знать, что результатом этого вызова будет запись значения 0x0001 в дескриптор конфигурации характеристик клиента (CCCD) на сервере.
Важно помнить, что, хотя нет никаких запретов или ограничений на количество характеристик, содержащихся в сервисе, сервисы предназначены для группировки связанных характеристик, которые определяют конкретные функции в устройстве.
Например, технически возможно создать сервис под названием сервис влажности, который будет включать в себя характеристику влажности и характеристику температуры. Но гораздо более логичным решением будет создать два отдельных сервиса для каждой несвязанной функции (отображение текущей температуры и отображение текущей влажности).
Стоит отметить, что Bluetooth SIG приняла довольно-таки большое количество сервисов и характеристик, которые удовлетворяют большей части распространенных сценариев использования. Для этих одобренных сервисов существуют спецификации, помогающие разработчикам реализовать их вместе с обеспечением соответствия и взаимодействия с каждым сервисом.
Если устройство заявляет о совместимости с сервисом, оно должно полностью соответствовать спецификации сервиса, опубликованной Bluetooth SIG. Это важно, если вы хотите разработать устройство, которое будет гарантированно подключаться к устройствам, изготовленными другим производителем. Сервисы Bluetooth, принятые SIG, делают соединение «предварительно согласованным» между устройствами различных производителей.
Вы можете найти список одобренных сервисов здесь, и их спецификации здесь. Одобренные характеристики находятся по этому адресу.
5.4 Профили
Профили по своему определению гораздо шире сервисов. Они занимаются определением поведения как клиента, так и сервиса, когда дело касается сервисов, характеристик и даже соединений и требований безопасности. Сервисы и их спецификации, с другой стороны, касаются реализации этих сервисов и характеристик только на стороне сервера.
Также как и в случае с сервисами, существуют одобренные SIG профили с опубликованными спецификациями к ним. В спецификации профиля вы можете найти следующее:
Определение ролей и взаимоотношений между GATT сервера и клиента.
Требуемые сервисы.
Требования сервисов.
Как используются требуемые сервисы и характеристики.
Детали требований к процессу установления соединения, включая параметры адвертайзинга и соединения.
Соображения безопасности.
Ниже в качестве примера приведена диаграмма, взятая из спецификации на профиль кровяного давления. Она показывает отношения между ролями (сервер и клиент), сервисами и характеристиками внутри профиля.
Роли представлены в виде желтых прямоугольников, сервисы – в виде оранжевых прямоугольников. Вы можете найти список профилей, одобренных SIG, здесь.
5.5 Пример GATT
Давайте посмотрим на пример использования GATT. В этом примере мы будем использовать файл GATT.xml, используемый в Silicon Labs Bluetooth Low Energy development framework (BGLib).
В этом XML-файле вы можете заметить следующее:
Определены два сервиса:
Сервис общего профиля доступа (GAP) с UUID: 0x1800 (одобрен SIG).
Сервис замены кабеля с UUID: 0bd51666-e7cb-469b-8e4d-2742f1ba77cc (Собственный сервис, определенный разработчиком приложения или производителем чипсета. Обычно так называют реализацию UART средствами Bluetooth. Например, у Nordic Semi эту роль выполняет Nordic UART Service, а у Dialog Semiconductor - Dialog Debug Service).
Сервис общего профиля доступа обязателен по спецификации и включает следующие обязательные характеристики:
Имя с UUID 0x2A00 и значением: Bluegiga CR Demo.
Окружение с UUID 0x2A01 и значением 0x4142.
Описание значений окружения приведены здесь.
Примечание: обычно создание и включение этого сервиса является задачей вендора чипсета и, обычно, разработчику предоставляется API для простой установки значений имени и окружения.
Сервис замены кабеля имеет одну характеристику под названием данные.
Характеристика данных имеет UUID: e7add780-b042-4876-aae1-112855353cc1
Включены свойства, разрешающие запись в характеристику и индикацию.
5.6 Операции с атрибутами
Существует шесть различных типов операций, которые могут производиться над атрибутами:
Команды: посылаются клиентом серверу и не требуют ответов.
Запросы: посылаются клиентом серверу и требуют ответов. Существуют два типа запросов:
Запросы на поиск информации
Запросы на чтение
Ответы: посылаются сервером клиенту в ответ на запрос.
Уведомления: Посылаются сервером клиенту с целью оповестить об изменении значения характеристики. Для получения уведомлений клиент должен включить их для интересующих характеристик. Помните, что уведомления не требуют подтверждения о получении от клиента.
Индикации: посылаются сервером клиенту. Во многом похожи на уведомления, но требуют подтверждения успешного приема клиентом.
Примечание: настройки уведомлений и индикаций представлены в атрибуте дескриптора конфигурации характеристик клиента (CCCD). Запись “1” в этот атрибут включит уведомления, запись “2” включит индикации. Запись “0” отключит как уведомления, так и индикации.
Подтверждения: посылаются клиентом серверу. Это пакеты, посылаемые с целью уведомить сервер об успешном приеме индикации клиентом.
5.6.1 Управление потоком и последовательность операций с атрибутами
Запросы последовательны по своей природе и требуют ответа от сервера перед отправкой нового запроса. Индикации имеют такое же требование: новая индикация не может быть отправлена до тех пор, пока не получено подтверждение о приеме предыдущей индикации.
Запросы и индикации являются взаимоисключающими с точки зрения требований к последовательности. То есть индикация может быть отправлена сервером до того как он ответит на запрос, который получил ранее.
Команды и уведомления отличаются, и не требуют управления потоком сообщений - они могут быть посланы в любое время. По этой причине, а также потому что сервер или клиент могут быть не в состоянии обработать эти пакеты, они считаются ненадежными. Запросы и индикации должны использоваться в случаях, когда надежность стоит во главе угла.
5.6.2 Чтение атрибутов
Чтение – это запрос по своей природе, так как оно требует ответа. Существует несколько типов запросов на чтение, но наиболее важны следующие два:
Запрос на чтение: простой запрос, ссылающийся на атрибут, который будет прочитан его дескриптором.
Запрос на чтение части данных: похож на запрос на чтение, но содержит смещение, указывающее, с какого участка чтение должно начаться, возвращая часть значения. Этот тип чтения используется для чтения только части значения характеристики.
5.6.3 Запись атрибутов
Запись может быть командой или запросом. Ниже представлены наиболее популярные типы записи:
Запрос на запись: как следует из названия, требует ответа от сервера, подтверждающего успешное получение данных.
Команда на запись: не требует ответа от сервера.
Упорядоченная запись (атомарное поведение операции): классифицируется как запрос и требует подтверждения от сервера. Они используются в случаях, когда требуется записать большое количество данных, не умещающееся в одно сообщение. Вместо того, чтобы записывать части сообщения и давать возможность кому-то прочитать некорректное неполное значение, применяются два типа запросов на запись, для того, чтобы иметь уверенность в безопасном выполнении операции:
Один или несколько запросов на подготовку к записи: каждый включает в себя смещение, с которым посылаемое значение должно быть записано в значение атрибута. Посылаемые значения также часто называют подготовленными значениями, и они хранятся в буфере на стороне сервера, еще не записанные в атрибут. Эта операция требует ответа со стороны сервера.
Один запрос на запись: используется для запроса сервера о выполнении или отмены записи принятых значений в атрибут. Требует ответа от сервера для того, чтобы клиент был уверен в том, что атрибут содержит целое и верное значение, посланное серверу.
5.6.4 Запрос на обмен MTU
Сервер и клиент согласуют общее значение MTU, использующееся для передачи данных в обоих направлениях. Запрос инициируется клиентом и может быть послан только один раз во время жизни соединения (согласно спецификации Bluetooth, version 5.0, Vol 3, Part F, Section 3.4.2.1).
Сервер отвечает особым пакетом, содержащим поддерживаемый им размер ATT_MTU. Итоговое значение будет выбрано равным меньшему из переданных между сервером и клиентом ATT_MTU.
Важно помнить, что различные версии BLE имеют разные поддерживаемые максимальные значения ATT_MTU.
5.7 Создание своего GATT
5.7.1 Общие рекомендации
Несмотря на то, что GATT это удивительно гибкий фреймворк, существуют несколько общих рекомендаций, которым нужно следовать при создании сервисов и характеристик для них:
Убедитесь, что внедрены обязательные сервисы и их характеристики:
Сервис общего профиля доступа (GAP)
Заданы характеристики имени и окружения.
Используйте одобренные Bluetooth SIG профили, сервисы и характеристики там, где это возможно. Это дает следующие преимущества:
Вы уменьшаете размер передаваемых пакетов, содержащих UUID сервисов и характеристик (включая пакеты адвертайзинга) ускоряете процедуру обнаружения и другие процедуры за счет использования 16-битных UUID вместо 128-битных.
Производители модулей и чипсетов обычно предоставляют примеры реализации этих сервисов в своих примерах и SDK - уменьшая нужное вам время на разработку.
Большее число сторонних устройств и приложений сможет взаимодействовать с вашим, тем самым расширяя число возможных пользовательских сценариев.
Группируйте характеристики, отвечающие за смежный функционал, в один сервис.
Избегайте создания сервисов, имеющий слишком большое количество характеристик. Хорошее разделение сервисов ускоряет процесс обнаружения характеристик и ведет к дружественному к пользователю модульному дизайну GATT.
В следующей главе мы рассмотрим практический пример, показывающий как разработать GATT для системы домашней автоматизации.
6. Урок создания GATT
Разработка GATT для вашего BLE устройства может быть очень сложной задачей. Для того, чтобы упростить ее, давайте пройдем полный урок создания GATT для простой системы домашней автоматизации.
Система домашней автоматизации это абстрактное нечто, но она поможет вам лучше понять шаги создания GATT для реального приложения, а не для какой-то обобщенной системы. Ниже показана схема с элементами системы “умного дома” и связями между ними.
Система состоит из множества устройств. Некоторые из них куплены в магазине, и мы не можем как-то изменить их прошивку, остальные подлежат модификации в соответствии с нашими нуждами.
6.1 Общее описание системы
Давайте опишем основные пользовательские сценарии для системы:
Владелец дома может использовать пульт дистанционного управления для включения и выключения светильника.
Владелец дома может наблюдать за изменениями показаний температуры и влажности на сенсоре окружающей среды.
Владелец дома получает уведомления об уровне заряда батареи всех элементов системы.
6.2 Элементы системы
Теперь давайте рассмотрим составляющие нашей системы.
Шлюз
Шлюз будет выполнять роль центрального BLE устройства во время обмена данными со всеми устройствами кроме смартфона, где он будет выполнять роль периферийного устройства. Мы можем контролировать это устройство и спроектируем GATT для него.
Команды для управления светильником будут поступать с пульта управления на шлюз, и с него на сам светильник.
Пульт управления
Пульт управления это устройство, которое выполняет только периферийную роль, для него мы также спроектируем GATT.Сенсор окружающей среды
Это стандартное устройство, GATT которого мы не можем изменить, так что область нашего интереса будет ограничена чтением показаний с него (данные о текущей температуре и влажности).Светильник
Это еще одно стандартное устройство, которое мы не можем каким-либо образом изменить.
Смартфон
Очередное стандартное устройство, мы будем использовать его для контроля системы.
6.3 Разработка GATT
Теперь мы пройдем пошагово весь процесс создания GATT, удовлетворяющего нашим требованиям.
6.3.1 Шаг 1: Документирование различных пользовательских сценариев
Несмотря на то, что GATT обычно больше сфокусирован на периферийной роли (так как обычно в роли сервера, предоставляющего данные, выступает периферийное устройство), центральное устройство также может выполнять роль сервера в особых случаях. Также, так как мы разрабатываем устройство, выполняющее обе роли (центральную и периферийную), это поможет нам понять, что должно произойти с каждой стороны, так как это повлияет на некоторые аспекты разработки системы и GATT.
6.3.1.1 Шлюз
Шлюз выполняет роль как центрального, так и периферийного устройства. Каждая из этих ролей используется для обеспечения связи с различными устройствами, входящими в состав системы. Основная задача шлюза как центрального устройства - считывать показания с множества периферийных устройств. Затем он, действуя в роли периферийного устройства, предоставляет собранные и обработанные данные другому центральному устройству (смартфону), который может передать эти данные на облачный сервер.
Рассмотрим пользовательские сценарии с точки зрения шлюза, для центральной и периферийной роли.
Периферийная роль
Пульт управления уведомляет шлюз, когда кнопки на нем нажимаются, для включения и выключения светильника.
Данные должны передаваться на облачный сервер через шлюз. Они представлены центральному устройству (например смартфону, имеющему доступ в интернет) в виде GATT-сервера в периферийной роли. Ниже перечень этих данных:
Показания температуры датчика окружающей среды
Показания влажности датчика окружающей среды
Статус светильника (включен или выключен)
Уровни заряда батареи пульта, светильника и датчика окружающей среды.
Центральная роль
Шлюз должен считывать некоторые данные, представленные устройствами, составляющими систему, и получать уведомления о других данных с этих устройств.
6.3.1.2 Пульт управления
Пульт управления выполняет одну функцию: управляет светильником. Он выполняет исключительно периферийную роль и должен предоставлять следующую информацию:
При нажатии кнопки “ВКЛ”: уведомить шлюз о том, что была нажата эта кнопка.
При нажатии кнопки “ВЫКЛ”: также уведомить шлюз о нажатии этой кнопки.
Уровень заряда батареи: шлюз должен иметь возможность читать данные о заряде батареи пульта и получать уведомления о его изменении.
6.3.2 Шаг 2: Настройка сервисов, характеристик и прав доступа
На этом шаге мы сгруппируем характеристики в группы (сервисы), объединяющие характеристики со схожим функционалом и зададим разрешения для каждой из них.
6.3.2.1 Шлюз
У нас есть один GATT-сервер для шлюза в периферийной роли. Посмотрев еще раз на данные, которые нам нужно передавать, мы можем назначить им характеристики и сгруппировать их в следующие сервисы:
Сервис датчика окружающей среды:
Характеристика показаний температуры датчика окружающей среды: “Температура”
Права: Чтение, уведомление.
Характеристика показаний влажности датчика окружающей среды: “Влажность”
Права: Чтение, уведомление.
Характеристика остаточного заряда аккумулятора: “Уровень заряда”
Права: Чтение, уведомление.
Сервис светильника:
Текущее состояние светильника “Статус”
Права: Чтение, уведомление.
Характеристика остаточного заряда аккумулятора: “Уровень заряда”
Права: Чтение, уведомление.
Сервис пульта дистанционного управления:
Характеристика остаточного заряда аккумулятора: “Уровень заряда”
Права: Чтение, уведомление.
Помимо этих сервисов необходимо реализовать обязательный (согласно спецификации Bluetooth) сервис:
GAP сервис:
Характеристика “имя”: имя устройства.
Права: чтение.
Характеристика местоположения: описание места, где размещено устройство.
Права: чтение.
6.3.2.2 Пульт управления
У нас есть один GATT-сервер для пульта управления. Мы можем назначить ему следующие сервисы и характеристики:
GAP сервис (обязательный):
Характеристика “имя”: имя устройства.
Права: чтение.
Характеристика местоположения: описание места, где размещено устройство.
Права: чтение.
Сервис аккумулятора:
Характеристика остаточного заряда аккумулятора: “Уровень заряда”
Права: Чтение, уведомление.
Сервис кнопок:
Характеристика кнопки “ВКЛ”
Права: уведомление.
Характеристика кнопки “ВЫКЛ”
Права: уведомление.
6.3.3. Шаг 3: Использование стандартных сервисов и характеристик
6.3.3.1. Шлюз
Сервисы датчика окружающей среды, светильника и пульта являются нашими собственными, так как не существует ни одного стандартного сервиса, который мы бы могли использовать для них. Однако у нас есть три устройства с аккумуляторами, заряд которых нам необходимо отображать и мы можем использовать стандартную характеристику уровня заряда. Мы будем использовать ее для каждого устройства в его сервисе в GATT шлюза. Также мы будем использовать обязательный GAP сервис.
6.3.3.2. Пульт управления
Для пульта управления мы можем использовать стандартный сервис уровня заряда батареи и обязательный GAP сервис.
6.3.4. Шаг 4: Присвоение UUID нашим сервисам и характеристикам
Для каждого нестандартного сервиса и характеристики мы можем использовать онлайн-инструмент для генерации UUID, например этот.
Распространенной практикой является выбор базового UUID для сервиса и увеличение значения третьего и четвертого старшего байта UUID для каждой последующей характеристики.
Для примера, возьмем следующий UUID для какого-либо сервиса:
00000001-1000-2000-3000-111122223333
И затем заменим выделенные байты на
0000000[N]-1000-2000-3000-111122223333, где N>1 - порядковый номер характеристики.
Единственное условие, которое накладывает ограничение на выбор UUID для наших сервисов и характеристик это условие несовпадения нашего UUID с базовым UUID Bluetooth SIG: XXXXXXXX-0000-1000-8000-00805F9B34FB.
Следование вышепредставленной методике выбора UUID немного упрощает понимание связей между сервисами и их характеристиками.
На таблицах ниже представлены наши сервисы, характеристики и их UUID для шлюза и пульта управления.
6.3.5. Шаг 5: Реализация сервисов и характеристик с использованием API SDK производителя платформы
Каждая платформа, встраиваемая или мобильная, имеет собственный интерфейс прикладного программирования (API, application programming interface) для реализации сервисов и характеристик. Задача читателя – самостоятельно реализовать их для выбранного им устройства или приложения.