読者です 読者をやめる 読者になる 読者になる

ガジェット調査ログ

購入したガジェットの記録などなど

Estimote Nearables Developer KitでiBeaconについて学ぶ(Android編)

去年注文したEstimote stickersの開発向けキットが注文から丸一年ほどしてようやく届いたので早速試してみる。

estimote.com

なお、私は現在Android開発者なので、Androidで動作確認を行う。iOSでも試すかは未定。でもAndroidでは機能不足な雰囲気。

ドキュメント

まずは技術ドキュメントのありかを探すところから。Estimoteの開発はiOSが中心に行われている。Androidには含まれない機能も多いので、iOS経験者なら迷わずiOSを選択すべし。 AndroidについてはGitHubSDKのみではないだろうか。

概要

ざっくりと公式サイトの拙訳をしてみる。

iBeaconとは何か

Beaconは小さなコンピューターである。その32-bit ARM® Cortex M0 CPUには加速度、温度センサー、そしてBluetooth 4.0 Smart 、別名BLEと呼ばれる2.4Ghzの無線を備える。

以前のBluetoothテクノロジーと比較した際のもっとも大きなアドバンテージはエネルギー利用効率の高さである。それと我々のエンジニアが電源管理に関する多くの仕事を入れたおかげでEstimote Beaconsはたった1つのCR2477バッテリー上でデフォルト設定で3年間持続する。

信号範囲と近接計測

Beaconは灯台と考えることができる。しかし光の代わりに信号派を、船の代わりにスマートフォンにその存在を知らせる。Estimote Beaconsは70メートルの範囲を持つ。しかしその信号は回析(障害物の向こう側に届く)されることができ、水(人体も含む)によって妨害または吸収される。現実世界では40m-50mと考えるのがよい。

携帯や他のスマート端末はその信号の強さから距離を計測することができる。 Beaconに近ければそれだけ強い信号を受ける。Beaconはその信号を連続的にブロードキャストしているのではなく、断続的に点滅していることに注意が必要である。

Estimote Stickersとは何か

Estimote Stickersはより小さなBeaconで、厚さが3mmしかない。それらはまた1つのバッテリーで動作するARM CPUに加速度、温度計、そしてBlutooth信号を組み込んでいる。

オリジナルのBeaconが発生地点と静的なロケーションのために設計されたのに対し、Stickersは独立したオブジェクトをスマートにするのに最適である。

Nearablesは毎日のアイテム(あるいは犬なども!)をスマートオブジェクトに変化させるEstimote Stickersとクラウドのおかげで、何でもその位置とモーション、そして環境をブロードキャストできる。

stickersはどのように動作するのか

Estimote Stickersは7メートルの範囲と、1つのCR2020バッテリーあたり1年の寿命を持つ。 ランダムなiBeacon IDの平行して、stickersは定義されたNearable IDとNearable Typeを持つ。 Nearable IDは8byteの数値で、Nearable Typeはプログラムされた10分の1のコンテキストstikcerである。

  • bag バッグ
  • bed ベッド
  • bike バイク
  • car 車
  • chair 椅子
  • dog 犬
  • door ドア
  • fridge 冷蔵庫
  • shoe 靴
  • ブランク(自分ようのコンテキストを製作できる)

Stickersは2つのプロトコルを使ってデータをブロードキャストする。 iBeaconとNearableである。 これはそのパケット内により多くのデータを含むことができるようになり、全てのiBeaconの機能の 利益を得る。

nearableプロトコルには以下の情報が含まれる

  • nearable ID 8bytes
  • nearable Type ID (fridge,dog, shoe ...)
  • 方向
  • 空間内の方向
  • 動作モーションのX,Y,Z値
  • 温度
  • ブロードキャスト値(近接計算に使われる)
  • バッテリーレベル
  • ファームウェアのバージョン

nearableの開発

nearableと対話するアプリはiBeaconと同じロジックに従う。ただしiBeacon IDの代わりに Nearable IDとNearable Typeを使う。もしiBeaconの経験があるなら、stickersを使うことは たやすい。

加えて、何かをトリガーとしたいなら、全ての状況に応じたデータが得られる。方向、nearable type, モーション、周囲の温度、1日の時間などだ。

<拙訳終わり>

どこから始めたらいいの?

とりあえず開発キットは届いたが何をどうすればよいのか。これも公式ブログに記事がある。

How to get started with Estimote Beacons? – Estimote Community Portal

だいたい以下のような感じのことが書いてある

  1. 箱から出せ
  2. アプリをダウンロードせよ
  3. スマホBluetoothと位置情報を有効にせよ
  4. デモをやってみろ
  5. Estimoteのアカウント作れ
  6. 自分のアプリを作れ!!

大したこと言ってない気がするが、とりあえずアプリをダウンロードして使ってみよう。

アプリのダウンロード

公式のデモアプリがあるのでインストールしてみる。先に述べておくと、このアプリよりもGitHubSDKに付属するデモアプリの方が参考になるだろう。

アカウントを作ろう

注文した人は既にアカウントを持っているはず。 Estimote Cloudにログインすると購入済みのBeaconなどの情報が得られる。

Estimote Cloud

Android SDKを試す

GitHubSDKがある。jar及びaarでの提供となっており、オープンソースではないっぽい。

Android 4.3以上

Bluetooth Low Energyが4.3からなので、SDKも4.3以降が対象となっている。すなわちminSdkVersionは18となる

defaultConfig {
    minSdkVersion 18
  }

SDKでできること

  • 範囲内にあるBeaconのスキャン(またはフィルタ)、レンジング
  • Beaconの領域検知(Beaconのエリアに入った・出た)
  • nearables (Stickerなど) の発見
  • EddyStoneのスキャン Beacons   |   Google Developers
  • Beaconの特性の読み書き

renging(レンジング)とは何か

デバイスとビーコンとの相対的な距離を測ること

参考: iBeacon(3) - リージョン監視とレンジング

アプリを登録する

estimote cloudにアプリを登録することでAPP_IDとAPP_TOKENがもらえる。なお、アプリ登録時に選択肢にSwiftObjective-Cしか選べない箇所があるが、IDとTOKENのゲットには関係がないので適当でOK。登録が終わるとテンプレート実装がダウンロードされるが、これもiOS向けなのでAndroidには無関係である。

実装

ざっくりいうと

  • onCreate でManagerつくってリスナーを設定
  • onStart で接続してスキャン開始
  • onStop でスキャン停止
  • onDestroy で切断

Application

EstomoteSDKの初期化をApplicationクラスの継承クラスで行う。 Estimote Cloudに登録していない場合はこの記述は不要かもしれない(未確認)。

public class EstimoteApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

    // Initializes Estimote SDK with your App ID and App Token from Estimote Cloud.
    // You can find your App ID and App Token in the
    // Apps section of the Estimote Cloud (http://cloud.estimote.com).
    EstimoteSDK.initialize(this, EstimoteConstants.APP_ID, EstimoteConstants.APP_TOKEN);

    // Configure verbose debug logging.
    EstimoteSDK.enableDebugLogging(true);
    }
}

Activityの実装サンプル

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private BeaconManager beaconManager;
    private String scanId;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        beaconManager = new BeaconManager(getApplicationContext());

        Log.d(TAG, "onCreate isBluetoothEnabled:" + beaconManager.isBluetoothEnabled());
        Log.d(TAG, "onCreate checkPermissionsAndService:" + beaconManager.checkPermissionsAndService());
        Log.d(TAG, "onCreate hasBluetooth:" + beaconManager.hasBluetooth());

        beaconManager.setNearableListener(new BeaconManager.NearableListener() {
            @Override
            public void onNearablesDiscovered(List<Nearable> nearables) {
                Log.d(TAG, "Discovered nearables: " + nearables);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                scanId = beaconManager.startNearableDiscovery();
                Log.d(TAG, "onServiceReady scanId:" + scanId);
            }
        });
    }

    @Override
    protected void onStop() {
        super.onStop();
        beaconManager.stopNearableDiscovery(scanId);
        Log.d(TAG, "onStop scanId:" + scanId);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        beaconManager.disconnect();
    }
}

データが取得できればこっちのもの。あとは良しなに実装すればよい。