Bluetooth Low Energyのデータ通信プロトコルの基本(★)

[BLE(Bluetooth Low Energy)の開発依頼は、フィールドデザインまでお気軽にお問い合わせください。]

 接続処理が完了すると、マスター、スレーブともにデータチャネルに移ります。どちらかがサーバになり、もう一方がクライアントになります。通常は、アドバータイズをしている側(スレーブ側)が、サーバになります。そのサーバに対して、スマートフォンなどのクライアントがアクセスに行くことになります(1つの機器で、サーバの役割、クライアントの役割とも持つことが可能です)。

下記のようなプロトコルスタックになっています。正確にはGAPからLinkLayerにアクセスするケース(スキャン時、接続時)など例外的なパスはありますが、おおよそこの図で説明できます。

なお、上記のプロトコルスタック図は、サーバ側、クライアント側の両方で共通です。
LinkLayerは、LLと略すこともあります。HCIは、Host Control Interfaceの略ですが、昔はこのレイヤでHost CPUとBluetoothデバイスがUART等で接続され制御していたのですが、現在はすべてSingle Chipで処理されていますので、このレイヤはなくなっています。
ATTは、Attribute Protocolの略です。GATTは、Generic Attribute Profileの略です。GAPは、Generic Access Profileの略です。これらの詳しい説明は、以降で行います。LayerとかProfileとかProtocolとかいろいろな名称が使われてますが、通信ですので中身はプロトコル(約束事)です。


属性(Attribute)

 サーバには属性(Attribute)というデータの箱があり、それにクライアント側からアクセスします。この属性のやり取りをするプロトコルをATT(Attribute)プロトコルと呼んでいます。さらに、この属性(Attribute)を複数組み合わせて、GATTデータベースというものを作ります。そのGATTデータベースにアクセスするプロトコルをGATTプロトコルと呼んでいます。

属性(Attribute)は、下記の集まりです。これらはサーバ内部で保存しておく値ですので、どのような形で保存しておいてもかまいません。

  • Attributeハンドル(2Byte)
  • Attributeタイプ(2 or 16Byte)
  • Attribute値(0-512Byte)
  • Attributeパーミッション

 Attributeハンドルは、通し番号です。Attributeタイプは、UUIDという識別子で、その値によってサービス名(Service)を示したり、キャラクタリスティック(Characteristic)と言われるものを示したりします。Attribute値は、アプリケーションレイヤが利用するデータが入ります。Attributeパーミッションは、読み書きできるとか、読み込みのみとかの属性です。この属性(Attribute)が、いくつも集まりGATTデータベースとなっています。


ATTプロトコル

属性(Attribute)にアクセスするATTプロトコルで使われるパケットフォーマットです。

Attribute
OpCode
(1Byte)

Attribute
Parameters
(0-N Byte)

Authentication
Signature
(0 or 12Byte)

Read Request, Write Request, Handle Value Notification, Handle Value Indicationなどのハンドルを操作する場合は、上記Attribute Parametersに、Handle番号が入ります。

ATTプロトコルでは主に下記の操作ができます。カッコの中は、実際のAttribute OpCode値です。

  • Error Handling
    • Error Response(0x01)
  • Server Configuration
    • Exchange MTU Request(0x02)
    • Exchange MTU Response(0x03)
  • Find Information
    • Find Information Request(0x04)
    • Find Information Response(0x05)
    • Find By Type Value Request(0x06)
    • Find By Type Value Response(0x07)
  • Reading Attributes
    • Read By Type Request(0x08)
    • Read By Type Response(0x09)
    • Read Request(0x0A)
    • Read Response(0x0B)
    • Read Blob Request(0x0C)
    • Read Blob Response(0x0D)
    • Read Multiple Request(0x0E)
    • Read Multiple Response(0x0F)
    • Read by Group Type Request(0x10)
    • Read by Group Type Response(0x11)
  • Writing Attributes
    • Write Request(0x12)
    • Write Response(0x13)
    • Write command(0x14)
    • Prepare Write Request(0x16)
    • Prepare Write Response(0x17)
    • Execute Write Request(0x18)
    • Execute Write Response(0x19)
    • Signed Write command(0xD2)
  • Server Initiated
    • Handle Value Notification(0x1B)
    • Handle Value Indication(0x1D)
    • Handle Value Confirmation(0x1E)

 例えば、Reading Attributesの中のコマンドの1つで、クライアントがサーバのデータを読む場合は、Read Request(Attribute OpCode:0x0A)というのをクライアントからサーバに送り、サーバがRead Response(Attribute OpCode:0x0B)というのを返してきます。

 このATTプロトコルは低レベルのプロトコルなので、温度計の値を読みこむとかの操作はできません。センサーの値を読むときなどは、一つ上のレイヤのGATTプロトコルが必要になります。


GATTデータベース

属性(Attribute)を集めたGATTデータベースですが、イメージがしづらいので、実際のセンサーの値を格納したデータベースで説明します。Bluetooth Low Energy規格では、この辺が非常に理解しずらいです。理解しづらいのは、サービスの宣言までが、1つの属性(Attribute)に割り当てられてしまっているからです。
通信の世界ではなく、MySQL等のデータベースの世界になっています。

 具体的な温度計のGATTデータベースは下記のようになります。1行ずつは、属性(Attribute)になってます。

Handle Type Value Permission
0x0023

0x2800
(=サービス)

0xAA00 Read
0x0024

0x2803
(=キャラクタリスティック)

0x12(プロパティ), 0x0025(データのHandle値), 0xAA01(データのUUID値) Read
0x0025

0xAA01
(=温度計データ)

0x00, 0x00, 0x00, 0x00 (=温度値) Read
0x0026

0x2902
(=Client Config)

0x00, 0x00 Read/Write
0x0027

0x2901
(=ユーザーデータ)

“Temp Data” Read
0x0028

0x2803
(=キャラクタリスティック)

0x0A, 0x0029(データのHandle値), 0xAA02(データのUUID値) Read
0x0029

0xAA02
(=設定用)

0x01 Read/Write
0x002A

0x2901
(=ユーザーデータ)

“Temp Conf” Read

GATTプロトコル

 GATTプロトコルは、GATTデータベースにアクセスするプロトコルです。いくつかのATTプロトコルの組み合わせで実現します。

 よく使われる操作には下記のようなものがあります。

  • Discover Characteristic:クライアントがCharacteristicを探す
  • Read Characteristic Value:クライアントがCharacteristic値を読む
  • Write Characteristic Value:クライアントがCharacteristic値を書く
  • Notify Characteristic Value:サーバがCharacteristic値を通知する