前回はPhysical Web の概要を説明させていただきました。早速この技術の上でどんな応用が可能なのか考えていきたいところではありますが、そのためにはまずその基盤となる技術を把握し、制約を知らなければなりません。
今回と次回に分け、一つ一つのパートを技術的に掘り下げていきたいと思います。
さて、まずは何と言ってもUriBeacon です。UriBeacon ではBluetooth Low Energy を利用していますので、まずはそちらについて解説していきます。
Bluetooth Low Energy
Bluetoothの現状
UriBeacon ではBluetooth Low Energy という無線通信技術を使って近接検知を行います。Bluetooth Low Energy は、“ Bluetooth LE” 、“ BTLE” 、“ BLE” というように略されます。本稿では以降BLE と略すことにします。
Bluetooth を知らないという人は現在ではさすがにいないでしょう。ヘッドホンやキーボードなど、日常でBluetooth 機器の恩恵に預かっている方もたくさんいるかと思います。
ですが、Bluetooth の登場から現在までの変遷についてまでは、あまり知られていないのではないでしょうか。
Bluetooth は1999年にバージョン1.0の仕様が発表され、2000年代前半から普及期に入りました。ユビキタスネットワーク という言葉が流行っていたのを思いだす人もいるかもしれません。
Bluetooth は登場以降、バージョンを重ねながら通信の高速化などの進化を続けていましたが、Wi-Fi などの他の無線通信技術とうまく差別化を計れずに伸び悩んでいた所がありました。
こういった中、それまでの高速化追求とは方針を別にした、省エネの方向にターゲットを向けた規格であるBLE を発表しBluetooth 4.0 において統合されました[1] 。
[1] Bluetooth 4.0は、EDR(Enhanced Data Rate) 、HS(HighSpeed)など、これまでのバージョンで追加されてきた規格も含んでいます。ここに新たに追加されたのがLEであり、4.0=LEではありません。
また、4.0の後にも進化は続いていて、2014年12月には4.2の規格が発表されIPv6 との連携なども考えられています。
UriBeacon で利用されているのは、この省エネバージョンであるBLE の規格になります。
BLEの手続きの流れ
主題があまり逸れてしまわないように、ここではBLEの仕組みのうち、UriBeacon の動作の理解に必要な部分だけ簡単に解説していきます。
それ以上のBluetooth 及びBLE の情報について、より詳しくは専門の文献を当たっていただければと思います。
アドバタイズ
BLEのフローはまずはアドバタイズ という動作から始まります。BLEのサービスを提供するデバイスが、「 自分はこんなサービスを提供していますよ」と言う情報を周囲に発信します。この情報を載せたパケットをアドバタイジングパケット と言います。サービスの識別にはUUID を利用します。一般的にはアドバタイジングパケット にService UUID が載せられます。
図1 ビーコンはアドバタイジングパケットを放出し、それぞれのパケットにはServiceを識別するためのUUIDが載っている
1秒おき、あるいは0.5秒おきなど、設定されたインターバルに従い、このブロードキャスト処理を行います。もちろんインターバルが短いほど、相手に到達しやすくなるのですが、電力は消費しやすくなります。なので、トレードオフを考慮してインターバルを設定することになります。
ちなみに到達可能距離は10m程度と言われています。電力を弱めれば到達距離を短くすることも可能です。
スキャン
BLEのスキャナが起動しているデバイス(スマートフォン等)が、このように発信されているアドバタイジングパケットの到達範囲内に入ることでこのパケットを読み込み、解析します[2] 。
図2 スキャンすることでパケットを取得し、その中のService UUIDなどをチェックする
Service UUIDなどを見て識別を行い、このパケットの発信元が自分の求めるサービスを提供していると判断すると、接続処理を行います。
図3 UUIDを見て、目的のサービスだと判断したら接続
接続を行うことで、デバイスが提供するサービスを利用することが出来るようになります。このとき必要であればペアリングなどを行いますが、BLEではペアリングを必要としない用途で使われることも多いようです。
サービスとは何か
ではここで言う「サービス」とは何でしょうか[3] 。
サービスにはcharacteristic(特性) と呼ばれる値がぶら下がっています。この値に対して読み書きしたり、値の変更をすることができます。
例えば、エアコンのコントローラであれば次のような例が考えられます。
図4 エアコンのコントローラというサービスがあり、4BC78330-337F-4D08-89B4-9A1028B56583というUUID を割り当てている
エアコンのコントローラというサービスがあり、4BC78330-337F-4D08-89B4-9A1028B56583というUUID を割り当てています。
このサービスは3つのcharacteristic を持っています。それぞれのcharacteristic はUUID をあてがわれています。
現在の室温(9200B09-F42C-4408-8277-C084F31FA746)
設定温度(47E26BA3-CF6E-4F2B-82F9-05A5C752287E)
スイッチ(A0370A52-E8DC-4478-BECF-420C3E373666)
BLE で利用するservice やcharacteristic のUUID が、あまりヒューマンリーダブルではないために、パッと見たときに難しく感じるかもしれませんが、次のようにWebのサービスと比較してイメージするとわかりやすいかもしれません。
図5 REFTfulなWebサービスではドメインを指定して接続し、パスを指定してGET/POSTなどを行う
図6 BLEではService UUIDを指定して接続し、CharacteristicのUUIDを指定してread/writeなどを行う
基本的にはkey-valueペアのようなものだ、とわかってしまえば凄く単純な話です。
ただし、いわゆるデバイスのon/offを制御するスイッチのような役割を持つcharacteristic もよく使われます。このように、write することで動作を切り替えることが出来るコントロールポイント としても振る舞えるという点は覚えておきましょう。
ちなみに上の例のエアコンのように、BLE でサービスを提供する側の役割をPeripheral(ペリフェラル) 、上の例のスマートフォンのようにサービスを享受する側の役割をCentral(セントラル) と呼びます。
UriBeaconでのBLEの利用
BLE についておおざっぱに理解できたところで、UriBeacon の話に戻ります。
UriBeacon は2つのモードを切り替えて使います。URI Advertising Mode とConfiguration Mode です。
URI Advertising Mode
URI Advertising Mode では、上で説明したような、「 相手と接続してcharacteristic の値の読み書きを行う」いうようなやりとりは実は行いません。アドバタイジングパケットのブロードキャストのみをずっと続けます。
図7 ビーコンはひたすらURLを載せたパケットを放出しつづける
Configuration Mode
Configuration Mode は、ビーコンの管理者が、URIなどのデータを設定するためのモードです。サービスに接続して、各characteristicに対して読み書きを行い、ビーコンの設定を行います。
図8 それぞれのcharacteristicに対して読み書きを行うことで、URIや電力値などの設定、ロックやアンロックなどの操作を行う
公式の仕様から抜粋しますが、次のようなcharacteristic が用意されています。名前を見れば何となくそれぞれのcharacteristic の役割が想像できるかと思います。
Characteristic
Lock State
Lock
Unlock
Uri Data
Uri Flags
Advertised Tx Power Levels
Tx Power Mode
Beacon Period
Reset
BLEのアドバタイジングパケットについて
UriBeacon の主要なモードはURI Advertising Mode のほうであり、その動作を把握するために一番重要なポイントはBLE のアドバタイジングパケットの理解です。
BLE のアドバタイジングパケットのうち、プリアンブルやヘッダ情報などの先頭部分、CRCが載っている後方部分を除いた31バイトの中央部に、サービス提供者がデータを選んで載せて行くことが出来ます。
図9 Advertisment Data の箇所に載せられるデータのタイプ(Ad Type)は「Generic Access Profile」で定義されている
このAdvertisment Data の箇所に載せられるデータのタイプ(Ad Type)は、以下に示した「Generic Access Profile」で定義されています。一度眺めてみると良いでしょう。
この中からサービス提供者が任意で載せたいタイプのデータを選び、容量が許す範囲でパケットに詰め込んで行きます。それぞれのデータは、データの長さ、データのタイプ、ペイロードという3つのパートで構成されています。
図10 UriBeacon の場合はServiceUUIDs とServiceData というタイプのデータを乗せることになる
UriBeacon の場合は、ServiceUUIDs と、ServiceData というタイプのデータを乗せることになります。
ServiceUUIDs
このServiceUUIDs レコードに載せる、Service UUID は、独自のものを用意すると128bit必要ですが、よく使われるサービスに関しては、32bit、16bitのものがBluetooth SIG によって定義されています。
UriBeacon では0xFED8 という一番短い16bitのService UUID を使うことになっています。
ServiceData-いかにしてURIを詰め込むか
次はServiceData のレコードを用意します。ここにURIを載せるのですが、載せられるスペースは非常に限られています。
ペイロード部分のフォーマットは次のようになっています。
図11 ペイロード部分のフォーマット
フラグ、電力、URIなどの値があるのがわかりますが、この少ないスペースにURIを載せるために工夫が必要になります。
まず1つの解決策としてgoo.gl やbit.ly のようなURL短縮サービス を使う事が推奨されます。
URL短縮サービス を利用することで、以下の表のようにバイトサイズをだいたい20バイト前後まで縮小できるでしょう。
goo.gl
http://goo.gl/fD0dPt
20
bit.ly
http://bit.ly/1bWUKmo
21
さらに、次のようにURLの先頭でよく使われるパターンは1byteで表現できるように変換ルールが決められています。
http://www.
0x00
https://www.
0x01
http://
0x02
https://
0x03
uri:urn:
0x04
そうすると、goo.glを利用した場合、http://goo.gl/fD0dPt の先頭の http:// という7バイトを 1バイトに短縮することができ、全体で14バイトまで短縮ができます。
ドメインのTLD部分も同様に短縮ルールが用意されています。
com 、org 、edu 、net 、info 、biz 、gov の7つについて、/ が続くパターンと続かないパターンそれぞれについて代替バイトが用意されています。
.com/
0x00
.org/
0x01
.edu/
0x02
.net/
0x03
.info/
0x04
.biz/
0x05
.gov/
0x06
.com
0x07
.org
0x08
.edu
0x09
.net
0x0a
.info
0x0b
.biz
0x0c
.gov
0x0d
このようにして圧縮処理を行い、URIを18バイトまでに収まるようにします。というわけで、使いたいURIのscheme部分とTLD部分を代替バイトに置き換え18バイトに収まるならそのままで、そうでないならgoo.glなどの短縮サービスを利用すると良いでしょう。
HTTP URL以外のURI
PhysicalWeb と言う“ Web” と名のつく技術の話になっていますので、HTTP URL を中心に解説してきましたが、UriBeacon の仕様では、その名の通りURLに限定されず、次のようにUUID を利用することも出来ます。
UUID のフォーマット
urn:uuid:B1E13D51-5FC9-4D5B-902B-AB668DD54981
PhysicalWeb という枠組みではなくUriBeacon の仕様のみを利用し、このUUID をビーコンの識別子として使うことで、“ ビーコンへの近接検知” 、“ 複数のビーコンを利用した屋内移動検知” など、現在AppleのiBeaconが利用されているようなタイプのサービスにも応用出来る、と言うことなのかもしれません。
特筆すべきことが無ければ、「 基本的にはHTTP URL を使う」と言うことでこの連載では話を進めていきますが、このようにUUID を渡すことが出来る、と言うことは覚えておきましょう。
BLEを使わないURIの共有
BLE でのアドバタイジングパケットでのフォーマットを紹介してきましたが、実はBLE を使わない方法についての議論もあります。
たとえばプライベートスペースのみでURIを共有したいケースです。アパートの部屋や会議室などを想像すれば良いでしょうか。部屋の外までパケットが到達してしまい、外にいる人が飛ばされたURIを拾うことが可能になってしまうわけですね。
このために特定のWi-Fi環境にログインできる人を限定し、mDNS [4] を利用してURIを共有する方法も考えられています。
実装について
この原稿の執筆時点では、国内で利用できるPhysicalWeb 対応ビーコンデバイスは一般販売などで手に入れることは出来ません(海外で販売されているものはあるのですが、国内で利用するには電波法などの問題があります) 。
ですが、UriBeacon のリポジトリには、様々な開発環境でUriBeacon の振る舞いを実現するためのライブラリコードが提供されていて、これらを利用して自前でビーコンを用意することは可能です。
Linux+node.jsやRaspberry Piなどいろいろな環境のためのデモやライブラリコードが揃えられていますので、得意な環境がこの中にあったら試してみてはいかがでしょうか。
iOSとAndroidのBLEサポート
iOS/Android でのBLE のサポートについても少し触れておきます。
iOS では、かなり早くからBLE への対応がされてきました。まずiOS 5 でCentral 側の機能が使えるようになり、次のiOS 6 ではPeripheral 用のAPIも搭載されました。
一方Android では、4.3でようやく対応が始まりました。その時点ではCentral 側の対応のみで、Peripheral 側には対応していませんでした。Peripheral 側として振る舞えるAPIが搭載されたのはAndroid 5(Lollipop)からです。
今回の解説の通り、ビーコン側はPeripheral として振る舞います(正確にはBroadcasterだが、iOS/AndroidなどのSDKの上では区別されません) 。
ではPeripheral 用のAPIが用意されているiOS 6以降、Android 5以降であればUriBeacon として振る舞えるのかというと、必ずしもそうではありません。
iOS ではアドバタイジングパケット に載せられるデータが制限されています。
CoreBluetoothプログラミングガイド より引用
ペリフェラルマネージャオブジェクトに対して指定できるのは、 CBAdvertisementDataLocalNameKeyとCBAdvertisementDataServiceUUIDsKeyの2つだけです。
と言うわけでiOSではLocalName とServiceUUIDs の2種類のデータしか直接指定できません(iBeacon のAPIを使うことで、Manufacturer Specific Data を、決められたフォーマットのみで利用は出来ます) 。そのため、PhysicalWeb で利用するServiceData が使えませんので、現状iOSではUriBeacon の発信側の振る舞いをさせることは出来ません。
Android のBLEのAPIでは比較的自由にアドバタイジングパケットにデータを載せられるようです。ただし、Android はiOS と違って様々なメーカの機種が存在しますので、それぞれに搭載されたBLE チップの影響を受けます。
例えばNexus シリーズでは、Nexus 6 やNexus 9 であればAndroid 5 から追加されたPeripheral 関係のAPIを使うことができるようです(Nexus 5 でもL Preview の頃はPeripheral 側の機能が使えたのですが、正式版のLollipop ではエラーを返すようになりました。チップに何か問題が見つかってサポートを外したのかもしれません) 。
と言うわけで、スマホやタブレットをUriBeacon として振舞わせて実験がしたいときには比較的新しいAndroid デバイスが必要になります。
iOS/Android用ライブラリ
凄く簡単にではありますが、用意されているライブラリのうち一部をピックアップして紹介してみます。
まずはAndroidです。
例えば今回紹介したURLの圧縮処理の部分であれば、次のようにエンコード/デコード処理が用意されています。
発信側のエンコード処理
先に説明したようにAndroid 5 で、チップが対応している機種を利用することが前提になります。
AdvertisingData生成時に、次にように簡単にエンコードできるようになっています。
import org . uribeacon . beacon . UriBeacon ;
byte [] data = UriBeacon . encodeUri ( url );
受信側のデコード処理
スキャナのコールバックにおいても同様に、簡単にURIを取得することが可能です。
import org . uribeacon . beacon . UriBeacon ;
UriBeacon uriBeacon = UriBeacon . parseFromBytes ( scanRecordBytes );
Log . d ( TAG , uriBeacon . getUriString ());
次にiOSになりますが、 既に説明したようにSDKの制限があるために発信側は実装できないのですが、受信側は実装することが出来ます。
こちらのライブラリが使えます。
実装例についてはPhysicalWeb のほうのリポジトリを参照すると良いでしょう。
Scannerごと用意されているので、それを利用して比較的簡単にURIの取得まで出来るようになっています。
_scanner = [[ UBUriBeaconScanner alloc ] init ];
_scanner startScanningWithUpdateBlock :^{
for ( UBUriBeacon * uriBeacon in [ _scanner beacons ]) {
// NSURI *u = [uriBeacon URI];
}
}];
このように、PhysicalWeb やUriBeacon のリポジトリにはライブラリやサンプルが充実してきていますので、それらを参考に、発信側や受信側を用意して実験してみてはいかがでしょうか。
まとめ
今回はUriBeacon で利用されているBLE がどんなものなのか、そのアドバタイズパケットに対してどのようにデータを詰め込んでいるかを中心に解説させていただきました。
次回はメタデータリゾルバを中心に解説したいと思います。