BLE под микроскопом (ATT и GATT…)

BLE под микроскопом (ATTи GATTи...)

BLE под микроскопа (ATT протоколи GATT…)

Част 1, преглед

Премина доста време откакто беше публикувана първата спецификация на Bluetooth 4.0. И въпреки че темата за BLE е много интересна, тя все още плаши много разработчици заради своята сложност. В предишните си статии разглеждах основно базовите нива Link Layer и Physical Layer. Това позволи да не се налага да навлизам в сложни и заплетени понятия като протокол атрибути (ATT) и общ профил атрибути (GATT). Но няма как да се избегне, без да се разберат тези концепции, не може да се разработват съвместими устройства. Днес искам да споделя с вас тези знания. В статията си ще се опра на учебник для начинаещи от сайта Nordic. И така, да започнем.

Защо всичко е толкова сложно?

Според мен още от самото начало беше ясно, че управлението на устройства чрез смартфони е много перспективна и дългосрочна тема. Затова решиха да я структурират веднага и по максимален начин, за да не създават производителите на различни джаджи свои собствени протоколи, които след това да не са съвместими. От тук и сложността. Още на първия етап в протокол BLE опитаха да вкарат всичко, което било възможно. И не е важно дали ще е нужно в бъдеще или не. Освен това беше предвидена възможност за разширяване на списъка с устройства в бъдеще.

Нека да погледнем изображението, където е нарисувана схемата на протокола BLE. Той се състои от няколко слоя. Най-долният, физическият слой (PHY), отговаря за радиоканала на устройството. Link Layer (LL) съдържа цялата последователност от байтове в предаваното съобщение. В предишните статии изучавахме точно него. Host Controller Interface (HCI) е протокол за обмен между слоевете или чиповете на BLE, ако контролерът и хоста са реализирани на различни чипове. За формирането на пакети, разделянето на фреймове, контрол на грешките и събирането на пакети отговаря Logical Link Control and Adaptation Protocol (L2CAP). За криптирането на пакетите отговаря Security Manager Protocol (SMP). Профилът на общ достъп (GAP) отговаря за първоначалния обмен на данни между устройствата, за да определи „Кой е кой“. Към него принадлежат и сканирането и реклама. В тази статия ще се спра на двете оставили части на протокола - GATT и ATT. GATT е надстройка над ATT, затова те са много взаимосвързани.

BLE под микроскопом (ATTи GATTи...)

За да опростяNarrativто, бих искал да се обърна към аналогия. Чух я преди време и бих искал да я споделя. Представете си BLE устройство като библиотека с няколко рафта. Всеки рафт представлява отделна тема. Например, имаме рафтове с фантастика, математика, енциклопедии. На всеки рафт стоят книги с указаната тема. А в някои книги има дори хартиени книги отметки с бележки. Освен това, имаме малък хартиен каталог на всички книги. Ако помните училищните библиотеки — това е тесен шкаф с хартиени карти. При тази аналогия шкафът е профилът на нашето устройство. Рафтовете са услугите, книгите са характеристиките, а каталогът — таблицата на атрибутите. Отметките в книгите са дескрипторите, за които също ще говоря по-късно в по-подробен вид.

Всички, които разработват устройства, знаят, че в много проекти има сходни фрагменти код. Става въпрос за това, че много устройства имат подобна функционалност. Например, ако устройствата работят на батерии, проблемът с зареждането и контрола на нивото им ще бъде един и същ. Същото важи и за сензорите. Всъщност, обектно-ориентираният подход в програмирането „дава възможност за създаване на обекти, които свързват свойства и поведения в самостоятелен съюз, който след това може да се използва многократно“. На моя поглед в BLE бе направен опит за подобен подход. Групата Bluetooth Special Interest Group (SIG) разработи профили. Устройства от различни производители, които имат еднакви профили, трябва да работят безпроблемно помежду си. Профилите от своя страна се състоят от услуги, а услугите от характеристики, допълвани от дескриптори. В общи линии това може да изглежда така:

BLE под микроскопом (ATTи GATTи...)

За пример, разгледайте схемата на профила на монитор за сърдечен ритъм (фитнес гривна). Той се състои от две услуги и няколко характеристики. От него веднага става ясна йерархията на профила. Характеристиката на контролна точка нулира общия брой на разходваните калории.

1. Услугата за сърдечен ритъм включва три характеристики (0x180D):
    a) Задължителната характеристика на сърдечната честота (0x2A37)
    б) Опционалната характеристика на позицията на сензора на тялото (0x2A38)
    в) Условната характеристика на контролна точка на сърдечния ритъм (0x2A39)
2. Услугата за поддръжка на батерията (0x180F):
    а) Задължителна характеристика на нивото на заряда на батерията (0x2A19)

UUID

За да можем недвусмислено да се обръщаме към елементите на профила (услуги, характеристики и дескриптори), е нужно всичко да бъде номерирано. За тази цел се въвежда понятието Universally Unique ID (UUID) или Универсален уникален идентификатор. В скобите на всяка линия е посочен UUID. И тук има една особеност. За UUID решиха да използват код с дължина 16 и 128 бита. Защо, ще питате? В протокола BLE всичко е подчинено на спестяване на енергия. Затова размерът от 16 бита е напълно разумен. Малко вероятно е в близкото бъдеще да бъдат създадени повече от 65 хиляди уникални услуги и характеристики. Към момента всичко, което можеха, вече е изчислено (помнете откъде е това — „той и вас е броил“ :-)) Номерираните елементи профили, услуги, характеристики и дескриптори можете да видите по линковете.

Въпреки това, мисля, че всички помнят историята с 4-те байта IP адреса в интернет. Първоначално си мислехме, че е достатъчно, а сега все не можем да преминем на 6-байтов адрес. За да не повтаряме тази грешка и да дадем пространство на изобретателите, SIG незабавно реши да въведе и 128-битови UUID. Лично на мен това ми напомня на нелицензирания диапазон 433МГц, който беше предоставен на всевъзможни Кулибини в радиоканалите. В нашия случай, на разположение бе предоставен 128-битен идентификатор на услуги и характеристики. Това означава, че можем да използваме практически всяко 128-битово значение за нашите услуги и устройства. Вероятността да създадем идентичен UUID е почти нула.

Всъщност, кратките 16-битови UUID имат своя разширение до 128-битово значение. В спецификацията това разширение се нарича Bluetooth Base UUID и има стойност 00000000-0000-1000-8000-00805F9B34FB. Например, ако 16-битовият UUID на атрибута има стойност 0x1234, то еквивалентният 128-битов UUID ще има стойност 00001234-0000-1000-8000-00805F9B34FB. И дори е приведена съответната формула:

                                128_bit_value = 16_bit_value * 2^96 + Bluetooth_Base_UUID

Откуда произлиза това магическо число, не ми е известно. Ако някой от читателите знае — нека напише в коментарите (Потребител с ник Sinopteek вече го направи. Вижте коментарите). Що се отнася до създаването на 128-битови UUID, принципно може да се използва специален генератор, който ще го направи вместо вас.

ATTи GATTи…

Същността на темата започва сега. Искам да напомня, че ATT е основан на клиент-сървърна архитектура. В момента разглеждаме устройството на сървъра. То съдържа информация като стойности на сензори, състояние на светлинен ключ, данни за местоположение и т.н. Сега, след като всички 'участници на нашия парад' са пронумерирани, трябва да ги разположим в паметта на устройството. Затова ги поставяме в таблица, наречена таблица на атрибутите. Запомнете добре това. Това е сърцето на BLE. Именно него ще разглеждаме по-нататък. Сега всяка редица ще наричаме атрибут. Тази таблица се намира дълбоко в стека и обикновено нямаме пряк достъп до нея. Инициализираме я и я извикваме, но какво се случва вътре в нея, остава скрито за нас.

Нека разгледаме изображение от спецификацията, но преди това искам да обърна внимание на често срещаната бъркотия в терминологията, а именно в дескрипторите. Ролята на дескриптора е да допълни описанието на характеристиката. Когато трябва да се разширят нейните функции, тогава се използват дескриптори. Те също са атрибути и заедно със сервисите и характеристиките се намират в таблицата на атрибутите. Ще ги разгледаме подробно във втората част на статията. Въпреки това, понякога дескрипторите се наричат номер на реда в таблицата на атрибутите. Това трябва да имате предвид. За да не се объркваме, за тези цели ще използваме термина 'указател на атрибут'.
BLE под микроскопом (ATTи GATTи...)

И така, атрибутът е дискретна стойност, която има следните свойства, свързани с него:
1. Указател на атрибут (Attribute Handle) — това е индексът на таблицата, съответстващ на атрибута.
2. Тип на атрибут (Attribute Type) — това е UUID, който описва неговия тип.
3. Стойност на атрибут (Attribute Value) — това са данните, индексирани с указателя на атрибута.
4. Разрешения на атрибутите (Attribute Permissions) — това е част от атрибута, разрешения, които не могат да бъдат прочетени или записани чрез протокола на атрибутите.

Как да разберем всичко това? Указателят на атрибута — това е, условно казано, неговият номер в нашата таблица.
Той позволява на клиента да се позовава на атрибута в заявки за прочит или запис. Можем да номерираме нашите редове (атрибути) от 0x0001 до 0xFFFF. В нашата асоциация с библиотечен шкаф – това е номерът на картата в хартиения каталог. Подобно на библиотечния каталог, картите са подредени по нарастващ номер. Номерът на всеки следващ ред трябва да бъде по-голям от предишния. Както в библиотеката, понякога се губят определени карти, така и при нас – в нумерацията на редовете могат да бъдат пропуски. Това е допустимо. Важно е да следвате нарастващ ред.

Типът атрибут определя какво представлява даденият атрибут. По аналогия с езика C,
където има булеви, числови променливи и низове, тук е същото. По типа атрибут разбираме
с какво имаме работа и как можем да работим с този атрибут по-нататък. По-долу ще разгледаме някои специфични типове атрибути. Например „сервизна декларация“ (0х2800), „декларация за характеристики“ (0х2803), „декларация за дескриптор“ (0x2902).

Стойността на атрибута – това всъщност е самата му стойност, извинете за тавтологията. Ако типът на атрибута е низ, то стойността на атрибута може да бъде например слоганът „Hello World !!!“. Ако типът на атрибута е „сервизна декларация“, то стойността му е самият сервиз. А понякога това е информация къде да намерите други атрибути и техните свойства.

Разрешенията на атрибутите позволяват на сървъра да разбере разрешен ли е достъпът до четене или запис.
Обърнете внимание, че тези разрешения се прилагат само към стойността на атрибута, а не към указателя, типа и самото поле на разрешенията. Т.е. ако записът на атрибута е разрешен, можем да променим например, реда „Hello World !!!“ на реда „Good morning“. Но не можем да забраним запис на нов ред или да променим типа на атрибута и да обозначим реда като „сервизна декларация“. Когато клиентът се свързва със сървъра, клиентът запитва за неговите атрибути. Това позволява на клиента да узнае какво може да предостави сървърът. Въпреки че не е задължително да се четат и записват стойности.

Как изглежда

Концепцията GATT е да групира атрибутите в таблицата на атрибутите заедно в много специфичен и логичен ред. Нека погледнем по-внимателно профила на сърдечния ритъм, представен по-долу. Най-лявата колона на тази таблица не е задължителна. Тя просто описва какво представлява този ред (атрибут). Всички останали колони вече ни са познати.

BLE под микроскопом (ATTи GATTи...)

В горната част на всяка група винаги имаме атрибут за обявяване на услугата. Неговият тип винаги е равен на 0x2800, а указателят зависи от това колко атрибута вече присъстват в таблицата. Неговите разрешения са винаги само за четене, без каквато и да е проверка на самоличността или авторизация. За тези понятия ще говорим по-късно. Стойността — това е още един UUID, който определя каква е тази услуга. В таблицата стойността е равна на 0x180D, която Bluetooth SIG определя като услуга за сърдечен ритъм.

След обявлението на услугата следва обявлението на характеристиката. По форма то е аналогично на обявлението на услугата. Неговият UUID винаги е 0x2803, а разрешенията също винаги са само за четене, без каквато и да е проверка на самоличността или авторизация. Нека разгледаме полето Attribute Value, което включва някои данни. То винаги съдържа указател, UUID и набор от свойства. Тези три елемента описват последващото обявление на стойността на характеристиката. Указателят естествено обозначава мястото на обявлението на стойността на характеристиката в таблицата на атрибутите. UUID описва какъв тип информация или стойност можем да очакваме. Например, стойността на температурата, състоянието на ключа за осветление или някаква друга произволна стойност. И накрая, свойствата, които описват как можем да взаимодействаме с характеристичната стойност.

Тук ни очаква още едно подводно камъче. То е свързано с разрешенията на атрибутите и свойствата на характеристиките. Нека погледнем изображението на полета от спецификацията.

BLE под микроскопом (ATTи GATTи...)

Както виждате, тук също присъстват полета, даващи възможности за четене и запис. Можете да се запитате, защо имаме разрешения за четене/запис за атрибута и свойството.
четения/записи за стойността на характеристиката? Не трябва ли те да са винаги еднакви? Работното е, че свойствата за стойността на характеристиката, всъщност, са само препоръки за клиента, използвани в ГАТТ и приложните слоеве. Това са просто указания за това, какво клиентът може да очаква от атрибута на обявлението за характеристиката. Нека разгледаме това по-подробно. Какви видове разрешения има атрибутът?

1. Разрешения за достъп:
     — четене
     — запис
     — четене и запис
2. Разрешение за автентикация:
     — изисква се автентикация
     — не се изисква автентикация
3. Разрешение за авторизация:
     — изисква се авторизация
     — не се изисква авторизация

Основната разлика между разрешенията на атрибутите и свойствата на характеристиките е, че първите се отнасят до сървърите, а вторите до клиентите. Сървърът може да има разрешение за четене на стойността на характеристиката, но да изисква автентикация или авторизация. Затова при заявка от клиента за свойствата на характеристиката, ще получим, че четенето е разрешено. Но при опит за четене ще получим грешка. Затова може спокойно да се говори за приоритет на разрешенията над свойствата. Знанието за това, какви разрешения има атрибутът, не можем да получим от страна на клиента.

Дескриптор

Нека се върнем към нашата таблица. След обявяването на стойността на характеристиката, могат да бъдат направени следните обявления на атрибути:
1. Ново обявление на характеристиката (в услугата може да има много характеристики)
2. Нова декларация на услугата (в таблицата може да ги има много)
3. Обявление на дескриптора

В случай на характеристика на измерването на честотата на сърдечните съкращения, в нашата таблица, обявяването на стойността на характеристиката е съпроводено с обявяване на дескриптора. Дескрипторът е атрибут с допълнителна информация за характеристиката. Има няколко вида дескриптори. За тях ще говорим подробно във втората част на тази статия. Сега ще се занимаваме само с дескриптора на конфигурацията на клиентските характеристики (Client Characteristic Configuration Descriptor — CCCD). Той има UUID равен на 0x2902. С помощта на този дескриптор клиентът има възможност да включи индикация или нотификация на сървъра. Разликата между тях е малка, но все пак съществува. Нотификацията не изисква потвърждение за получаване от страна на клиента. Индикацията обаче изисква такова потвърждение, въпреки че то се извършва на ниво GATT, без да достига до нивото на приложението. Защо е така, ще питате вие? Уви, не ми е известно. Ще кажа само, че специалистите от Nordic препоръчват използването на нотификация. Освен това проверката за целостта на пакета (чрез CRC) се извършва и в двата случая.

Заключение

В края на статията искам да кажа следното. Последната таблица е малко объркваща. Въпреки това, се спрях на нея, защото се извежда в статията, на която се опирам. Във втората част на статията си имам намерение да се задълбоча в спецификацията на BlueTooth 4.0. Там ни очакват по-коректни схеми и рисунки. В третата част искам да разгледам лог, получен с помощта на програмата Wireshark от едно от устройствата и да видя "на живо" цялата теория, която изучаваме.

Служител на Групата Компании «Цезар Сателлит»
Печерских Владимир

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster