Ловим уведомления с помощью маячков
Статья автора Ильи Гараха, в рамках конкурса «Device Lab от Google».
Но налёт радости был омрачен ограничениями устройств, ведь с BLE (Bluetooth с низким энергопотреблением) на тот момент умели работать только новые Айфоны и последние версии устройств на Android, поэтому данное решение сложно было продвинуть как рабочее для широкой аудитории. Со временем процент устройств поддерживающих BLE существенно вырос, поэтому в начале 2016 мы закупили ibeacon-маяки для тестирования. С этого все и началось.
Если вы не в курсе, ibeacon — это протокол (формат) взаимодействия по BLE придуманный Apple. На рынке есть много производителей маяков, которые передают данные в этом формате. Первым маяком, который попал в мои руки был ibeacon-маяк от фирмы «iBecom».
Его доставили в почтовом конверте, без каких-либо инструкций (собственно, как и любые другие маяки), и что с ним делать дальше я не представлял. Началась долгая переписка с технической поддержкой «iBecom», в ходе которой выяснилось, что настроить маяк можно только через приложение для iPhonne (при этом надо было отправить запросы на регистрацию в каком-то их внутреннем портале), а владельцы Android-устройств могут скачать любое приложение для управления маяками из «Play Market». Проходить квесты с iPhone мне на захотелось; приложения для Android действительно видели маяк, но ни одно из них не позволяло его настраивать, вопрос: «Так и должно быть?» остался нерешённым.
К слову, все приложения показывали разные расстояния до маяка: от 1 до 10 метров, хотя маяк лежал в нескольких сантиметрах от телефона. Это настолько умиляло, и я начал искать отзывы о реальных внедрениях. Выяснилось, что позиционирования отлично работает в тестовых комнатах, а в реальных условиях сила сигнала зависит не только от батареи и расстояния, а также от стен, перегородок, и вообще всего, что находится в помещений. Поэтому даже если у вас будет натыкано много маяков, и вы будете знать их координаты, то стриангулировать и точно определить расположение телефона скорее всего не удастся. Эта задача решается созданием «карты сигналов» для микро-локаций: расставляете маяки, берете устройство и ходите по местности, в каждой небольшой зоне сканируете маяки, считываете силу их сигналов, все это дело как-нибудь хешируете, полученный хеш будет идентифицировать микро-зону.
Небольшое отступление
Мы не занимаемся нативной мобильной разработкой, а используем Cordova. У Cordova есть свои плюсы, есть много минусов и ограничений, а так же надо уметь её готовить, но в определенных случаях плюсов больше (для нас). Поэтому здесь и далее речь будет идти исключительно о Cordova.
Так вот, для Cordova был и есть готовый плагин для работы с ibeacon. Он легко установился и довольно быстро удалось собрать первое тестовое приложение. Телефон вполне стабильно отлавливал приближение к маячку и выход из зоны «видимости». Не помню точных характеристик «iBecom» маяка, но обычно заявляют, что маяк ловится на 10 метров (а некоторые на 50 и больше). Мой телефон «терял» маяк в одной комнате при удалении от него примерно на 4 метра.
Еще одна интересная особенность заключалась в том, что для ловли маяка необходимо указывать его UUID (узнать UUID можно с помощью любого приложения для работы с BLE и маяками, UUID так же можно изменить, но для этого нужен софт от производителя)
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion('someMyld', '00000000-0000-0000-0000-000000000000');
cordova.plugins.locationManager.startMonitoringForRegion(beaconRegion);
beaconRegion = new cordova.plugins.locationManager.BeaconRegion ( 'someMyId2' , '00000000-0000-0000-0000-000000000123');
cordova.plugins.locationManager.startMonitoringForRegion(beaconRegion);
И так далее в цикле. Уведомление о маяке вернется в ваш коллбек. Таким образом, вам заранее надо знать UUID всех своих маяков, а сделать broadcast поиск невозможно (забегая немного вперед — broadcast все же возможен, хоть и через… одно место).
Поигравшись с ibeacon мы поняли, что в целом его можно использовать как дополнительную «фичу» и ловить «клиента», когда он близко подходит к маяку, например, садится за стол или подходит к товару. Использовать маяки для позиционирования в помещениях нам показалось технически возможным, но уж больно хлопотным занятием. Ну, и конечно «клиент» должен установить себе ваше приложение.
В итоге мы внедрили этот плагин в режиме теста в реальное приложение и все прошло гладко, ничего не сломалось и не стало конфликтовать (если вы не знакомы с Cordova, то проблемы с кривыми и конфликтующими плагинами — это то, на что постоянно приходится тратить время при разработке, мы любя называем эту проблему «Cordova Plugin Hell»). Убедившись, что все работает, я поставил галочку напротив ibecon и с чистой совестью отложил маяк на будущее.
Eddystone
Совершенно недавно я узнал, что кроме ibeacon существуют и другие протоколы работы маяков. Речь конечно идет про Eddystone, который придумал Google, а так же Altbeacon, который придумало сообщество. Это вернуло меня к мыслям о маякам и их возможностях, а увидев пост на Хабре о возможности протестировать Eddystone маяки, я не смог пройти мимо и подал заявку на участие. И уже через несколько недель на моем столе лежал eddystone-маяк от производителя Accent System.
Если вы не в курсе, то формат Eddystone включает в себя больше данных, чем iBeacon, который, по сути передает только 16-байтовый UUID, а так же два числа (major и minor values), а поймать эти данные можно только в вашем приложении. Eddystone позволяет маяку работать в разных режимах: так же как и iBeacon передать UUID (в eddystone он называется UID), передавать URL (который вшит непосредственно в маяк, и вы можете его настраивать), телеметрию (мета-данные маяка, теплота), а так же режим передачи EUID и циклической его смены.
Основной шик заключается в том, что телефоны на Android, которые поддерживают BLE, умеют ловить Eddystone c URL автоматически — вам не надо ставить дополнительных приложений. Просто включаете Bluetooth, подходите к маяку и ловите уведомление о том, что телефон нашел ссылку.
iPhone без костылей чужие технологии понимать не хотят, но могут ловить URL, если установлен браузер Google Chrome.
Конечно, я сразу захотел проверить эту фичу. На сайте производителя я нашел ссылку на приложение в Play Market, которое можно использовать для конфигурирования маяка. Маяк нашелся, без особых проблем я перевел его в режим конфигурирования (необходимо вытащить и вставить обратно батарею, и в течение 30 секунд маяк переходит в Dev режим). Прописал URL, всё сохранил и стал ждать, что будет дальше. И ничего не произошло.
Разумеется, на помощь придёт великий Google. Я полез читать про Google Beacon Dashboard (это облачная панель управления маяками), про Google Proximity API и NearBy API. Выяснилось, что с помощью специального мобильного приложения (Google Beacon Tool) надо поймать бекон и зарегистрировать его в облаке, после чего у бекона через веб-интерфейс можно настроить и URL, и много других параметров (аттачменты, привязка к карте и т.п.). Все это неплохо взорвало мозг и основательно запутало, но примерно спустя полдня изучения мануалов я начал понимать, что к чему.
Итак:
- Google Proximity API — это API (Java), с помощью которого вы можете подключиться к eddystone бекону и сконфигурировать его (грубо говоря некий бекенд);
- NearBy API — это API (Java), с помощью которого телефон клиента сможет получать данные из облака Гугла о маяках;
- Google Beacon Dashboard — собственно само облако, через веб можно настраивать маяки;
- Google Beacon Tool — мобильное приложение от Гугла для ловли маяков и регистрации в облаке;
- А так же у самого Eddystone маяка можно настроить URL;
- Именно вшитый в маяк URL и будет ловиться телефоном, даже без установки приложений;
Основная цель Google Beacon Dashboard и NearBy API — внедрить маяки и управлять их параметрами через веб, не разрабатывая свой бэк-енд для этого. А Google Proximity API используется, если вам нужно внедрить управление маяками в свой проект.
Проблема заключалась в том, что мой телефон упорно не хотел ловить маяк с URL. Оказалось, что у меня был запрет на поиск публичных ссылок, которые можно убрать в настройках Google в вашем Android-девайсе (именно настройки Google, а не системы, и если вы еще там не ползали, то найдете много интересного).
С этой проблемой разобрались. Ради интереса я проверил телефоны всех ближайших коллег и знакомых: ни у кого такой фигни не было и после включения Bluetoothа, все девайсы сразу поймали ссылку. Списали всё на странности настройки моего девайса.
Дальше я попытался зарегистрировать Eddystone-маяк в облаке Google, но Google Beacon Tool упорно не находило Eddystone, хотя iBeacon (от «iBecom») нашелся сразу, и с ним проблем не было. После обилия тщетных попыток я написал в саппорт производителю «Accent Systems» (к слову, если вы собираетесь обильно внедрять именно эти маяки, учтите, что само собой по-русски никто там не говорит). Ответ от «Accent Systems» я получил через 3–4 рабочих дня, что на мой скромный взгляд совсем не быстро.
В ответ мне прислали ссылку на Dropbox, где я мог скачать новую версию приложения для конфигурирования маяка и новую документацию. Новое приложение перепрошило маяк, Beacon Tool его наконец нашло. Стоит отметить, что вся эта история со скачиванием приложения по неясным ссылкам выглядит по крайней мере сомнительно для серьезного производителя устройств (и, кстати, партнера Google).
Согласно новой документации от «Accent Systems» их eddystone маяки могут одновременно вещать как 4 обычных eddystone и 2 ibeacon.
На практике же мне так и не удалось заставить работать слоты, кроме первого. К слову, осознание этого факта заняло достаточно много времени, потому что сперва я настраивал 3-ий слот и долго не мог понять почему ничего не работает.
Таким образом, мой Eddystone маяк мог вещать одновременно как ibeacon и как eddystone (в любом режиме), т.е. 1+1 вместо заявленных 4+2 одновременных слотов.
Программируем тестовое приложение
После того как с Eddystone маяком удалось наладить стабильную работу пора разработать тестовое приложение. Как я уже написал ранее — все будем делать на Cordova.
Ищем плагины для работы с eddystone для Cordova и сразу находим этот. Это плагин от компании Evothings, которая занимается разработкой и поставкой различных решений для BLE устройств.
Финальный вариант моего тестового приложения я залил на гитхаб.
Не вдаваясь в детали нашей внутренней кухни, пример сделан на базе нашего внутреннего каркаса приложений, который работает на F7 Framework и RequireJS. Весь основной код находится здесь.
Я добавил плагин (cordova-plugin-eddystone), скопировал их пример, сбилдил приложение и запустил на телефоне.
Небольшое отступление для тех, кто хочет использовать Cordova. Мы не билдим приложения локально, вместо этого развернут билд-сервер в Digital Ocean. Все это может быть интегрировано с вашим CI-решением или кустарными-скриптами. В итоге при пуше билд-сервер оповещается, pull-ит изменения и запускает билд. Весь процесс тщательно комментируется нашим ботом в Slack (с текстом из коммитов), поэтому все всегда в курсе, что билдится, и когда все готово для установки. В целом, несложно настроить обратную связь и через ADB автоматически устанавливать приложениях на телефон.
Тестировать же основную логику Cordova приложений можно в браузере, потому что по сути приложение — это обычный веб-сайт. Мы нашли этот подход крайне удобным, ведь не надо беспокоиться об окружениях, версиях Java, Cordova, какие Android Target установлены, а билд-сервер поднимается из снапшота за 1 минуту. Конечно, это история про Андроид, адаптация, билд и продакшен для ios отличаются.
Если вы решите пойти этим путем рекомендую добавить в билд удаление и добавление платформы, это избавит вас от многих проблем с плагинами.
Так вот, после билда примера, я сразу подключил дебаггер (через chrome://inspect) и увидел, что хоть пример и работает без ошибок, но беконов он не находит. И это абсолютно нормально для Cordova — плагины очень часто не работают как надо. Я начал изучать плагин cordova-plugin-eddystone и обнаружил код, который запускает BLE сканирование.
// The device object given in this callback is reused by easyble.
// Therefore we can store data in it and expect to have the data still be there
// on the next callback with the same device.
evothings.easyble.startScan(
// Scan for Eddystone Service UUID.
// This enables background scanning on iOS (and Android).
['0000FEAA-0000-1000-8000-00805F9B34FB'], function(device)
{
// A device might be an Eddystone if it has advertisementData... var ad = device.advertisementData; if(lad) return;
// With serviceData...
var sd = ad.kCBAdvDataServiceData;
if(lsd) return;
// And the 0xFEAA service.
Магическое число 0000FEAA-0000–1000–8000–00805F9B34FB — это идентификатор Eddystone-маяков. Оно передается в другие методы плагина и в итоге уходит в Java плагин. Изучаем исходный код метода evothings.easyble.startScan и понимаем, что передавать идентификатор необязательно. Убираем его и смотрим, что происходит — плагин ловит маяки, то, что нужно!
Более того, теперь плагин ловит все BLE устройства, в том числе и не маяки. И это отлично, пусть ловит, а мы уж как-нибудь решим, что делать с этими данными.
Небольшое отступление для тех, кто хочет использовать Cordova. Подключите свой телефон по USB, разрешите отладку, откройте в Google Chrome chrome://inspect и выберите свое приложение. Вы можете отлаживать его как обычный сайт, а так же прямо на лету изменять JS-код.
Ок, делаю форк плагина и начинаю вносить изменения.
Первым делом, убираем строку ['0000FEAA-0000-1000-8000-00805F9B34FB']
.
Вижу, что теперь плагин ловит и ibeacon, но отметает его на дальнейшей валидации. Читаю документацию по формату ibeacon и eddystone. Все маяки шлют Scan Record, который содержит все данные. В base64 это выглядит как-то так:
AgEGGv9MAAIVoHxcqFnrTqiZVjC3duD+3AAEAAS7DBbw/1/r3V649LuVAQAAAAAAAAAAAAAAAAAAAAAAAAA=
Конвертируем в шестнадатиричную систему:
И читаем описание Scan record для ibeacon формата:
Видим, что 6–8 байты (х4c000215) — это константы, после которых идет UUID ibeacon-а. Парсим scan record, находим эти 4 байта и считаем следующие 16 байт. Затем конвертируем все в строку к формату типа:
a07c5ca8–59eb-4ea8–9956–30b776e0fedc
(https://github.com/garakh/cordova-eddystone/blob/master/js/eddystone-plugin.js#L534 и дальше по коду).
Допиливаю другие мелочи и валидации, запускаю, проверяю — все работает как надо, теперь кроме eddystone плагин ловит и ibeacon. При этом не надо задавать заранее UUID ibeacon, ведь плагин ловит все.
Пушу плагин и приступаю в внедрению Eddystone в реальное приложение.
Продакшен
Самое время познакомить вас с одним из стартапов, в которых я принимаю активное участие.
Лоя — лояльность как сервис. Лоя даёт бизнесу возможность легко и быстро внедрить программы лояльности, предоставляя дашборд с аналитикой, API и другие инструменты.
Одна из фишек — бизнес может заказать себе мобильное приложение, где клиенты смогу копить баллы и получать подарки. А если бизнес хочет сделать быстрый старт, то может предлагать своим клиентам общее решение: клиентское приложения Лоя, в котором присутствуют и все остальные компании.
Именно в него мы и будем добавлять поддержку Eddystone. Для того, чтобы не усложнять проектируем простой алгоритм работы с маяками:
- Приложение ловит маяк, собирает его данные: MAC адрес, URL, UUID, NID+BID (это EUID у eddystone);
- Отправляет данные на сервер;
- Сервер проверяет, есть ли такой бекон у какой-либо компании;
- Если бекон есть, то возвращает текст сообщения, которое отобразим на экране, а так же шлем PUSH, мало ли телефон в кармане;
- Если приложение ловит Eddstone URL, то на сервере валидируется MAC адрес маяка, и если все ок, то открываем страницу с этим URL.
К слову, если у клиента не будет установлено нашего приложения, он все равно увидит URL, потому что Eddstone рулит.
Алгоритм для компании:
- Покупают маяк;
- С помощью любой утилиты выясняют его данные (UUID, MAC и т.п.);
- Указывают рекламное сообщение (в нашем веб-дашборде) или конфигурируют маяк в режиме Eddystone URL;
- Размещают маяк в магазине;
- Проходящие рядом покупатели видят URL или пуш нотификацию, если установлено наше приложение;
Ок, итак, добавляем в дашборд управление маяками:
К слову, фронтенд у нас работает на Angular 1.х, RequierJS, Bower, Gulp. Бекенд: PHP Phalcon, MongoDB. Прекрасная связка опробованная на многих проектах. Дописываем серверный API и переходим к программированию мобильного приложения. Т.к. все уже протестировано, то добавляем наш форкнутый плагин и наслаждаемся ловлей беконов.
Финальное видео и релиз
- Тест ibeacon (подносим бекон — видимо сообщение);
- Тест eddystone URL (подносим бекон — открывается страница);
- Билдим релиз и заливаем в Play Market;
Т.е. не все устройства поддерживают BLE держим в маркете несколько версий. Версия 0.1.0 с поддержкой беконов (будет работать на Android 5+) и 0.0.8 без поддержки (будет работать 4-х версиях Андроида).
Заключение
Было потрачено около 30 человеко-часов на изучение и тестирование и 5 часов на интеграцию в боевое приложение, разработку бэк-енда и релиз. Работа с маячками в сети до сих пор освещена скудно и запутано. Приходится общаться с саппортом производителей маячков, и по их ответам понимаешь, что у самих производителей это работает не сильно лучше.
Использовать маячки для indoor-навигации, на мой взгляд можно, но пока достаточно сомнительно, да и внедряется с большими трудозатратам. Маячок от Accent Systems так и не заработал на всех слотах.
Батарея маячка от iBecom умерла где-то через 6 месяцев (маяк просто лежал на столе), хотя заявлено чуть ли не 2–3 года работы.
Eddystone URL — на мой взгляд очень перспективная штука, не требует наличия специальных приложений и единственное, что работало из коробки без шаманства.
В сравнении Eddystone и iBeacon — eddystone однозначно выигрывает. Не вижу никакого смысла закупать ibeacon маяки, которые стоят так же, работают точно также криво, а в плане функциональности отстают на несколько лет.
Комментарии (1)
7 ноября 2016 в 15:10
0↑
↓
Такой вопрос я правильно понимаю эта технология работает только когда BlueTooth на телефон включен?