BLE под микроскопом. Часть 3
В первой и второй частях мы рассмотрели принципы построения сетей BLE, а так же затронули необходимый инструментарий для работы с ними. В третьей части мы займемся практическим применением полученных знаний. Для этих целей мы рассмотрим этот проект на микросхеме nRF51822 фирмы Nordic.
Проект реализовывает передачу данных на рекламных каналах без использования стека.
Для того, что бы запустить проект, необходима микросхема nrf51822 на любом КИТ-е, программатор J-LINK, а так же установленный SDK. Распаковываем проект и размещаем в директорию SDK, в папку где лежат примеры периферии. Это нужно для того, что бы не переписывать пути к библиотекам. Принимаемые данные можно увидеть при помощи программы nRF Connect.
Сегодня мы рассмотрим как формируется пакет для передачи по каналам BLE. Самое интересное для нас находится в файле ble_radio.c. Функцию radio_init() я позаимствовал в программе сниффера от Nordic-a. Это самая ответственная часть. Без правильной инициализации радиоканала мы вообще не увидим никакие посылки. Каждые 100 ms программа посылает в эфир три фрейма на рекламных каналах. Как формируются посылки, мы сейчас и рассмотрим.
Начинается посылка с заголовка. В зависимости от флага ble_adv_conn наше устройство будет видеться присоединяемым (ADV_IND) или не присоединяемым(ADV_NONCONN_IND). Различие между ними давалось в первой части. Здесь лишь хочется заметить, что в обоих случаях уже выставлен флаг randon-ного МАС адреса. Если же мы хотим получить public MAC адрес, то заголовочный байт будет 0х00 и 0х02 соответственно. Далее следует байт длины всего пакета и служебный нулевой байт. Я так и не разобрался зачем это нужно. В эфир он не выставляется, но если его не будет, мы получим сдвиг байтов в посылке.
Далее следует шесть байт МАС адреса и блок флагов. Здесь надо указать общий формат заполняемых данных. Сначала идет байт длины (LEN), затем идентификатор содержимого (TYPE), а затем уже сами данные (VALUE). Блок флагов — это первый блок данных, который мы можем увидеть в программе nRF Connect.
Далее записывается имя устройства. В данном случае, после байта длины, идет идентификатор 0х08. Он означает, что это сокращенное имя устройства. Если сделать идентификатор равным 0х09, имя будет видится как полное. Для нас это не принципиально, т.к. мы работаем без стека и все запросы отрабатываем сами. В случае работы со стеком, на запрос телефона полного имени, оно будет выставлено в ответной посылке. Следом за именем идет блок заводских данных и контрольная сумма. Следует заметить, что идентификатором заводских данных является байт 0xFF, следом за которым должны идти 2 байта ID производителя и сами данные. Это то поле, в котором мы можем передавать любые свои данные.
Подобным образом посылка BLE может содержать и другие данные, например UUID устройства или мощность устройства (TYPE = 0x0A). Посмотреть все идентификаторы можно здесь. А вот как выглядит эта посылка в Wireshark. Мы видим, что эта программа дает значительно больше информации для разработчика, чем nRF Connect.
Однако это ещё не всё. Если мы сформируем посылку в формате маяка (ADV_NONCONN_IND), то она будет приниматься на телефон специальной программой. Для того, что бы телефон увидел устройство в формате ADV_IND, необходимо правильно отрабатывать запрос SCAN_REQ. Как указывалось во второй части для этого мы должны своевременно выставить ответ SCAN_RSP. Эти посылки мы можем увидеть только при помощи сниффера. Они выглядят следующим образом.
В данном случае в них нет ничего интересного. Первая (SCAN_REQ), кроме заголовка, содержит MAC адреса самого телефона и нашего устройства. Вторая (SCAN_RSP) — только заголовок и MAC адрес гаджета. Однако ответная посылка может содержать и данные. Как уже говорилось ранее, это позволяет передавать больше информации на телефон. В этом случае, принцип заполнения посылки аналогичен тому, что мы рассмотрели выше. На этом третья часть, посвященная изучению посылок BLE, завершена.
Печерских Владимир
P.S. Если внимательно посмотреть функцию CheckData(), то можно увидеть, что в ней две части. Она отрабатывает как запросы SCAN_REQ(заголовок 0x03), так и CONNECT_REQ(заголовок 0x05) Это дает возможность не только получать данные на телефон, но и посылать одну команду на гаджет. В данном случае, устройство издает писк и моргает светодиодом. К сожалению, команда будет всего одна и будет выполняться при попытке присоединиться к устройству. Таким образом, мы можем, к примеру, включать/отключать лампочку не устанавливая никаких приложений на свой смартфон. Это можно делать прямо из меню «Настройки->Bluetooth» телефона.
Комментарии (10)
pecherskih
02.02.2017 22:52Он безусловно собирается. Я его сегодня собирал и настраивал. Вообще он был собран ещё на SDK7 на Keil4. Вижу именно от Keil-a у вас чего то не хватает. В принципе это не страшно. Проект был выложен как демонстрационный. Вы можете собрать его сами. Самое важное — это файл radio_init() с настройками радио.
Именно в нем вся соль. Остальное — просто обвязка.
Alexeyslav
03.02.2017 11:05Что за рекламные каналы?
shemerey
03.02.2017 11:40Имеются ввиду Advertisement channels — это каналы на которых устройство транслирует данные в эфир, на постоянной основе, через них обычно передаются данные которые генерируются на устройстве потоково. Например темпиратура с датчиков темпиратуры и т/д
Alexeyslav
03.02.2017 11:47Тогда это вовсе не рекламные каналы, а широковещательные или другой по смыслу синоним подобрать к «вещающие всем». Но никак не рекламные.
Броадкаст чтоли, или как ещё…shemerey
03.02.2017 13:09ну это вопрос к спецификации http://www.argenox.com/a-ble-advertising-primer/
pecherskih
03.02.2017 14:02Хотел бы уточнить. Эти единственные каналы передачи для маячков. И тогда, да, это каналы передачи данных на постоянной основе. Для присоединяемых устройств эти каналы служат только для спаривания гаджета и телефона. Если за определенное время, спаривания не произошло, то передача рекламных пакетов останавливается. Если спаривание произошло, то устройства переходят на работу на остальных 37 каналах.
Alexeyslav
03.02.2017 16:47Очень, очень неудачный синоним подобран к слову Advertisement в данном случае. Для этой ситуации есть более точные и конкретные понятия. Анонс, анонсирование… — что-то из этого более подходящее чем «реклама».
pecherskih
03.02.2017 19:00Если не нравится термин рекламные каналы, используйте выражение — каналы объявления. Это будет так же верно. Однако хотелось бы услышать вопросы про содержание, а не про форму. Судя по количеству ваших комментариев, вы только тем и занимаетесь что рекламируете себя (или объявляете).
x893
Конспективно.
Но если публикуете проект, то неплохо бы проверить, что он собирается.
..\..\..\..\Source\templates\arm\arm_startup_nrf51.s
..\..\..\..\Source\templates\system_nrf51.c
..\..\..\..\Source\keil_arm_uv4.lnt
Первые два я еще смогу найти. А третий?