【BLEを使う】GAP(Generic Access Profile)概要
【BLEを使う】記事の一覧はこちら。
読書百遍 義 自ずから あらわる
いままでの記事はこちらをご覧ください。
ここではGAPについて自分のメモ用に調べた結果を書きます。 勉強しながら随時追加修正を行うので、内容の正確さを保証しません。
本記事は、以下の文献およびサイトを参照しています。
未熟な私のいい加減な解説を見て、間違った知識を得るくらいなら以下の本を読んだ方が確実に有意義です。
以前にも同様の理由で社内の若者に以下の本を勧めたのですが「英語の本は読めない」という理由で拒絶されたことがありました。
仮にも技術者を名乗る人間が、たかたが200ページ程度の洋書くらい読めないなんて、どれだけ知的に怠惰なのだと私は呆れるのです。
http://reinforce-lab.github.io/blog/2013/08/13/blebook-ch2-ble-spec/
BLEはどのようにして相互に通信をするのか
GAPはBLEが通信する際のadvertisingや接続を制御する。 そのためGAPについて理解するためには、BLEがどのように通信をしているかを知らないといけない。
BLEは、後述するadvertisingパケットを送る側と受け取る側に分類できる。
あるデバイスのBLEがadvertisingパケットを周囲に転送するadvertisingを行い、周囲のデータをスキャンしているデバイスのBLEがそのadvertisingパケットを検知すると、接続を開始する。その後は接続が確立したBLE同士でデータパケットを送受信する通信状態になる。
GAPの役割
GAP(Generic Access Profile)は、BLEが通信において果たす役割を規定する。
役割には以下の4つがある。
① Broadcaster
データ送信だけを行い、データ受信はしない。後述するadvertisingパケットにデータを乗せて周囲にひたすら飛ばす。 例えば、自分の位置を知らせるiBeaconは周囲のBLEに位置情報を出すだけで、自分は受信をしないので、この役割に属する。
② Observer
データ受信だけを行い、データ転送はしない。後述するadvertisingパケットに乗っているデータを読み取る。 例えばiBeaconの位置情報を読み取り表示するアプリならば、データを受信だけしていればいいので、この役割に属する。
③ Central
周囲にあるBLEが送信するadvertisingパケットを検知して接続を開始し、そのBLEをネットワークに加えるかどうかの判定をする。複数のBLEとの接続も可能である。
④ Peripheral
advertisingパケットを周囲に送信して、Centralに発見してもらい、接続許可をもらい、接続を確立させる。多くの場合、1つのCentralにのみ接続する
BLEはBluetooth Low Energyの名が体を表すように低消費電力を目指して設計されている。 この4つの役割には、その低消費電力のための工夫が随所に見られる。
たとえばCentralはPeripheralに比べて複雑な処理を要する。だからCentral役はiPhoneなどのパワフルなCPUを持つ機械が担うことが多い。
そしてPeripheralをより簡素にしたことで、小さなメモリと処理能力の低いCPUしか持たないBLE ICチップでもPeripheral役の実装が可能となった。
処理能力の低いCPUは消費電力が小さく、小型で安価である。そのため多くの製品にPeripheralは実装され、広く普及している。
①と②は接続を行わず、③と④は接続を行う点に注意する。 ①②と③④でadvertisingパケットの使い方が異なっている点に注意する。①、②はBLE同士の接続を確立する必要がなく、advertisingパケットはアプリにデータを送るために使われている。一方、③、④はCentralがPeripheralを発見して、それらと接続するためにadvertisingパケットを使っている。
送受信をするなら③④だけでも可能なのに、わざわざ①②と③④に分けているのは低消費電力のためである。
③と④は接続を行っているが、接続には多くの電力を使う。そのため接続を行わず、advertisingパケットのデータだけを使って必要な情報をやりとりする①と②は消費電力を節約できる。
BLEの役割は自由に変えることができるが、多くの場合、BLEがどのような役割を果たすかは固定的である。
例えば上記の例ではBroadcasterの役割を持つiBeaconが突然Observer役として受信専用機になったり、Peripheral役になって他機との接続を試みるようにしてもメリットはないのでやらない。
別記事で述べるGATTのクライアントやサーバを、GAPのCentralやPeripheralと混同してはいけない。両者は別のものである。例えばGAPのPeripheral役のBLEでもクライアントとサーバーのどちらにでもなれる。
BLEはどのようにして相互に通信をするのか(再考)
BLE通信について、もう少し詳細に調べる。
① advertising
CentralがPeripheralに接続できるようにするためには、Peripheralは、advertisingする必要がある。
advertisingは日本語に訳せば広告、宣伝。つまり、あるBLEが自分の存在を周囲のBLEに対して宣伝し、アピールしている状態を意味する。
advertisingパケットは20ミリ秒から10.24秒の間の範囲の時間間隔で送信される。 Peripheralは、advertisingパケットを送信した後しばらくの間は、接続要求の受信待ちをする。
Centralはadvertisingパケットを受信すると接続を開始するための接続要求を送信する。
advertisingパケットは、最大31バイトのデータを含む。
そのデータは、ユーザがBLEを識別するための名前、パケットを送信しているデバイスに関する情報、デバイスが検出可能かどうかを知るために使われるいくつかのフラグなどから構成されている。(advertisingパケットについては後述)
Centralがアドバタイジンパケットを受信したとき、Centralはスキャン要求を送信することで更なるデータをPeripheralに要求できる。Peripheralはスキャン要求により追加のデータとして31バイトのスキャン応答を送信する。
BLEは2,4GHz帯の40chを使用しているが、advertisingは、WLANの干渉を避けるために40個の内の3つの周波数チャンネル37ch,38ch,39chを使って送信されている。この周波数は他の37チャンネルと比べて、WiFiと干渉を起こしにくい帯域が選ばれている。
② スキャンとInitiating
スキャンは、Centralがadvertisingパケットを受信し、スキャン要求を送信するまでの状態を示す。スキャンを行う時間をスキャンウィンドウ、1つのスキャンを行ってから次のスキャンを行うまでの時間をスキャン間隔と呼ぶ。
スキャンウィンドウをスキャン間隔で割った値を走査デューティサイクルと呼ぶ。
スキャンウィンドウがスキャン間隔と等しい場合は、一つのスキャンが終わると同時に次のスキャンが開始されるので、Centralは連続スキャンを行うことを意味する。
スキャンは3つの帯域について37ch→38ch→39chの順番で、周期的に繰り返し行われる。
initiatingとは、Centralがadvertisingパケットを受信し、Peripheralへの接続要求を送信するまでの状態を示す。
③ 接続
CentralとPeripheralが最初にデータ交換したときから接続状態にあると定義する。
接続状態において、CentralはPeripheralから決められた時間間隔でデータパケットを要求する。この間隔は、Centralによって決められ、接続間隔と呼ばれる。
ただしPeripheralはCentralに接続パラメータの更新要求を送信することができる。
接続間隔は、Bluetoothコア仕様に応じて7.5ミリ秒から4秒の間でないといけない。
Peripheralが時間制限内にCentralからのデータパケットに応答しない場合、リンクは失われたとみなす。
接続の間、デバイスは、advertising用のチャネルを除いた37個のチャンネルを使用して通信を行う。
advertisingパケットの構成
advertisingパケットは以下のような構成を持つ。nRF51822のSoft Deviceではパケットの生成は多くの部分が自動化されているので、実際にアプリケーションを作成するときに、プログラマが設定すべきなのはAD structureの部分がほとんどとなる。
・Access Address
advertisingパケットを意味するアドレスは固定値で0x8E89BED6。
・Adv PDU
Adv PDU Typeは7種類がある。
ここではadvertisingパケットに使用する4種類を紹介する。
[3:0] | Type | 接続性 | スキャン | 指向性 |
---|---|---|---|---|
0000 | ADV_IND | 有り | 有り | 無し |
0001 | ADV_DIRECT_IND | 有り | 無し | 有り |
0010 | ADV_NONCONN_IND | 無し | 無し | 無し |
0110 | ADV_SCAN_IND | 無し | 有り | 無し |
(接続性)
Centralとの接続を開始するかしないかを示す。
(スキャン)
Centralがadvertisingパケットを検知したとき、Centralからのリクエスト要求とPeripheralからのリクエスト応答の送受信をするかしないかを示す。
(指向性)
指向性が有りのタイプは、特定のデバイスのみを対象とする。このタイプのpayloadはadvertisingアドレスと対象のデバイスのアドレスしか持たず、常に接続性が「有り」になる。
指向性がないタイプは不特定多数のデバイスを対象とする。
ADV_INVは典型的なadvertisingパケットで、Peripheralは周囲にある不特定多数のHost全てに自分の存在を宣伝して、Centralがそれを検知すればスキャンパケットの送受信をした上で、Centralからの接続要求に備える。
・Advertiser’s Data
AD structureは最大31bytesまでなら、幾つでも作ることができる。31bytesの内、使わないbyteは0の値で埋める。
また、31bytesで足りない場合はScanパケットを使って更に31bytes使うこともできる。
AD structureは、そのAD structureの長さ(Length)、AD type、AD typeで指定した項目のAd Dataで構成される。
代表的なAD typeには以下がある。
名称 | AD type | Data byte数 | 概要 |
---|---|---|---|
Flags | 0x01 | 1 | Discoverや接続のタイプ |
16-bit Service UUIDs | 0x02 | 可変 | BLEの機能。UUIDの長さは2byte以上の短縮版。 |
16-bit Service UUIDs | 0x03 | 2 | BLEの機能。UUIDの長さは2byteの短縮版。 |
32-bit Service UUIDs | 0x04 | 可変 | BLEの機能。UUIDの長さは4byte以上の短縮版。 |
32-bit Service UUIDs | 0x05 | 4 | BLEの機能。UUIDの長さは4byteの短縮版。 |
128-bit Service UUIDs | 0x06 | 可変 | BLEの機能。UUIDの長さは16byte以上。 |
128-bit Service UUIDs | 0x07 | 16 | BLEの機能。UUIDの長さは16byte。 |
Shortened Local Name | 0x08 | 可変 | UTF-8で符号化されるユーザ・インタフェースの表示名などの先頭の数バイト |
Complete loca name | 0x09 | 可変 | UTF-8で符号化されるユーザ・インタフェースの表示名などの全文字 |
Tx Power Leve | 0x0A | 1 | 送信電力 |
Manifacturer Specific Data | 0xFF | 可変 | 企業の任意データ |
① Flagsの設定値
• Limited Discoverable Mode
設定値:0x01
設定した時間が経過した場合や何らかのイベントが発生した場合のみデバイスを発見できるモード。
• General Discoverable Mode
設定値:0x02
常にデバイスが発見できるモード。
• BR/EDR Not Supported
設定値:0x04
BLEのみをサポートし、4.0以前のBluetoothには対応していないことを示す。
• Simultaneous LE and BR/EDR to Same Device Capable (Controller)
設定値:0x08
BLEにも4.0以前のBluetoothにも対応していることを示す。(Peripheral側)
• Simultaneous LE and BR/EDR to Same Device Capable (Host)
設定値:0x10
BLEにも4.0以前のBluetoothにも対応していることを示す。(Central側)
②Service UUIDs
BLEでサービスというのは、機能を意味する。
温度を測る機能は温度計サービス、心拍数を測る機能は心拍計サービスと呼ばれる。
ユーザーが新しい機能を作れば、それもサービスと呼ばれる。例えばiphone(Central BLE)の画面をタッチすると、装置(Peripheral BLE)に付いているLEDが点滅する機能を作れば、それはさしずめタッチ点灯サービスとでも呼ばれるだろう。
その各サービスにはサービスを識別するためのUUIDが割り当てられている。
UUIDは通常16bytesだが、よく使われるサービスはBluetooth SIGで定義された2bytesや4bytesの短縮版がある。短いデータでUUIDを表現できれば、送信時間と電力とメモリの短縮につながるという利点がある。
例えば温度計サービスは2byteの0x1809、心拍計サービスは2byteの0x180Fが割り当てられている。
この2byteを正式な16bytesのUUIDに直すときは
0000xxxx-0000-1000-00805F9B34FB
のxxxxの部分に上記の2bytes UUIDを代入する。
一方、自分で作成したタッチ点灯サービスにはそのような短縮版はないから、はじめから16bytesのUUIDを使わないといけない。
このようにUUIDを表現するのに、短縮版を使うか、16bytesを使うかを指示するのが、このAD typeの役割である。
UUIDについてはGATTの記事でも解説する。
(今後、AD typeの解説を随時追加予定)