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, калі Controller і Host рэалізаваны на розных чыпах. За фармаванне пакетаў, дзяленне на кадры, кантролем памылак і зборку пакетаў адказвае Logical Link Control and Adaptation Protocol (L2CAP). За шыфраванне пакетаў адказвае Security Manager Protocol (SMP). Профіль агульнага доступу (GAP) адказвае за першапачатковы абмен дадзенымі паміж прыладамі, для вызначэння "Who is who". Да яго таксама ставяцца scanning і advertising. У гэтым артыкуле я спынюся на двух астатніх частках пратаколу - GATT і ATT. GATT з'яўляецца надбудовай над ATT, таму яны моцна пераплецены.

BLE пад мікраскопам (ATTы GATTы...)

Для спрашчэння апавядання, я б хацеў звярнуцца да аналогіі. Я яе недзе чуў і хацеў бы падтрымаць. Уявіце сабе BLE прыладу ў якасці кніжнай шафы з некалькімі паліцамі. Кожная паліца - гэта асобная тэматыка. Напрыклад, у нас ёсць паліцы з фантастыкай, матэматыкай, энцыклапедыямі. На кожнай паліцы стаяць кнігі з пазначанай тэмай. А ў некаторых кнігах ёсць нават папяровыя закладкі з запісамі. Акрамя таго, у нас ёсць невялікі папяровы каталог усіх кніг. Калі падушыце школьныя бібліятэкі — гэта вузкая скрыня з папяровымі карткамі. Пры такой аналогіі шафа - гэта профіль нашага прылады. Паліцы - гэта сэрвісы, кнігі - характарыстыкі, а каталог - гэта табліца атрыбутаў. Закладкі ў кнігах — гэта дэскрыптары, пра якія я таксама раскажу пазней, больш падрабязна.

Усе, хто распрацоўваў прылады, ведае, што ў шматлікіх праектах ёсць падобныя кавалкі кода. Справа ў тым, што многія прылады маюць падобны функцыянал. Да прыкладу, калі прылады працуюць ад акумулятараў, то праблема зарадкі і кантролю іх узроўня, будзе аднолькавай. Тое ж датычыцца і датчыкаў. Уласна, аб'ектна-арыентаваны падыход у праграмаванні "дае магчымасць ствараць аб'екты, якія злучаюць уласцівасці і паводзін у самастойны саюз, які затым можна шматразова выкарыстоўваць". На мой погляд, у BLE была зроблена спроба падобнага падыходу. Групай Bluetooth Special Interest Group (SIG) былі распрацаваны профілі. Прылады ад розных вытворцаў, якія маюць аднолькавыя профілі, павінны без працы працаваць сябар з сябрам. Профілі ў сваю чаргу складаюцца з сэрвісаў, а сэрвісы з характарыстык, якія дапаўняюцца дэскрыптарамі. У агульным выпадку гэта можа выглядаць так:

BLE пад мікраскопам (ATTы GATTы...)

Для прыкладу, разгледзім схему профіля heart rate monitor (фітнес бранзалет). Ён складаецца з двух сервісаў і некалькіх характарыстык. З яе адразу становіцца зразумелая іерархія профіля. Характарыстыка кантрольнай кропкі скідае агульны падлік выдаткаў калорый у нуль.

1. Сэрвіс сардэчнага рытму ўключае тры характарыстыкі (0x180D):
    a) Абавязковая характарыстыка частаты сардэчных скарачэнняў (0х2A37)
    б) Апцыйная характарыстыка становішча датчыка цела (0x2A38)
    в) Умоўная характарыстыка кантрольнай кропкі сардэчнага рытму (0x2A39)
2. Сэрвіс абслугоўвання батарэі (0x180F):
    a) Абавязковая характарыстыка ўзроўню зарада батарэі (0x2A19)

UUID

Для таго, каб мы маглі адназначна звяртацца да элементаў профіля (сэрвісам, характарыстыкам і дэскрыптарам) трэба ўсё іх як то пранумараваць. Для гэтай мэты ўводзяць такое паняцце як Universally Unique ID (UUID) ці Ўніверсальны ўнікальны ідэнтыфікатар. У дужках кожнага радка як раз і пазначаны UUID. І тут ёсць адна асаблівасць. Для UUID вырашылі выкарыстоўваць код даўжынёй 16 і 128 біт. Навошта, спытаеце вы? У пратаколе BLE усё падпарадкавана захаванню энергіі. Таму памернасць у 16 ​​біт суцэль разумная. Ці наўрад у найблізкай будучыні будзе створана больш 65тыс. унікальных сэрвісаў і характарыстык. На дадзены момант усё што маглі, ужо палічылі (памятайце адкуль гэта - «ён і вас палічыў» :-)) Пранумараваныя элементы профіляў, сэрвісаў, характарыстык и дэскрыптараў вы можаце паглядзець па спасылках.

Аднак, я думаю, усё памятаюць гісторыю з чатырма байтамі IP адрасы ў інтэрнэце. Спачатку думалі што хопіць, а зараз усё ніяк не пяройдзем на 4-бай байтны адрас. Што б не паўтараць гэтай памылкі і даць прастор гарэзлівым ручкам самаробаў, SIG адразу вырашыла ўвесці яшчэ і 6-мі бітныя UUID. Гэта асабіста мне нагадвае неліцэнзійны дыяпазон 128Мгц, які быў дадзены на водкуп разнастайным Кулібіным ад радыёканала. У нашым выпадку, на водкуп быў аддадзены 433-мі бітны ідэнтыфікатар сэрвісаў і характарыстык. Гэта азначае, што мы, для сваіх сэрвісаў і прылад, можам выкарыстоўваць практычна любое 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. У нашай асацыяцыі з кніжнай шафай - гэта нумар карткі ў папяровым каталогу. Аналагічна, як у каталогу бібліятэкі, карткі размяшчаюцца ў парадку павелічэння нумара. Нумар кожнага наступнага радка павінен быць больш папярэдняга. Як і ў бібліятэцы, часам губляюцца некаторыя карткі, так і ў нас - у нумарацыі радкоў могуць быць прамежкі. Гэта дапускаецца. Галоўнае, што б яны ішлі па нарастальнай.

Тып атрыбуту вызначае, што ўяўляе сабой дадзены атрыбут. Па аналогіі з мовай Сі,
дзе ёсць булевыя, лікавыя зменныя і радкі, так і тут. Па тыпе аттрыбута мы даведаемся
з чым мы маем справу і як нам далей з гэтым атрыбутам працаваць. Ніжэй мы разгледзім некаторыя спецыфічныя тыпы аттрыбут. Напрыклад "сэрвісная дэкларацыя" (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 роўную 0х2902. Пры дапамозе гэтага дэскрыптара кліент мае магчымасць уключыць на серверы індыкацыю ці натыфікацыю. Розніца паміж імі невялікая, але ўсё ж ёсць. Натыфікацыя не патрабуе пацверджання ў атрыманні з боку кліента. Індыкацыя ж гэтага патрабуе, хоць яна і адбываецца на ўзроўні GATT, не даходзячы да ўзроўню дадатку. Навошта так, спытаецеся вы? Нажаль, гэта мне не вядома. Скажу толькі, што адмыслоўцы Nordic-а рэкамендуюць выкарыстоўваць натыфікацыю. Тым больш, што праверка цэласнасці пакета (пры дапамозе CRC) адбываецца ў абодвух выпадках.

Заключэнне

У канцы артыкула я хацеў бы сказаць вось пра што. Апошняя табліца некалькі заблытаная. Аднак я спыніўся на ёй з-за таго, што яна прыводзіцца ў артыкуле, на якую я абапіраюся. У другой частцы свайго артыкула я маю намер паглыбіцца ў спецыфікацыю BlueTooth 4.0. Там нас чакаюць больш карэктныя схемы і малюнкі. У трэцяй частцы, я жадаў бы разабраць лог, атрыманы пры дапамозе праграмы Wireshark ад аднаго з гаджэтаў і ўбачыць "у жывую" усю тую тэорыю, якую мы з вамі вывучаем.

Супрацоўнік Групы Кампаній "Цэзар Сатэліт"
Пячэрскіх Уладзімір

Крыніца: habr.com

Дадаць каментар