Generic Attribute Profile(GATT)層は、Bluetooth Low Energyデバイスがクライアントにデータを公開する方法を定義します。Bluetoothモジュールを製品に統合するエンジニアにとって、GATTサービスアーキテクチャはアプリケーションの性能、消費電力、相互接続性を直接決定します。本記事ではモジュールベース製品における実践的なGATT設計判断を解説します。

GATT階層構造

GATTはデータを4段階の階層で構成します:

レベル 説明
Profile 用途に応じたサービス群 Heart Rate Profile
Service 関連するCharacteristicのグループ Heart Rate Service (0x180D)
Characteristic プロパティ付きの名前付き値 Heart Rate Measurement (0x2A37)
Descriptor Characteristicのメタデータ Client Characteristic Configuration (0x2902)

モジュールは通常1つ以上のPrimary Serviceを実装します。Secondary Serviceは他のサービスから参照される場合のみ意味を持ちます。実用上、ほとんどのモジュール設計ではSecondary Serviceを避けます。

サービス設計

Primary Service登録

各サービスは128-bit UUIDで識別されます。2つの割り当て戦略があります:

  • 16-bit UUID(0x1800–0x26FF):Bluetooth SIGが標準サービスに割り当て。モジュールが標準プロファイル(例:Battery Service 0x180F)を実装する場合に使用。
  • 128-bitカスタムUUID:独自サービス用。ベースUUIDを生成し、各サービスとCharacteristicの下位バイトを増分。

一般的なベースUUIDパターン:

Base:    6E40XXXX-B5A3-F393-E0A9-E50E24DCCA9E
Service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
Char 1:  6E400002-B5A3-F393-E0A9-E50E24DCCA9E
Char 2:  6E400003-B5A3-F393-E0A9-E50E24DCCA9E

NordicのUARTサービスで使用されるこの手法は、製品ライン全体のUUID管理を簡素化します。

Characteristicプロパティ

各Characteristicはクライアントとの相互作用を制御するプロパティを宣言します:

プロパティ オペコード 方向 用途
Read 0x0A Client → Server 設定値の読み取り
Write 0x12 Client → Server 制御コマンド
Write Without Response 0x52 Client → Server 高頻度コマンド
Notify Server → Client センサデータストリーミング
Indicate Server → Client 重要なアラート
Broadcast Server → All ビーコン形式のアドバタイズ

Notification vs Indication

両者はサーバからクライアントへのデータプッシュですが、信頼性保証が異なります:

  • Notify(ATT_HANDLE_VALUE_NOTIFICATION):応答確認なし。レイテンシ:1 Mbps PHYで~3 ms/パケット。スループット:23-byte MTUで最大270 kbps、247-byte MTUで最大~800 kbps。
  • Indicate(ATT_HANDLE_VALUE_INDICATION):クライアントからのATT確認必須。1往復追加(~6–10 ms)。配送確認が必須のデータに使用。

10 HzでセンサデータをストリーミングするモジュールではNotifyが明確な選択です — 次のサンプルが消失パケットを補完します。アラームイベントを報告するモジュールではIndicateがクライアントの受信確認を保証します。

Descriptor設計

NotifyまたはIndicateをサポートするCharacteristicにはClient Characteristic Configuration Descriptor(CCCD、UUID 0x2902)が必須です。CCCDに0x0001を書き込むとNotifyが有効、0x0002でIndicate有効、0x0000で両者無効になります。

推奨されるオプションDescriptor:

Descriptor UUID 目的
Characteristic User Description 0x2901 人間可読名
Characteristic Presentation Format 0x2904 単位、指数、データ型
Characteristic Extended Properties 0x2900 Reliable Writeサポート

Presentation Format Descriptorは複数センサタイプを提供するモジュールで特に有用 — クライアントアプリケーションが値が温度(0x07、単位0x272F = 摂氏)か湿度(0x06、単位0x272F = パーセント)かを自動検出できます。

MTUとスループット最適化

デフォルトATT MTUは23バイト(ペイロード20バイト)。最近のスマートフォンはMTU 247以上をサポートします。接続時にMTU交換を要求すべきです:

// MTUネゴシエーションの擬似コード
ble_att_exchange_mtu_request(247);
// 交換後、有効MTU = min(ローカル, リモート)
// Notifyペイロード = MTU - 3バイト ATTヘッダ

各MTU値でのスループット比較(接続間隔30 ms、1 Mbps PHY):

MTU ペイロード/パケット パケット/間隔 スループット
23 20 B 4 21 kbps
185 182 B 1 48 kbps
247 244 B 1 65 kbps

Data Length Extension(DLE)対応モジュール(Bluetooth 4.2+)では、DLEと大MTUの組み合わせで1 Mbps PHY上のスループットが800 kbpsを超える可能性があります。

実践例:マルチセンササービス

温度、湿度、加速度センサを統合するモジュールのフラットサービス設計:

Service: 6E400001-... (Custom Sensor Service)
├── Char: 6E400002-... (Temperature, Read|Notify)
│   └── CCCD: 0x2902
│   └── Presentation Format: 0x2904 (int16, 0.01°C, unit Celsius)
├── Char: 6E400003-... (Humidity, Read|Notify)
│   └── CCCD: 0x2902
│   └── Presentation Format: 0x2904 (uint16, 0.01%, unit percentage)
├── Char: 6E400004-... (Acceleration XYZ, Notify)
│   └── CCCD: 0x2902
└── Char: 6E400005-... (Sampling Rate, Read|Write)

Sampling Rate Characteristicにより、クライアントはモジュールの通知頻度を設定できます — 10を書き込むと10 Hz、0で全通知無効化。

消費電力への影響

各Notifyは1 Mbpsで~1.2 msの無線アクティブ時間を消費します。10 Hz、20バイトペイロードの場合:

  • 無線アクティブ率:~12 ms / 1000 ms = 1.2% デューティサイクル
  • 推定平均電流:0.012 × 8 mA (TX) + 0.988 × 5 µA (sleep) ≈ 100 µA
  • CR2032電池寿命(220 mAh):~2200時間 ≈ 91日

1 Hzに低下すると、平均電流は~13 µAに低下し、電池寿命は~1.9年に延長されます。

一般的な設計上の落とし穴

  • 過剰に分割されたサービス:関連データを複数サービスに分散すると、クライアントは複数回のサービス発見が必要になります。関連Characteristicを1つのサービスにまとめましょう。
  • CCCDの欠落:Notifyプロパティを持つCharacteristicにCCCDがないと、一部のスタックがサービスを拒否します。Notify可能なCharacteristicには必ずCCCDを含めましょう。
  • UUID衝突:体系的なベースパターンなしでランダム128-bit UUIDを使用すると、製品バリアント間で衝突のリスクがあります。連続下位バイトのベースUUIDを採用しましょう。
  • 過剰なIndicate使用:高頻度データ(例:50 Hz IMU)にIndicateを使用すると、確認応答で帯域幅を浪费します。Indicateは低頻度・高信頼性イベントに限定しましょう。
  • Presentation Formatの無視:0x2904 Descriptorがないと、クライアントアプリケーションはデータ解釈をハードコードしなければならず、nRF Connect等の汎用GATTブラウザとの相互接続性が損なわれます。

結論

GATTサービスアーキテクチャはBluetoothモジュールとホスト間のアプリケーション層契約です。適切なサービス構成、Characteristicプロパティの選択、Descriptorの正しい使用は、モジュールが第三者エコシステムにクリーンに統合されるか、デバッグの負担となるかを決定します。フラットサービス設計、ストリーミングデータのNotify、体系的UUID割り当て、MTU最適化 — これらの原則がモジュールベース製品開発の確かな基盤となります。