iBeacon и Eddystone — это сервисы Apple и Google соответственно, использующие BLE (Bluetooth Low Energy) для локального позиционирования внутри помещений. Базовый принцип у обоих сервисов одинаков, отличается лишь формат передаваемых данных. Маяк (передатчик) периодически, с интервалом от долей секунды до нескольких секунд, передаёт пакеты стандарта Bluetooth LE, которые содержат помимо заголовка дополнительную информацию. Технология не предназначена для точного определения положения в помещении, а лишь для фиксирования момента приближения на некоторое близкое расстояние к маяку.
Классический пример использования маяков — музеи. Приходя в музей, вы устанавливаете на смартфон специальное приложение и отправляетесь осматривать экспозицию. Приближаясь к экспонату (маяку) на некоторое расстояние, смартфон это фиксирует и выводит на экран экскурсионную информацию.
В продаже можно найти немало готовых маяков, но сегодня мы соберем прототип собственного маяка (как iBeacon, так и Eddystone) на микроконтроллере SAML21 и BLE модуле BTLC1000 от Atmel.
Железо
Bluetooth будем реализовывать на базе платы расширения ATBTLC1000-XPRO с данным модулем. В качестве хоста используем микроконтроллер ATSAML21J18B, установленный на отладочной плате ATSAML21-XPRO-B
Генерируем пример для iBeacon
Для этого заходим на страницу Atmel | Srart — Web конфигуратор кода для микроконтроллеров Atmel. В одной из наших прошлых статей мы уже писали об использовании этого инструмента. На главной странице нажимаем кнопку Browse All Examples и в открывшемся окне выбираем отладочную плату SAM L21 Xplained Pro, а в поиске набираем строку ibeacon. Выбираем пример BLE Simple-BTLC1000 и жмем кнопку Open Selected Project:
Получившаяся по умолчанию конфигурация по-идее соответствует железу и менять тут ничего не нужно. На всякий случай, можно сравнить результат со скриншотом и жмем кнопку EXPORT PROJECT в правом верхнем углу экрана:
Ставим галочку напротив пункта Makefile (standalone), переименовываем проект и жмем кнопку DOWNLOAD PACK:
В результате скачивается файл с расширением *.atzip. В принципе это обычный архив, в котором хранится проект для Atmel Studio. Открываем файл (он должен быть ассоциирован со студией) и ждем пока запустится проект. В открывшемся диалоге меняем при желании имя проекта и путь к папке с проектом и жмем ОК:
Ждем пока проект сформируется.
Пробный запуск
В принципе, пример «из коробки» уже работает как iBeacon. Пробуем скомпилировать проект кнопкой F7.
Если компиляция прошла успешно можно залить проект в микроконтроллер для первых тестов. Рекомендую предварительно запустить терминальную программу для мониторинга дебажной информации. Встроенный отладчик EDBG определяется в системе в том числе и как виртуальный COM-порт, к которому подключен один из SERCOM’ов микроконтроллера
Запускаем свою любимую терминалку, ставим скорость 115200 и галочку DTR.
Жмем кнопку F5 для того чтобы залить прошивку. Если заливаете в первый раз, появится сообщение с просьбой выбрать используемый программатор:
В диалоговом окне указываем наш отладчик:
Жмем еще раз F5 и ждем пока запрограммируется контроллер и начнет исполняться программа. Если всё сделано правильно, в терминалке должны увидеть следующую информацию:
Теперь запускаем на телефоне любое приложение, работающее с маяками (например, iBeacon & Eddystone Scanner для Android) и мы должны увидеть нашу метку.
Немного разберемся с форматом передаваемых данных. А он, по старой традиции Apple, очень прост. Маяк из полезной нагрузки передает следующие данные:
UUID. 128-битный уникальный идентификатор группы маяков, определяющий их тип или принадлежность одной организации
Major. 16-битное беззнаковое значение, с помощью которого можно группировать маяки с одинаковым UUID
Minor. 16-битное беззнаковое значение, с помощью которого можно группировать маяки с одинаковым UUID и Major
Measured Power (уровень сигнала в 1 м от передатчика). 8-битное знаковое целое — значение индикации уровня принимаемого сигнала (RSSI), откалиброванное на расстоянии 1 м от приёмника, которое используется для определения близостимаяка к приёмнику (мобильному устройству). Измеряется в dBm.
В основном файле simple_btlc1000.c определен массив adv_data, в который и помещаются эти данные. Помимо этого, есть дополнительная служебная информация, расшифровку которой можно найти в документе Proximity Beacon
Specification на странице developer.apple.com/ibeacon.
static uint8_t adv_data[] = { 0x1a, 0xff, 0x4c, 0x00, // Company ID 0x02, 0x15, // Beacon Type // Proximity UUID 0x21, 0x8A, 0xF6, 0x52, 0x73, 0xE3, 0x40, 0xB3, 0xB4, 0x1C, 0x19, 0x53, 0x24, 0x2C, 0x72, 0xf4, 0x00, 0xbb, // Major 0x00, 0x45, // Minor 0xc5 // Measured Power };
Основное волшебство происходит в функции beacon_init(), которая вызывается непосредственно перед главным циклом в main. В ней, используя API-функцию at_ble_adv_data_set мы сообщаем модулю какие именно данные мы хотим передавать (тот самый массив adv_data), а далее используя функцию at_ble_adv_start запускаем сам процесс передачи с указанием частоты их передачи (BEACON_ADV_INTERVAL).
static void beacon_init(void) { static at_ble_handle_t service; /* establish peripheral database */ if (at_ble_primary_service_define(&service_uuid, &service, NULL, 0, chars, 2) != AT_BLE_SUCCESS) DBG_LOG("Failed to define the primary service"); /* set beacon advertisement data */ if(at_ble_adv_data_set(adv_data, sizeof(adv_data), scan_rsp_data, sizeof(scan_rsp_data)) != AT_BLE_SUCCESS) DBG_LOG("BLE Beacon advertisement data set failed"); /* BLE start advertisement */ if(at_ble_adv_start(AT_BLE_ADV_TYPE_UNDIRECTED, AT_BLE_ADV_GEN_DISCOVERABLE, NULL, AT_BLE_ADV_FP_ANY, BEACON_ADV_INTERVAL, BEACON_ADV_TIMEOUT, BEACON_ABSOLUTE_INTERVAL_ADV) != AT_BLE_SUCCESS) { DBG_LOG("BLE Beacon advertisement failed"); ble_device_disconnected_ind(); } else { DBG_LOG("Advertisement started"); ble_device_connected_ind(); } }
Переделываем проект под маяки Eddystone от Google
Для этого требуется сделать всего одну вещь — изменить передаваемый массив данных в функцию at_ble_adv_data_set. Заведем отдельный массив и заполним его. Про формат пакета можно прочитать тут. В отличии от iBeacon, Eddystone на данный момент может передавать 3 типа пакетов. Идентификатор типа передается в одном из байтов посылки:
Мы будем передавать ссылку.
Формат записи самой ссылки можно подсмотреть на этой странице.
Eddystone-URL HTTP URL encoding
Примечание: домена .ru в списке поддерживаемых нет. Мне очень хотелось, чтобы ссылка была живая, поэтому я напишу geektimes.com, т.к. с него есть редирект на geektimes.ru, а вот habrahabr.com аналогичным образом в домен .ru не перенаправляется.
В итоге получаем следующий пакет для Eddystone:
static uint8_t eddystone_data[] = { 0x03, 0x03, 0xaa, 0xfe, 0x10, // длина 0x16, 0xaa, 0xfe, // 16-bit Eddystone UUID 0x10, // Frame Type: 0x10 для URL 0xf0, // TX Power 0x00, // URL Scheme: http://www. 'g', 'e', 'e', 'k', 't', 'i', 'm', 'e', 's', 0x00, // .com/ };
Не забываем указать в API новый пакет:
at_ble_adv_data_set(eddystone_data, sizeof(eddystone_data), scan_rsp_data, sizeof(scan_rsp_data)) != AT_BLE_SUCCESS)
Компилим, заливаем, смотрим результат.
На этом всё, до новых встречь. Теперь уже на просторах хабра.
ссылка на оригинал статьи http://habrahabr.ru/post/273865/
Добавить комментарий