Делаем стартап просто и технологично. Маячки Eddystone

Вы когда-нибудь были в Лувре? Добрались до Мона-Лизы? Если да, то наверняка вы увидели лишь большую очередь перед ней, а саму картину лишь издалека и не в полный размер. Люди хотят изучить подробнее полотно, запомнить каждую его деталь, узнать о нем все подробности, поэтому они надолго остаются рядом с ним. Но что, если всю эту информацию перенести прямо в смартфон? Сделать так, чтобы картина сама рассказала устройству о себе, а оно передало информацию вам?

de641d14d39546ef86fc98165e3742f7.jpg
Статья автора Алексея Набережного, в рамках проекта «Devces Lab от Google».

В этой статье мы опишем технологии iBeacon и Eddystone, которые вполне могут решить нашу проблему. Эти технологии используют маленькие Bluetooth Low Energy устройства — так называемые маячки. Мы расскажем, что такое маячки, как они устроены и как с ними работать.

Маячок для инженера-программиста


Посмотрим, что из себя представляет маячок. На обзор habrahabr.ru предоставил модель iBKS105, произведённую Accent Systems. Маячок представляет из себя небольшую круглую коробочку с наклеенным двусторонним скотчем с одной стороны для удобного закрепления на любых поверхностях, например, на стекле магазина.
6dff9e4daf1eebb72d71d0ac1e661d66.png

Вот так он выглядит:

649ef6d18ad142e1893bee4cc47d77b7.jpg

Маячок может работать от одной батарейки CR2477 целых 40 месяцев благодаря BLE модулю NRF51822, произведённому компанией Nordic Semiconductors. При этом iBKS105 поддерживает протоколы iBeacon и Eddystone, посылая максимум 5 Advertisment-пакетов (1 для iBeacon и 4 для Eddystone).

iBeacon, закрытая технология, представленная Apple в 2013 году, предусматривает трансляцию одного пакета, содержащего UUID (16 байт), Major и Minor (ещё по 2 байта), а также TX Power (1 байт): итого 21 байт. UUID обычно используется для определения приложения, работающего с маячком, Major — для определения группы маячков, а Minor — для определения номера маячка в группе. Apple предлагает использовать утилиту UUIDGEN для генерации этой информации и приводит следующий пример определения маячка в магазине.

ff06059aa04a9bedc60033579f2feb9b.png

Apple предлагает закрытый стандарт настройки маячков. Однако для получения информации о нем необходимо получить лицензию iBeakon License.

Технологию Eddystone придумала Google в июле 2015. В отличие от iBeacon, стандарт Eddystone является открытым и поэтому поддерживается устройствами на базе любых операционных систем. Eddystone может куда больше, чем его конкурент: он транслирует до 4-х пакетов даных — Eddystone-UID (20 байт), Eddystone-URL (до 20 байт), Eddystone-TLM (14 или 18 байт) и, с 14 марта 2016, Eddystone-EID (10 байт). Eddysone-UID — это аналог пакета, используемого в iBeacon, в то время как Eddystone-URL передает какой-либо URL адрес, который может быть открыт на устройстве, принимающем пакет. Eddystone-TLM пакет содержит телеметрическую информацию, такую как напряжение батареи передатчика, температура окружающей среды, время с момента включения и др. Eddystone-EID (Ephemeral IDs) является зашифрованным идентификатором, позволяющим регистрировать маячок в WEB сервисах. Он поддерживает AES-шифрование, равно как Eddystone-TLM последней версии. В целях безопасности при установлении связи устройства обмениваются открытыми ключами, а маячок меняет идентификатор псевдо-случайно (с промежутком от 1 секунды до 9 часов). Для настройки Eddystone маячков Google изобрела открытый стандарт GATT Configuration Service. Подробнее про протокол Eddystone можно узнать по ссылке на Github.

Настройка маячка


Как уже было сказано, наш маячок умеет работать как с iBeacon, так и с Eddystone. Accent Systems выпустила приложения iBKS Config Tool для iOS и Android, позволяющие настраивать их маячки. По умолчанию маячок может войти в режим настройки только в первые 30 секунд после включения, так что, приобретая маячок, не спешите вытягивать защитный язычок! В противном случае маячок придется открыть и извлечь батарейку, а после вставить её обратно.

Приложение для Android имеет больше преимуществ, так как позволяет видеть телеметрическую информацию. При попытке подключения к маячку будет запрошен пароль, записанный в энергонезависимую память, если он был установлен.

4cd8fefc4ee340fabf03de68ba7cbd13.jpg

Затем можно выбрать режим, в котором работает маячок — iBeacon, Eddystone UID, Eddystone URL или смесь этих режимов. Eddystone-EID пакеты рассылаются, если включен один из режимов Eddystone.

ff09a2f76e004f898865888a2ac8c1b5.jpg

Дальше уже можно попробовать и иные виды настроек:

  • выбрать силу сигнала, частоту рассылки пакетов (0.1 — 10 секунд);
  • установить пароль, выбрать URL и UID;
  • активировать режим разработчика, позволяющий подключаться к маячку в любое время и передавать телеметрические пакеты в режиме iBeacon;
  • выполнить калибровку для передачи параметра силы сигнала. Такая настройка желательна для новых маячков. Чтобы её выполнить, нужно замерить силу на определенном расстоянии от маячка и вписать её в нужное поле конфигуратора.

Обратите внимание, что, если на устройстве не установлено никаких приложений, работающих с маячками, iOS никак не отреагирует на их появление, в то время как Android должен показать уведомление (используя Google Play Services). Мы проверяли маячки с помощью iPhone. Как выяснилось, сделать это проще всего, воспользовавшись Google Chrome.
ad81a128a7cd1075d8bb283389e45b02.png

Inside Android SDK


Попробуем посмотреть на то, что посылает нам маячок.

Создадим тестовый проект BeaconNotifier и добавим permissions BLUETOOTH и BLUETOOTH_ADMIN. Также разметим наши будущие Reciever и Service: Reciever будет отлавливать изменение состояния Bluetooth, а Service — искать наши маячки.

   <uses-permission android:name="android.permission.BLUETOOTH" />
   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
   <application …>
       <activity android:name=".MainActivity">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
           intent-filter>
       activity>

       <receiver android:name=".BTReceiver">
           <intent-filter>
               <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
               <action android:name="ru.racoondeveloper.beaconnotifyer.WAKE_RECEIVER"/>
           intent-filter>
       receiver>
       <service android:name=".BService" />
   application>

Reciever отлавливает два Action — включение, выключение Bluetooth, а также интент, который мы сами будем отсылать при открытии приложения, чтобы в первый раз оживить наш сервис.

public class BTReceiver extends BroadcastReceiver {
   private Intent BServiceIntent;

   @Override
   public void onReceive(Context context, Intent intent) {
       final String action = intent.getAction();
       if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
           final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
          
 if (state == BluetoothAdapter.STATE_TURNING_OFF) {
               // Bluetooth выключился — убиваем сервис
               if (BServiceIntent != null) {
                   context.stopService(BServiceIntent);
                   BServiceIntent = null;
               }
           }
           if (state == BluetoothAdapter.STATE_ON) {
               // Bluetooth включился — запускаем сервис
               if (BServiceIntent == null) {
                   BServiceIntent = new Intent(context, BService.class);
                   context.startService(BServiceIntent);
               }
           }
       }
       if (action.equals("ru.racoondeveloper.beaconnotifyer.WAKE_RECEIVER")) {
           // Поймали событие запуска приложения — запускаем сервис
           if (BServiceIntent == null) {
               BServiceIntent = new Intent(context, BService.class);
               context.startService(BServiceIntent);
           }
       }
   }
}

Service будет содержать поток, который ищет устройства Bluetooth Low Energy. Когда находим устройство, выдаем уведомление и продолжаем поиск.

public class BService extends Service {
   BeaconFinderThread thread;
   boolean live = true;

   @Override
   public IBinder onBind(Intent arg0) {
       return null;
   }

   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
       // создаем экземпляр потока и запускаем его
       thread = new BeaconFinderThread();
       thread.start();
       return START_STICKY;
   }

   @Override
   public void onDestroy() {
       // останавливаем поток
       live = false;
       thread = null;
       super.onDestroy();
   }

   private class BeaconFinderThread extends Thread{
       @Override
       public void run() {
           // создаем экземпляры BluetoothAdapter и BluetoothLeScanner
           final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
           final BluetoothLeScanner mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();

           // когда устройство будет обнаружено, будет вызван колбек
           ScanCallback mScanCallback = new ScanCallback() {
               @Override
               public void onScanResult(int callbackType, ScanResult result) {
                   // собираем данные о результате поиска
                   ScanRecord mScanRecord = result.getScanRecord();
                   mScanRecord.

                   String resulty = result.getDevice().getAddress() + " — "
                           + result.getRssi() + " — "
                           + mScanRecord.getDeviceName();

                   // показываем уведомление!
                   showNotification(resulty);

                   // повторяем поиск, пока не указано, что поток остановлен
                   if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON && live)
                       mBluetoothLeScanner.startScan(this);
               }
           };
           if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON && live)
               mBluetoothLeScanner.startScan(mScanCallback);
           super.run();
       }
   }

   private void showNotification(String name) {
       // отправляем уведомление
       Context context = getApplicationContext();
       Intent notificationIntent = new Intent(context, MainActivity.class);
       PendingIntent contentIntent = PendingIntent.getActivity(context,
               0, notificationIntent,
               PendingIntent.FLAG_CANCEL_CURRENT);
       Notification.Builder builder = new Notification.Builder(context);

       builder.setContentIntent(contentIntent)
               .setSmallIcon(R.mipmap.ic_launcher)
               .setContentTitle("Device found")
               .setContentText(name);
       Notification notification = builder.build();

       NotificationManager notificationManager = (NotificationManager) context
               .getSystemService(Context.NOTIFICATION_SERVICE);
       notificationManager.notify(0, notification);
   }

}

Это все, что нужно сделать, чтобы получить данные с маячка. Вот что у нас получилось:

67f6b5ac79908c39fe890d696fa66fd8.jpg

Исходный код приложения доступен на Github.

К сожалению, нам придется установить специальное приложение для получения информации от маячков. Но ведь не у всех пользователей оно установлено. Гораздо проще включить Bluetooth на телефоне и сразу получать нужную информацию, не устанавливая приложение. В этом нам поможет Google.

Google


Нужно признать, что Google вторгся в наш мир. ОС Android, которая занимает 82.8% рынка смартфонов, давно уже потеснила iOS. Многие пользователи iOS предпочитают устанавливать браузер Google Chrome на свой смартфон. Неудивительно, что Google стала компанией, чье имя тесно связано с такой перспективной разработкой, как маячки. Существуют несколько интернет-сервисов, помогающих дополнять тот малый объем информации, который способны передавать эти BLE девайсы, например, pubnub, но Google внедрил поддержку своего облачного сервиса прямо в Google Play Services, которые можно найти практически на любом Android устройстве. Поэтому можно сказать, что Google является монополистом в этой области. Поэтому в нашей статье мы будем рассматривать именно сервисы Google.
10efcfb729a51d03aeeeedebd0b85cf4.png

Настройка маячка


Как известно, Google в своём арсенале имеет огромное количество сервисов для разработчиков.

Сервис Google, работающий с маячками, доступен по следующей ссылке: https://developers.google.com/beacons/dashboard. Google нас тепло встречает таким уведомлением:

57cab529b21d7ea946c351d83b3c5408.png
a30578db163632ee36d6512628ce0bb0.png

Для использования сервиса необходимо перевести маячок в режим передачи Eddystone — UID или URL. Для этого действия нам пришлось обновить iBKS105, используя приложение nRF Connect.

Подключаем маячок к сервису Google Beacons


Скачаем приложение Beacon Tools (оно доступно для iOS и для Android). Входим туда под своим Google аккаунтом и выбираем наш проект. Маячок появится во вкладке «Unregistered». Выберем его и нажмем «Register Beacon». Готово, маячок добавлен в наш проект.

d9ae9ad05528421fa2cb973668cfecb2.jpg

Теперь мы увидели маячок на сайте. Это хороший знак.

47efdea365b6e0c888941793e15a52e9.png

Выберем его для настройки.

Мы можем задать маячку описание, место, этаж, параметр стабильности, а также другие свойства, которые нужны для конкретных приложений.

Параметр стабильности определяет, стационарен маячок или движется. Если маячок лежит в магазине, логично определить место на карте и этаж, а также указать, что он стационарен. А если приклеить маячок на лобовое стекло автобуса, то стоит указать, что он портативный, а также не указывать место и этаж (только если мы не в Лондоне).

Теперь нужно заставить маячок передавать действительно нужную нам информацию. Откроем выпадающий список «View beacon details» и выберем «Nearby Notifications».

0260d81c69c7c4936d701a6e53aaad46.png

Сначала мы видим всего лишь 4 текстовых поля, но не стоит недооценивать возможности маячков! Итак, что может нам рассказать маячок, подключенный к Google Cloud? Он может:

  • передать URL адрес;
  • предложить установить на устройство приложение;
  • отправить интент в систему, открывая приложение, если оно установлено.

Зададим имя уведомления в поле Title, а его описание — в поле Description. Поле language служит для определения языка уведомления, чтобы пользователи могли видеть контент на их родном языке. Язык задает ISO 639–1 код (чаще всего 2 строчные буквы, например, ru).

Дальше мы видим выпадающий список.

4094e779efee78dfe4ec94dc19f8ee3e.png
  • Web URL выбираем, если хотим, чтобы маячок передавал какой-либо сетевой адрес. Для настройки предлагается всего одно поле — сам адрес. В отличие от обычного Eddystone-URL мачка, маячок, использующий сервис Google, также передаст свое описание. Еще одним плюсом является передача ссылок любой длины, в отличие от 16 символов Eddystone-URL протокола.
  • Если хотим, чтобы маячок рекламировал пользователям какое-либо приложение, выбираем App intent with install fallback. Там есть 3 поля — 2 используем для выбора интента, а в одно пишем имя пакета желаемого приложения. Если приложение не установлено, нас перебросит в Google Play. В противном случае приложению будет отправлен интент.
  • Еще один вариант — App intent with web URL fallback. Он аналогичен предыдущему, но, если приложение не установлено на устройстве пользователя, нас отправят на указанный URL адрес.

Когда мы закончим с этими настройками, надо нажать на кнопку Create. Это сохранит наши труды.

Теперь мы можем проверить результат. Для этого надо на устройстве Android выбрать в настройках Google → Nearby Notifications → Scan. Мы должны увидеть данные, которые мы настраивали в конфигураторе на сайте.

022589b512514eb6aa3d0ab171502e19.png

Трудна ли настройка Eddystone


Сразу становится очевидно, что маячки — технология для программистов. Нам пришлось 4 часа сидеть за столом и пытаться все оптимизировать. Мы перепрошили Beacon, разбирались с локализацией, подбирали различные Property. Это при условии, что мы сильны в понимании Package, Exported, Action, Intent, Binder и многих других Android-терминов.

Хочется, чтобы у пользователя все работало, не надо было ничего устанавливать, чтобы действия по настройке смартфона были очень простыми.

Возникает мысль о создании Market Place — сервиса, связывающего людей, которые хотят организовать IT-мероприятие (заказчиков), и людей, которые готовы настроить маячки (исполнителей). Это будет самая обычная доска объявлений о предложениях по организации IT-мероприятий с маячками.

Например, однажды исполнителю придет уведомление:

cd429c93fae12eb9d96419627c4bf9d8.png

Исполнитель вспомнит, что на нашем сервисе он взял заказ на замену автомобильных номеров Eddystone-маячками. Это поможет дорожным службам идентифицировать автомобили и уменьшить количество угнанных машин. Исполнив его, руководствуясь нашей статьей, он получит вознаграждение, а мир — технологию.

Свою машину мы уже зарегистрировали, осталось всего 7 миллионов.

Заключение


Надеемся, что после прочтения данной статьи вы заинтересуетесь новыми технологиями. Мы уверены, что через несколько лет маячки станут частью повседневной жизни наравне со смартфонами.

Комментарии (0)

© Habrahabr.ru