- PVSM.RU - https://www.pvsm.ru -

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

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

Делаем стартап просто и технологично. Маячки Eddystone - 1
Статья автора Алексея Набережного, в рамках проекта «Devces Lab от Google [1]».

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

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

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

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

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

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

Маячок может работать от одной батарейки 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 для генерации этой информации и приводит следующий пример [3] определения маячка в магазине.

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

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 [4]. Подробнее про протокол Eddystone можно узнать по ссылке на Github [5].

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

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

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

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

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

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

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

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

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

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

Inside Android SDK

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

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

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

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

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

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

<b>public class</b> BTReceiver <b>extends</b> BroadcastReceiver {
   <b>private</b> Intent <b>BServiceIntent</b>;

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

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

<b>public class</b> BService <b>extends</b> Service {
   BeaconFinderThread <b>thread</b>;
   <b>boolean live </b>= <b>true</b>;

   @Override
   <b>public</b> IBinder onBind(Intent arg0) {
       <b>return null</b>;
   }

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

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

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

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

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

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

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

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

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

       NotificationManager notificationManager = (NotificationManager) context
               .getSystemService(Context.<i><b>NOTIFICATION_SERVICE</i></b>);
       notificationManager.notify(0, notification);
   }

}

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

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

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

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

Google

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Делаем стартап просто и технологично. Маячки Eddystone - 16
  • 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. Мы должны увидеть данные, которые мы настраивали в конфигураторе на сайте.

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

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

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

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

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

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

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

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

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

Заключение

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

Автор: Google

Источник [9]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/android/209756

Ссылки в тексте:

[1] Devces Lab от Google: http://special.habrahabr.ru/google/lab

[2] iBKS105: http://accent-systems.com/product/ibks-105

[3] пример: https://developer.apple.com/ibeacon/Getting-Started-with-iBeacon.pdf

[4] GATT Configuration Service: https://github.com/google/eddystone/tree/master/configuration-service

[5] Github: https://github.com/google/eddystone

[6] Github: https://github.com/SCaptainCAP/BeaconNotifyer

[7] которая занимает 82.8% рынка смартфонов: http://www.idc.com/prodserv/smartphone-os-market-share.jsp

[8] https://developers.google.com/beacons/dashboard: https://developers.google.com/beacons/dashboard

[9] Источник: https://habrahabr.ru/post/310486/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best