Descriptor:Client Characteristic Configurationと実例

著者: IT Sectr 公開日: 2026-07-15 読了時間: 8 分

Descriptor はBLEキャラクタリスティックの補助属性であり、その値に関するメタデータや設定を提供します。Bluetooth Core Specification 5.4はデスクリプタをGATTプロファイルの不可欠な部分として定義しています:測定単位、値の範囲、テキスト名を記述し、通知の購読を管理します。最もよく知られているデスクリプタはClient Characteristic Configuration Descriptor(CCCD、0x2902)で、Centralがキャラクタリスティックからの通知を購読できるようにします。Bluetooth SIGによると、8つの標準デスクリプタが規定されており、追加のメタデータのために開発者がカスタムデスクリプタを作成することもできます。

重要ポイント

  • Descriptor — キャラクタリスティックの値に関するメタデータや設定を含む補助属性です。
  • CCCD(0x2902) — 最も重要なデスクリプタ:Centralはこれを介してキャラクタリスティックの変更通知を購読します。
  • 標準デスクリプタには、テキスト名のためのUser Description(0x2901)とデータ形式のためのPresentation Format(0x2904)があります。
  • 各キャラクタリスティックは複数のデスクリプタを持つことができますが、各標準タイプは1つまでです。
  • Core Bluetoothは自動的にデスクリプタを作成しますが、特定のメタデータのためにカスタマイズすることもできます。

BLEにおけるDescriptorとは?

Descriptor はGATTプロトコルの属性で、Characteristicに付随し、その値や使用方法に関する追加情報を提供します。GATTの用語では、キャラクタリスティックがデータであり、デスクリプタはそのデータのメタデータです。

各Characteristicは0個以上のデスクリプタを持つことができます。デスクリプタはGATTテーブル内で個別の属性として定義され、Bluetooth SIG空間に独自の16ビットUUIDを持ちます。デスクリプタは独立して存在できず、常に特定のキャラクタリスティックに紐付けられています。

Bluetooth Core Specification 5.4(2023)によると、デスクリプタは標準(Bluetooth SIGが定義)とカスタム(開発者が定義)の2つに分類されます。標準デスクリプタは0x2900~0x2908の範囲のUUIDを持ち、厳密に定義された機能を実行します。カスタムデスクリプタはカスタムサービスやキャラクタリスティックと同様に128ビットUUIDを使用します。

デスクリプタはBLE接続の動作を設定するための重要なメカニズムです。CCCD(0x2902)なしでは通知を購読できず、Presentation Format(0x2904)なしではCentralがキャラクタリスティックの生のバイトを解釈できません。

Client Characteristic Configuration Descriptor(CCCD)

CCCD(UUID 0x2902)はBLEで最も重要かつ広く使用されているデスクリプタです。キャラクタリスティックからのNotifyおよびIndicateに対するCentralの購読を管理します。CCCDに書き込まなければ、Notifyプロパティがあってもキャラクタリスティックは通知を送信しません。

CCCDは16ビットの値で、最下位ビット(0x0001)がNotifyを有効にし、2番目のビット(0x0002)がIndicateを有効にします。CentralはCCCDに目的の値を書き込むことで通知を購読します。Centralが0x0000を書き込むと購読は解除されます。

CCCDの仕組みは次のとおりです:CentralがNotifyをサポートするキャラクタリスティックを検出すると、そのCCCDデスクリプタを見つけて0x0001を書き込みます。その後、Peripheralがキャラクタリスティックの値を更新するたびに、Handle Value Notificationを介して購読中のCentralに自動的に送信されます(Centralからの要求なしで)。

Apple Core Bluetooth Programming Guideによると、キャラクタリスティックに対してsetNotifyValueを呼び出すと、CCCDはシステムによって自動的に管理されます。開発者が手動でCCCDを探して書き込む必要はありません。Core Bluetoothが通知の有効化時に自動的に実行します。

プログラムによる通知の購読

iOSでは、CBPeripheralオブジェクトのsetNotifyValueメソッドで購読します。

swift
import CoreBluetooth

// キャラクタリスティック通知を購読
peripheral.setNotifyValue(true, for: characteristic)

// デリゲートが更新値を受信
func peripheral(
    _ peripheral: CBPeripheral,
    didUpdateValueFor characteristic: CBCharacteristic,
    error: Error?
) {
    // characteristic.valueに新しいデータがあります
    guard let data = characteristic.value else { return }
}

Androidでは、BluetoothGatt.setCharacteristicNotificationを使用して通知を購読します。開発者は手動でCCCDに値0x0001を書き込む必要もあります。

java
import android.bluetooth.*;

// 通知を有効にする
bluetoothGatt.setCharacteristicNotification(characteristic, true);

// CCCDに0x0001を書き込む
BluetoothGattDescriptor descriptor = characteristic
    .getDescriptor(
        UUID.fromString("00002902-0000-1000-8000-00805F9B34FB")
    );
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);

Bluetooth SIG標準デスクリプタ

Bluetooth SIGは一般的なキャラクタリスティック設定タスクのために8つの標準デスクリプタを定義しています。各デスクリプタには厳密に定義されたUUIDと値の形式があります。

UUIDデスクリプタ名目的値の型
0x2900Characteristic Extended Propertiesキャラクタリスティックの追加プロパティuint16(ビットマスク)
0x2901Characteristic User Descriptionキャラクタリスティックのテキスト名UTF-8文字列
0x2902Client Characteristic Configuration通知管理uint16
0x2903Server Characteristic Configurationブロードキャスト用サーバー設定uint16
0x2904Characteristic Presentation Formatデータ表示形式構造体(7バイト)
0x2905Characteristic Aggregate Format複数キャラクタリスティックの結合UUIDリスト
0x2906Valid Range有効値の範囲uint16 × 2(最小、最大)
0x2907External Report Reference外部レポート参照uint16
0x2908Report Reference内部レポート参照uint8 + uint16

Characteristic User Description(0x2901)はUIに特に便利です:アプリケーションのインターフェースに表示できるキャラクタリスティックの人間が読める名前を含みます。例えば、Battery Levelキャラクタリスティックには「バッテリー充電レベル」という値のUser Descriptionデスクリプタがあります。

Characteristic Presentation Format(0x2904)はキャラクタリスティック値の解釈方法に関する情報を含みます:形式(uint8、uint16、float)、指数、測定単位(Bluetooth SIGレジストリのUUID経由)、名前空間、説明。例えば、温度は指数-2(分度値0.01°C)、測定単位「摂氏」のint16になります。

iOSとAndroidでのDescriptorの使用方法

デスクリプタへのアクセスはiOSとAndroidで異なります。Core Bluetoothは通知が有効になると自動的にCCCDを管理しますが、Androidではデスクリプタに手動で値を書き込む必要があります。両方のアプローチを見てみましょう。

iOS:自動CCCD管理

iOSでは、開発者は通常デスクリプタと直接やりとりしません。setNotifyValueを呼び出すと、Core Bluetoothが自動的にCCCDを見つけて必要な値を書き込みます。デスクリプタの読み取りにはdiscoverDescriptorsメソッドを使用します。

swift
// デスクリプタを検出
peripheral.discoverDescriptors(for: characteristic)

// User Description値を読み取る
func peripheral(
    _ peripheral: CBPeripheral,
    didDiscoverDescriptorsFor characteristic: CBCharacteristic,
    error: Error?
) {
    for descriptor in characteristic.descriptors ?? [] {
        if descriptor.uuid == CBUUID("2901") {
            peripheral.readValue(for: descriptor)
        }
    }
}

Android:手動CCCD管理

Androidでは、開発者はキャラクタリスティックのCCCDデスクリプタを見つけて、通知を有効にするために値を書き込む必要があります。これはiOSと比較して追加の手順です。

java
// User Descriptionデスクリプタ値を読み取る
BluetoothGattDescriptor userDesc = characteristic
    .getDescriptor(
        UUID.fromString("00002901-0000-1000-8000-00805F9B34FB")
    );

if (userDesc != null) {
    bluetoothGatt.readDescriptor(userDesc);
}

カスタムデスクリプタの作成

カスタムデスクリプタは、Bluetooth SIGの標準デスクリプタで十分でない場合に使用します。例えば、医療用センサーの製造元がセンサーのキャリブレーション情報を含むデスクリプタやエラーログのデスクリプタを追加する場合があります。

カスタムデスクリプタはカスタムキャラクタリスティックと同様に128ビットUUIDで作成します。Peripheral側では、開発者が適切なAPIを介してキャラクタリスティックに追加します。Central側では、discoverDescriptorsを呼び出すと自動的に検出されます。

カスタムデスクリプタを作成する際は、値の長さが期待されるデータ型と一致し、アクセス権(読み取り/書き込み)が明示的に指定されている必要があります。カスタム目的でBluetooth SIG標準デスクリプタの範囲(0x2900~0x2908)のUUIDを使用しないでください。

DescriptorとCharacteristicの違い

キャラクタリスティックとデスクリプタはGATT属性の異なるレベルです。キャラクタリスティックはデータポイントであり、デスクリプタはそのメタデータまたは設定です。その違いは、目的、UUID、アクセスルールのいくつかの側面に現れます。

キャラクタリスティックにはGATTテーブルに常に存在する必須の宣言があります。デスクリプタはオプションであり、キャラクタリスティックにデスクリプタがない場合もあります。キャラクタリスティックは独立して読み取り、書き込み、通知の送信ができます。デスクリプタは常にキャラクタリスティックに紐付けられ、単独では存在しません。

Bluetooth Core Specification 5.4によると、GATTテーブルの属性の順序は次のとおりです:サービス宣言、キャラクタリスティック宣言、キャラクタリスティック値、キャラクタリスティックデスクリプタ(ある場合)、次のサービス。この順序はGATTクライアントの正しい動作のために必須です。

よくある質問

キャラクタリスティックにすでにNotifyプロパティがあるのに、なぜCCCDが必要なのですか?

CCCDは購読管理に必要です:Notifyプロパティはキャラクタリスティックが通知を送信できることを示すだけで、有効にはしません。CentralはCCCDに0x0001を書き込んで明示的に購読する必要があります。これにより、準備ができていないCentralへの不要なデータ送信を防ぎます。

1つのキャラクタリスティックにいくつのデスクリプタを持たせられますか?

仕様はデスクリプタの数を制限していません。実際には、各キャラクタリスティックは通常1~3個のデスクリプタを持ちます:CCCD(Notify/Indicateを持つキャラクタリスティック用)、オプションでUser DescriptionとPresentation Formatです。デスクリプタが多すぎるとGATTテーブルのサイズが増加します。

Peripheral側で手動でデスクリプタを作成する必要がありますか?

ほとんどの場合、必要ありません。iOSとAndroidのCore Bluetoothは、NotifyまたはIndicateプロパティを持つキャラクタリスティックに自動的にCCCDを追加します。カスタムデスクリプタは特定のメタデータのためにのみ手動で作成します。

CCCDにカスタムデータを書き込めますか?

いいえ、CCCDには厳密に定義された形式(uint16)と目的(通知管理)があります。他の値を書き込むとBluetooth仕様に違反し、購読が機能しなくなる可能性があります。カスタムデータには128ビットUUIDのカスタムデスクリプタを使用してください。

Characteristic User Descriptionはアプリケーションにどのように役立ちますか?

User Descriptionにはキャラクタリスティックの人間が読める名前が含まれます。例えば、UUID 0x2A6Eの代わりに「デバイスの温度」と表示できます。アプリケーションはこの名前をインターフェースに表示することで、ハードコードされた文字列なしでBLEデバイスとのやりとりをユーザーにとって理解しやすくします。

まとめ

  • Descriptor — メタデータや設定を保存するためにキャラクタリスティックに付随する補助GATT属性。
  • CCCD(0x2902) — キャラクタリスティックの通知とIndicateに対するCentralの購読を管理する主要なデスクリプタ
  • Bluetooth SIGは一般的なタスク(説明、フォーマット、設定)のために8つの標準デスクリプタ(0x2900~0x2908)を規定しています。
  • iOSではCCCDは自動管理されます。Androidでは通知を有効にするために手動で値0x0001を書き込む必要があります。
  • カスタムデスクリプタは標準デスクリプタでカバーされない独自のメタデータのために128ビットUUIDで作成します。
  • デスクリプタは独立して存在せず、常にキャラクタリスティックに紐付けられGATTテーブル内で追従します。
  • デスクリプタの適切な使用は正しいBLE接続設定とアプリケーションのデータ明確性を保証します。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください