【BLE】GAP・GATTについて調べてみた

# はじめに
本記事は、簡潔に言うと「よさげなBLE解説記事があるので、それを和訳して書き残しておこう」というものです。最近BLEマイコンを触る機会があったのですが、それまで自分が持っていた知識は以下のようなものでした。


* スマホ、イヤホン、テレビなど多くのデバイスで使用される短距離無線通信の一つ
* 周波数帯は2.4GHzで、似たような規格ではzigbeeがある
* 用途は異なるがWiFiと同じ周波数帯でもある

これでは具体的なことは何もわかっていないので、下準備として色々調べていたところBLEモジュールメーカーのAdafruitが[初心者向けにGAP,GATTについて説明している記事](https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gap)を見つけました。
今回は、これを和訳し、別途自分の理解を補足的に付け加えていこうと思います。
あくまで和訳なので、構成とタイトルは元記事そのままにしておきます。引用は自分のコメントです。
訳と理解が不正確な可能性は大いにありますので、間違いがあればご指摘いただけると幸いです。


# GAP

GAPはGeneric Access Profileの頭文字をとった言葉であり、接続とアドバタイジングをつかさどる。GAPは外界からデバイスを検知可能にしたり、デバイスが他のデバイスとやり取り可能にするかを決めている。


## Device Roles
GAPはデバイスの役割について様々に定義しているが、頭に入れておくべきはCentralとPeripheralである。

* Peripheralデバイスは、小型、省電力、リソースが限られており、もっと強力なリソースを持つCentralに接続する。例えば、心拍数モニターや、BLEの近接タグがこれに当たる。
* Centralデバイスは、普通はスマホとかタブレットなどのペリフェラルよりもプロセッサーやメモリが強力なものである。

> 例えば、ワイヤレスイヤホンでは、イヤホンがペリフェラル、スマホがセントラル。
農業IoTのような分野では、温湿度センサがペリフェラル、データを集約するラズパイなどがセントラルになります。

## Advertising and Scan Response Data
GAPでアドバタイズするには2種類の方法があり、使われるのはアドバタイジングデータペイロードとスキャンレスポンスペイロードである。
この2つのペイロードは同じで、ともに31バイトを上限としている。しかし、必須なのはアドバタイズデータだけである。というのも、アドバタイズデータは周囲のセントラルデバイスに自分が存在することを知らせるためにコンスタントに送信するものであるためだ。
一方、スキャンレスポンスペイロードは、セントラルデバイスが追加でリクエストすることができる2つめのオプショナルなペイロードである。
このペイロードは、デバイスをデザインする人がアドバタイジングデータにプラスして、例えばデバイスの名前などを送信することを可能する。

> GAPのレイヤーでは、ペリフェラルはアドバタイジングパケットというパケットを投げることが決められているということのようです。
接続が不要な通信(逆に接続をするためにセントラルに見つけてもらうために出すパケット)で、スキャンレスポンスはアドバタイジングパケットに入りきらないデータがあれば送る。という理解でいいのかと思います

## Advertising Process
次のイラストはアドバタイジングのプロセスとアドバタイジングペイロードとスキャンレスポンスペイロードがどのように働いているかを説明したものだ。
ペリフェラルは特定のアドバタイジングインターバルを設定し、インターバルが過ぎるごとにアドバタイジングパケットを送信する。長いアドバタイジングインターバルを設定することで省電力にできるが、レスポンスの応答性は下がる。(例えば2秒と20msでは20ms間隔でアドバタイズしたほうが応答性は高い)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545001/ce51e510-84e6-e08a-f81f-0ade60ad2ee4.png)


もし、このアドバタイジングパケットを拾っているデバイスが、スキャンレスポンスペイロードにも興味があり(かつペリフェラル側で許可されている場合に限り)、追加でスキャンレスポンスペイロードをリクエストし、ペリフェラルはそれに対して追加のデータを送信する。

> アドバタイジングパケットはセントラルに見つけてもらうためのものなので、間隔が長いと見つけられないよということですね。

## Broadcast Network Topology
ほとんどのペリフェラルは、他のデバイスとコネクションを確立し、GATT service とcharacteristicsを利用できるようにする(これにより双方向により大きなデータをやりとりが可能になる)ためにアドバタイジングを行っているが、一方で単にデータをアドバタイジングするだけでよいという状況もある。

この状況は主に、ペリフェラルが同時にいくつものデバイスにデータを送信したいときである。同時にいくつものデバイスにデータを送るというのは、アドバタイジングパケットにしかできない。というのも、接続を確立したデータ送受信モードでは、接続している２つのデバイス間でしかそのデータは見ることができないからだ。

次の図に示すように、アドバタイジングペイロード、もしくはスキャンレスポンスペイロードに31バイトという小さなデータのみを含むことで、小さなコストでBLEデバイスが周囲のあらゆるデバイスと一方向通信をすることが可能になる。
これはBLEの用語では「Broadcasting」として知られている。
これは、AppleのiBeaconで使われているアプローチで、例えば、Manufacturer Specific Dataフィールドを使ってカスタムペイロードをメインアドバタイジングパケットに挿入している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545001/180e1a6d-b083-9811-7af2-391ac9176c04.png)

ペリフェラル・セントラル間で接続が確立されると、アドバタイジングプロセスはストップし、アドバタイジングパケットを送信できなくなるのが一般的である。ここから先はGATTのservicesとcharacteristicsを使用し、双方向通信を行うことになる。

> 実際のところ、何秒おきかにデータを送ることができればいい場合は、このブロードキャストを使っていれば問題ありません。もっと大きなデータのやり取りが生じる場合（イヤホンとか？）の場合は、GATTというまた別の方法を使います。

# GATT
GATTとは、Generic Attribute Profileの略であり、ServisesとCharacteristicというコンセプトを使って2つのデバイスがデータを相互に送受信する方法を定義している。
GATTはAttribute protocol(ATT)という汎用のdataプロトコルを使用しており、ここではServices,Characteristicsと関連するデータを各エントリーが16bit IDであらわされたシンプルなルックアップテーブルを使用している。

GATTは、専門のコネクションが2つのデバイス間で張られたときに動くもので、これは既にGAPによってアドバタイジングプロセスは済んでいることを表している。

GATTとコネクションに関して一番に覚えるべきことは、コネクションは排他的であるということである。
その意味するところは、BLEペリフェラルは一度に一つのデバイスとしか接続できないということである。
ペリフェラルがセントラルデバイスと接続した瞬間にペリフェラルはアドバタイジングをやめるため、
その接続がブレークするまでは、他のデバイスはそのペリフェラルを接続はもちろん検知もできない。

接続を確立することはまた、2方向通信をおこなうための唯一の方法である。接続下では、セントラルはペリフェラルにデータを送ることができるし、その逆もまた可能である。

> とりあえず、次のことがポイントな気がします
① GAPによって接続を確立したあとのはなし
② 双方向通信ができる
③ 1ペリフェラルに1セントラル

## Connected Network Topology
次の図はBLEが接続された環境下でどのように動くかを説明したものである。
一つのペリフェラルは、一つのセントラル(スマホなど)にしか接続できないが、セントラルは複数のペリフェラルに接続可能である

もし2つのペリフェラル間でデータを交換する必要が出てきた場合には、すべてのメッセージがセントラルデバイスを介してやり取りされるcustom mailbox systemを実装する必要がある。

一度ペリフェラルとセントラルの間でコネクションが確立されると、コミュニケーションは双方向に行うことができるようになる。これは、GAPとアドバタイジングデータだけを使う場合の一方向ブロードキャスティングのアプローチとは異なる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545001/28883026-a1dc-8327-c35e-7021d6e0680e.png)

> 1セントラルは複数台のペリフェラルと接続可能、というのは覚えておいた方がよさそうです。確かに、パソコンはBLEのマウス、イヤホンなど複数台のデバイスとBluetooth接続していますね。

## GATT Transactions
GATTに関連して理解すべき重要なコンセプトにサーバー/クライアントの関係がある。

ペリフェラルはGATT serverとして知られている。これは、ATT lookup data,serviceとcharacteristicsの定義, サーバーへリクエストを送るGATT client(スマホ/タブレット)を保持している。

すべてのデータ取引はマスターデバイスであるGATT Clientからはじまり、GATT ClientはスレーブデバイスであるGATT Serverからのリクエストを受けつける。

コネクションが確立されると、ペリフェラルは「接続間隔」をセントラルに提案する。するとセントラルデバイスは、毎接続間隔ごとにペリフェラルへの接続を行い新しいデータがあるかなどの確認を行う。
ここで重要なのが、この接続間隔はあくまで提案に過ぎないということである！
セントラルデバイスは常にこのリクエストに応えることはできるわけではない。なぜならば、他のペリフェラルとの通信を行っていたり、システムリソースが足りなかったりするためだ。

次の図は、ペリフェラル(GATTサーバー)とセントラル(GATTクライアント)がデータをやり取りする様子を示したものである。すべてのトランザクションはマスターデバイスから始まっている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545001/131dc5c5-2435-8037-c543-18fbf4c88e12.png)

> HTTPの場合と比較して、サーバーとクライアントの命名が逆になっているように感じますね。
すべての通信がクライアント(セントラル)から始まるのは、直感的にそうな気がします。接続間隔がペリフェラルから通知されるのは、それぞれのデバイスごとに必要な接続インターバルが異なるからだと思われます。

## Services and Characteristics
BLEのGATTのトランザクションは、高レベルでネストされた(入り組んだ？)Profiles, Services, Characteristicsと呼ばれるオブジェクトに基づいている。つぎの図にその様子を示す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545001/f7f410c5-7d51-65e4-99ad-3192fc234ee8.png)

## Profiles
プロファイルは、実際にはBLEペリフェラル自体には存在せず、単純に定義済みのサービスのコレクションである。Bluetooth SIGまたは周辺機器の設計者によって事前にコンパイルされている。たとえば、心拍数プロファイルでは、心拍数Serviceとデバイス情報Serviceを組み合わされる。
GATTベースのプロファイルで公式に採用されているもののリストはこちらを参照。
[Profileの概要](Profiles Overview (https://adafru.it/E8u)) (https://adafru.it/E8u)

> GATTプロファイルは、サービスとキャラクタリスティックから構成されるということでいいと思います

## Services
サービスはデータをロジックエンティティ(実体)に落とし込むために使われ、キャラクタリスティックと呼ばれる特定のデータの塊を含んでいる。
一つのサービスは一つ以上のサービスを持つことができ、それぞれのサービスはUUIDと呼ばれるユニークな数字のIDを持っているので区別がつくようになっている。UUIDは16bit(BLEサービスで公式に採用されている)もしくは128bit(カスタマー独自のサービス用)を使用することができる。

公認のBLEサービスは[Services](https://www.bluetooth.com/specifications/gatt/services/)から閲覧可能。例えば、Heart Rate Serviceを見ると、オフィシャルのUUIDは0x180Dであり、3つのキャラクタリスティックを含み、しかし最初の一つだけが必須であることがわかる。

>公式に定義済みのものがあるようですね。この用途であれば、こういったデータを含むべきなのでこのサービスを使用すると便利。というのをあらかじめ用意してくれているのだと思います。
おそらくサービスのUUIDをみれば、何のためにどういったデータを送っているというのがわかるということだと思います。


## Characteristics
GATTで最も低層のコンセプトがキャラクタリスティックであり、これは一つのデータポイントを格納している(実際は配列も格納でき、例えばxyz軸の3軸の加速度なども入れられる)
サービスと類似してキャラクタリスティックも16bitか128bitの事前に定義されたUUIDで同定できる。我々は自由に[standard characteristics defined by the Bluetooth SIG](https://adafru.it/E8w) を使用できるし（which ensures interoperability across and BLE-enabled HW/SW）、もしくは独自に自分のペリフェラルとソフトウェアだけが理解できるキャラクタリスティックを定義しても良い。

例として[the Heart Rate Measurement characteristic](https://adafru.it/E8x)はthe Heart Rate Serviceには必須で、UUIDは0x2A37を使用している。このキャラクタリスティックは、HRM data形式の8bitの値(UINT8やUINT16など)ではじまり、この設定されたバイト数分の心臓の拍動データを含んでいる。
キャラクタリスティックは、BLEペリフェラルとのやりとりの上でメインになるので、このコンセプトを理解することは重要である。
これらはまた、BLEのペリフェラルに（セントラルから）データを送り返す際にも使われる。
というのは、ユーザーはキャラクタリスティックに書き込むこともできるからである。
ユーザーは、「UART Service」と2つのキャラクタリスティックを用いてシンプルなUART-typeのインターフェースを実装することができる。2つのキャラクタリスティックは、片方をTX,もう片方をRXチャンネルとし、片方のキャラクタリスティックはリードオンリーに設定し、もう片方には書き込みの特権を与えればよい。

> 要は、GATTで実際に見るべきデータはここに入ってるということだと思います。

# まとめ
* BLEデバイスには、ペリフェラルとセントラルがある
* GAPでは、接続を確立する前の一方向データ通信が規定されている
* GATTでは、接続が確立した後の双方向通信が規定されている
* GATTのデータはProfile,Service,Characteristicsからなり、Serviceはそのデータの用途を表すUUIDと、実データであるCharacteristicsを含む

# さいごに
記事を読んだことによって、わからないなりに少しは理解が進んだ気がします。
特にGATTなど、まだまだ理解が不十分なところは見えていますが、これをとっかかりにしてどんどん理解を進めていきたいです。
和訳文はGoogle翻訳の方がマシみたいな書き方になっているところが多々あり、読みづらくてすみません。
さらに理解が進んだら第二弾を書きたいと思います。

#参考
* [Introduction to Bluetooth Low Energy Created by Kevin Townsend](https://cdn-learn.adafruit.com/downloads/pdf/introduction-to-bluetooth-low-energy.pdf?timestamp=1583648690)