みかんのゆるふわ技術ブログ

Raspberry PiやIoT関係のことを書き残していきます

Bluetooth Low Energy ~ GATTの仕組みを学ぼう

Bluetooth Low Energy (BLE) はみなさん便利に使っていますよね。

Raspberry Piや電子工作でBLEを扱おうと思うと、独特の用語?がたくさん出てきたりして、見よう見まねでDIYすると思います。 せっかくなので、この機会にBLEの標準的なフォーマットであるGATTについて、仕組みを知っておきましょう。

GATTとは?

GATT (Generic Attribute Profile) はBLE機器が持つデータ構造とその操作方法を定義したものです。

BLE機器はGATTベースのプロファイルを持っていることが多いです(Bluetoothイヤホンなどは別です)。 GATTの仕組みを理解していれば、統一的な方法でBLE機器へアクセスできますので、DIYがはかどりますね。

例えば体温計、心拍数計などはBluetooth SIGという標準化団体がGATTベースのプロファイルを定義しています。 例えば心拍計であれば、「現在の心拍数」や「どこに着ける機器か」などのデータ構造が決まっています。 これは標準規格で定義されているので、このプロファイルに対応していればメーカー関係なく同じ方法で通信ができます。

しかし、メーカー独自のプロファイルの場合でも、GATTを採用している機器なら、同じようなやり方でデータにアクセスできます。 もちろん、データの中身はメーカーごとに違うとしてもです。 独自にBLE機器をDIYする場合でも、GATTに対応していれば、数あるオープンソースのライブラリやスマホのAPIから簡単にアクセスできるので便利です。

GATTの構造

f:id:kimura_khs:20200813184343p:plain:w480

GATTプロファイルは複数のサービス (Service)からなります。 例えば、温度計、湿度計、気圧計が一体になった気象センサーがあったとしたら、 「温度計」「湿度計」「気圧計」の3つのサービスがあるかもしれません。

サービスは、複数の特性 (Characteristic)を持ちます。 特性の値を読み書きすることで、センサー値の読み取りや、機器の制御などができます。 例えば、「温度計」であれば、「現在の温度」「摂氏か華氏か」などの特性を持ち、 「現在の温度」は読み取り専用の特性、「摂氏か華氏か」は読み書きに対応して設定変更ができる特性になっているかもしれません。

サービスについて

サービスには固有のUUIDが割り当てられます。 Bluetooth SIGで規格化されたものは16bitの短縮IDとなり、メーカー独自のものは128bitのUUIDになります。 メーカー独自プロファイルであっても世界で唯一になるようにUUIDを決めることで、 このIDから「温度計」などのサービスを一意に識別できます。

Bluetooth SIGで規格化されたサービスはこちらに一覧があります。

www.bluetooth.com

例えば、デバイス情報 (Device Information)はUUID: 0x180A、心拍数 (Heart Rate)はUUID: 0x180D、などとなっています。

一方で、メーカー独自のものは128bitのUUIDです。 例えば、Texas InstrumentsのSensorTagの温湿度センサーサービスはUUID: f000aa20-0451-4000-b000-000000000000となっています。

特性について

サービスは、複数の特性 (Characteristic)、を持ちます。 特性の値を読み書きすることで、センサー値の読み取りや、機器の制御などができます。 例えば、「温度計」であれば、「現在の温度」「摂氏か華氏か」などの特性を持ち、 「現在の温度」は読み取り専用の特性、「摂氏か華氏か」は読み書きに対応して設定変更ができる特性になっているかもしれません。

プロファイルと同様、サービスや特性にも、Bluetoothの標準化団体が規格化したものと、メーカー独自に決めたものがあります。 Bluetooth SIGが標準化したものは、次のページに一覧があります。

www.bluetooth.com

特性もUUIDを持っており、中身の値の意味を一意に識別できます。 サービスと同じく、SIGが定義したものは16bitのUUID、メーカー独自のものは128bit UUIDです。

属性(ATT)とは

上の図で、特性(Characteristic)は属性(ATT)の集合体と書きました。

特性(Characteristic)は、宣言 (Declaration) と (Value)という2つの属性(ATT)を持ちます。他に説明(Descriptor)などの属性を持つ場合もあります。 宣言の部分には、アクセス方法を定義するプロパティなどが含まれます。

f:id:kimura_khs:20200813182008p:plain:w480

属性(ATT)の構造を図にしてみました。

属性は、次の4つから構成されています。

  • ハンドル(Handle) - デバイス内で属性に連番で付与される16bitの番号
  • (Type) - 値に何が入っているかを示すUUID。サービスや特性(Characteristic)を表す
  • (Value) - 属性の値で長さはいろいろ
  • 権限(Permission) - 読み書き等の権限を表す

図にすると、このようになります。

f:id:kimura_khs:20200813182016p:plain:w480

属性(ATT)は通信手順が定められており、GATTではこの属性(ATT)をデバイス間で読み書きすることで、特性(Characteristic)の読み取りや書き込みを行い、サービスを利用することになります。

例を見てみよう

Microchip社のページに、心拍系の例が載っていたので見てみます。

f:id:kimura_khs:20200813191937p:plain
出典: Microchip Developer Help

こちらの例だと、心拍系のサービスの中に、Heart Rate MeasurementBody Sensor LocationHeart Rate Control Pointの3つの特性(Characteristic)が搭載されており、それぞれ宣言(Declaration)、(Value)の属性(ATT)を持っています。 SIG標準規格なので、型(Type)のUUIDはすべて16bitになっていますね。

これを見ると、Handle=0x8002の属性(ATT)を読む(READ)ことで、心拍数[bpm]が取得できたり、Handle=0x8005を読むことで、「腕で測定している」といった情報が取得できそうですね。

さらに以下の記事で、SensorTagというBLE温湿度・気圧・照度・加速度センサーにGATTでアクセスしてみました。

www.mikan-tech.net

これらの例を見たり、身近なBLE機器へ実際にアクセスしてみたりして、GATTへの理解を深めていきましょう。