DelphiでスマホやPCをBLEビーコンにしたり、ビーコンの電波を受けてみたりする

これは [Delphi Advent Calendar 2016](http://qiita.com/advent-calendar/2016/delphi) 3日目の記事です。

そして全4回の連載記事でもあります。その他の記事は以下の通りです。

+ DelphiでスマホやPCをBLEビーコンにしたり、ビーコンの電波を受けてみたりする
+ [ビーコンの距離測定精度を上げるためのキャリブレーションを行うアプリをDelphiで作る](http://qiita.com/kazinoue/items/fefe996df6e39d6f0381)
+ [固定Beaconを使って現在位置を測位するアプリをDelphi/C++BuilderとBeaconFenceで作る](http://qiita.com/kazinoue/items/99e46201bc9f3b81dfbe)
+ [IoTデバイスの計測値やiBeaconを利用した位置測位結果をGoogle Spreadsheetでリアルタイムに分析するためにGoogle Formを使う](http://qiita.com/kazinoue/items/55131d81ee75533bd1c4)

# Delphi でビーコンって扱えるの？ いまさら Delphi って古くね？
いえいえ、**Delphi は今はマルチデバイスマルチプラットフォーム向けの開発が行えるのですよ**。マルチデバイスマルチプラットフォーム向け開発では Xamarin という選択肢もありますが、Delphi でも出来るんです。というか、Delphi のほうがマルチプラットフォームの対応は早かったはず。

だけどそういう最近の機能が知られてない気がするので、今回は Delphi でビーコンを扱う話を書いてみました。

# ビーコンを使うアプリって、ハードが必要だよね？
そうです。ビーコンを使うアプリを試そうと思ったら、ビーコンが必要です。でも、PCやスマホをビーコン代わりにしてもいいんです。

いまどき、開発者１人が使えるデバイスは、ノートPC、デスクトップPCに加えて、スマホやタブレット(iOS / Android)など、３～４つ以上あると思います。

そこで、**周囲にあるデバイスを使って、BLEビーコンにしたり、あるいは電波を受信させてみることにします**。これは Delphi Advent Calendar ですから、当然ながら Delphi でやりますが、C++Builderでも大丈夫です。

(Raspberry Pi を使えば、というようにハードを新たに買い足すのは今回はナシで）

ただしAndroid デバイスの場合は古いデバイスの場合にビーコンにならない機種があります。Android では Lolipop 以降でビーコンにする機能が提供されましたが、この機能を使うにはハードウェア側の対応も必要です。古い端末はBLEビーコンとして動作するためのハードウェア要件を満たしていない可能性が高く、また Lolipop 以降にリリースされた端末でも非対応の場合があります。

これについては以下のページが参考になるのではと思います。
http://altbeacon.github.io/android-beacon-library/beacon-transmitter-devices.html

# DelphiでスマートフォンやPCをビーコンにするには、Delphiのどのエディションが必要ですか？
2019年11月時点での最新バージョン 10.3.3 はすべてのエディションでWindows 32/64-bit, macOS 64-bit, iOS 64-bit, Android 64-bit 向けの開発が行えます。ただし開発環境はWindowsにインストールします。この記事の初稿は Delphi 10.1 を前提に作成しているため、いくつかの箇所に古い記述が残っているかもしれませんが、現在のバージョンではエディションによらずクロスプラットフォーム開発ができるということだけ覚えておいてください。

またCommunity Edition は年間売上5,000USドル未満の個人またはスタートアップ企業の開発者が無料で使用できますので、ご自宅のPCにインストールしてすぐに試せます。この条件に該当しない場合でも30日間利用可能な評価版が利用できます。（Community Editionの利用条件に該当しない個人や企業の開発者がCommunity Editionを利用することはライセンス上許諾されていません）

# 使うもの
|項目|内容|
|:-:|:-:|
|ビーコンにするデバイス|BluetoothLEがついているWindows10のPC|
|ビーコンを検出するデバイス|同上|
|開発環境|Delphi 10.3.3|

Windows側について着目してみると、単にBluetoothがついていればよいわけではなく、BluetoothLE対応であることが必須です。USBのBluetoothドングルを使う場合や、Windows7/8/8.1からアップグレードしたPCに内蔵のBluetoothデバイスでは、BluetoothLEに非対応の可能性もあります。

また、たとえば「Macbook 上の仮想マシンで Mac の Bluetooth デバイスを扱う」のは、わりと上級者向けの話になります。ビーコンはペアリングが不要なためか、意外に思ったように動かないことがあります。このあたりの設定や操作に不慣れな方は「物理PCに装着したBluetoothデバイス」の組み合わせを試すほうが確実です。

またOS自体については、Windows標準のBluetoothスタックがBluetoothLEに対応したのがWindows10からです（RTのことは忘れよう……）。参考までにWindowsのOSバージョンとBluetoothスタックの関係を表にしてみたのがこちらです。着色した箇所はBluetoothLEに関連する箇所です。
![image](https://qiita-image-store.s3.amazonaws.com/0/149350/b5531708-4c0a-1df4-b0b4-4aace2672562.png)

……画像ではなくHTMLの表にしたほうがよかったかなあ。

開発環境については、バージョンが 10.1 Berlin 以降ならOKです。これより前のバージョンはWindows10でのBLEビーコンに対応していません（正確にいうと 10 Seattle より前の Delphi/C++Builder では、その当時の OS 標準スタックが BluetoothLE に対応していないのだから、そもそもサポートのしようがない）。

そしてDelphiではすべてのエディションでモバイル向け開発も可能となっています。Delphiでは２つのフレームワーク、VCLとFireMonkeyが利用できますが、マルチデバイス向けのFireMonkeyフレームワーク向けに作成したプロジェクトはWindowsの他にmacOS、iOS、Android向けにデプロイできるため、Windowsで動作確認したコードをそのまま他のプラットホーム向けにビルド、実行できます。

| エディション | Windows | macOS | iOS | Android |
|:-:|:-:|:-:|:-:|:-:|
| Community|○|○|○|○| 
| Professional |○|○|○|○|
| Enterprise |○|○|○|○|

# 作業の流れ
ビーコンにする場合でも、ビーコンを検出する場合でも、イチから実装する必要はありません。どちらの処理も Delphi のサンプルプロジェクトがあります。

サンプルプロジェクトはそれぞれ以下のパスにあります。

|種類|パス|
|:-:|:-:|
|ビーコンになる|C:\Users\Public\Documents\Embarcadero\Studio\18.0\Samples\Object Pascal\Multi-Device Samples\Device Sensors and Services\Bluetooth\Beacons\Beacon Device|
|ビーコンを検出|C:\Users\Public\Documents\Embarcadero\Studio\18.0\Samples\Object Pascal\Multi-Device Samples\Device Sensors and Services\Bluetooth\Beacons\Beacons Proximity|

またはサンプルプロジェクト一式を以下のURLよりダウンロード頂けます。
https://sourceforge.net/code-snapshots/svn/r/ra/radstudiodemos/code/radstudiodemos-code-2015-branches-RADStudio_Berlin.zip

これらをビルドして試してみましょう。

# ビーコンにしてみる
まずは早速、ビーコンになるほうのサンプルプロジェクトを開いてみましょう。
![サンプルプロジェクト_BeaconDeviceDemo.png](https://qiita-image-store.s3.amazonaws.com/0/149350/56247da6-3007-ffea-c89a-75c381fbbea4.png)

開くとDelphiのIDE画面はこのようになっているはずです。
![サンプルプロジェクト_BeaconDeviceDemo_開いた直後.png](https://qiita-image-store.s3.amazonaws.com/0/149350/42958fd6-5aae-7a94-faa8-1623b4ed6b5f.png)

あとはビルドするターゲットを選択してビルドするだけです。サンプルプロジェクトをビルドするだけだからカンタンですねー。（なお、MacやiOS向けのビルドでは、Macの実機とPAServerのインストールなどのいくつかの準備が必要ですが、ここではその説明を省略しています）

さて、ビルドできたバイナリを実行してみましょう。実行したら中央の "Enable Beacon" を押すだけです。
![BeaconDeviceDemoを実行する.gif](https://qiita-image-store.s3.amazonaws.com/0/149350/1c36df73-c9fd-4c04-9940-09a8f38b0a22.gif)

そうすると、このデバイスは UUID=11111111-2222-3333-4444-555555555555、Major=1, Minor=1 という識別情報を持ったビーコンになっています。しかしこれが本当に上記の識別情報を出しているかどうかは分からないですよね。そこで今度は別のデバイスから、このビーコンを検出してみることにしましょう。


ちなみに、上記のスクリーンショットは [Reflector2](http://www.airsquirrels.com/ja/reflector/) を使って iOS の画面を PC 側に表示しつつ、[AssistiveTouch](https://support.apple.com/ja-jp/HT202658) をポインタ代わりに代用してます。iPhone や iPad の操作画面を Reflector でPC側に出すというのは割と普通に行われることだと思いますけど、スマホやタブレットではどこを操作しているのかがわかりづらいですよね。そういうときに AssistiveTouch のメニューをポインタとして代用すると便利ですよー。操作している箇所をPC上でマウスカーソルで後追いするという手もありますけど、それは案外面倒なのです。そして animated GIF の作成には [LICEcap](http://www.cockos.com/licecap/) を使っています。これは Windows/macOS でデスクトップ上の任意の矩形を選んで animated GIF が作れます。

……脱線しすぎました。それでは続けます。

# ビーコンを検出してみる

さて、今度はビーコンを検出するサンプルプロジェクトを開きます。
![サンプルプロジェクト_BeaconProximityDemo.png](https://qiita-image-store.s3.amazonaws.com/0/149350/139dea37-b54b-345f-c50b-696e97c97db9.png)


プロジェクトが開いたら、GUID の入力項目 (TEdit）を選択し、左下の「オブジェクトインスペクタ」より Text プロパティを選択します。
![サンプルプロジェクト_BeaconProximityDemo_デフォルトで表示するGUIDを変更.png](https://qiita-image-store.s3.amazonaws.com/0/149350/f16c3df7-9801-8450-870d-a0e8616dbc6b.png)

この Text プロパティには、{11111111-2222-3333-4444-555555555555} のように {} でUUIDを囲った文字列を指定しておきます。

それでは Beacons Proximity をビルドして実行してみよう。
![BeaconProximityDemoを実行してみる.gif](https://qiita-image-store.s3.amazonaws.com/0/149350/0109d545-e240-1121-4c60-b5360318e751.gif)

AddRegion してから Start を押し、Monitoring タブに切り替えてみます。これで先ほど作成したビーコンが検出できるはずです。

このようにして、PCやMacOS、iOS、Android をビーコンにしたり、あるいはビーコンを検出するデバイスとして使うことができました。

# サンプルプロジェクトを使わずに自分で実装してBeaconにしてみる
Beaconにするには、TBeaconDevice というコンポーネントを使います。スクリーンショットは BeaconDevice をフォームに配置しつつ、UUID, Major, Minor, TxPower の値を書き換えるための入力フィールド　(TEdit) と、編集内容を BeaconDevice に反映させるためのボタンを配置しています。
![image](https://qiita-image-store.s3.amazonaws.com/0/149350/812683d5-b5e2-7c61-1398-c2e34557fbc9.png)

ただし設定を決め打ちでやるならば、これらのコントロールは一切不要であり、単に TBeaconDevice を配置した上で下記４点の値を適切に設定し、Enabled を True にするだけです。
- UUID
- Major
- Minor
- TxPower

値を変更できるようにしたい場合は、Buttonのクリックイベントを以下のように設定します。

```delphi:TForm1.Button1Click
procedure TForm1.Button1Click(Sender: TObject);
begin
  BeaconDevice1.Enabled := False;

  BeaconDevice1.UUID := Edit1.Text;
  BeaconDevice1.Major := StrToInt(Edit2.Text);
  BeaconDevice1.Minor := StrToint(Edit3.Text);
  BeaconDevice1.TxPower := StrToInt(Edit4.Text);

  BeaconDevice1.Enabled := True;
end;
```

また、Form の生成時のイベントを以下のように書いておけば、編集用の TEdit を BeaconDevice1 の設定内容で初期化できます。

```delphi:TForm1.Button1Click
procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := BeaconDevice1.UUID;
  Edit2.Text := BeaconDevice1.Major.ToString;
  Edit3.Text := BeaconDevice1.Minor.ToString;
  Edit4.Text := BeaconDevice1.TxPower.ToString;
end;
```

ココらへんの話を IDE の画面上で操作している様子のスクリーンショットがコレ。
![licecap.gif](https://qiita-image-store.s3.amazonaws.com/0/149350/80508930-e35f-e347-826f-23d8104bd205.gif)


# 次回予告？
次回はこのビーコンのキャリブレーションを行います。キャリブレーション無しでビーコンを使うと精度が出ないんです。このときに、ビーコンを検出するアプリをサンプルプロジェクトではなく自分で作る話もやってみます。

そして、キャリブレーションができたら、その先はいよいよBeaconFence を使って位置測位するアプリを作ってみようかと思います。

ただしこのためにはビーコンが3つ必要です。ビーコンがない場合は今回の方法でPCやスマホをビーコンにしてみてください。

⇒ Delphi Advent Calendar 2016 10日目に「[ビーコンの距離測定精度を上げるためのキャリブレーションを行うアプリをDelphiで作る](http://qiita.com/kazinoue/items/fefe996df6e39d6f0381)」を書きました。