Characteristicは、Bluetooth Low Energyにおける基本的なデータ単位であり、Centralがペリフェラルデバイス上の情報を読み取ったり書き込んだりします。各Characteristicは特定のGATTサービスに属し、固有のUUIDと可能な操作を定義するプロパティのセット(read、write、notify、indicate)を持ちます。Bluetooth Core Specification 5.4 (2023)によると、Bluetooth SIGは医療、フィットネス、産業用デバイスのため500以上の標準特性を指定しています。開発者は、センサー読み取りからデバイス制御コマンドまで、あらゆるユーザーデータを送信するためにカスタム特性を作成します。
まとめ
Characteristicは、値とメタデータを含むGATTプロトコルの属性です。BLEアーキテクチャでは、データはデバイス間で直接送信されるのではなく、サービスの特性の値を読み取ったり書き込んだりすることで送信されます。サービスがフォルダなら、Characteristicはそのフォルダ内のファイルです。
各Characteristicは、宣言(declaration)、値(value)、ディスクリプタ(descriptors)の3つのコンポーネントから構成されます。宣言には、特性のUUIDとそのプロパティが含まれます。値はCentralとPeripheralの間で実際に送信されるデータです。ディスクリプタは追加の設定を提供します。
Bluetooth Core Specification 5.4 (2023)によると、BLEのすべてのデータ交換は特性に対する操作を通じて行われます。Heart Rate ProfileやBattery Serviceといった標準プロファイルでさえ、事前定義されたUUIDを持つ特性のセットの上に構築されています。これにより、事前設定なしで異なるメーカーのデバイスの互換性が保証されます。
開発者が理解すべき重要な点は、各Characteristicが異なるプロパティの組み合わせをサポートできることです。ある特性は読み取りのみ、別の特性は書き込み用、さらに別の特性は通知用である可能性があります。プロパティの正しい選択が、使用シナリオとデバイスの消費電力を決定します。
特性のプロパティ(properties)は、その特性に対して許可される操作を定義します。これはバイトマスクであり、各ビットが特定の操作を有効または無効にします。以下に主なプロパティを示します。
| プロパティ | ビット | 説明 | 一般的な使用例 |
|---|---|---|---|
| Read | 0x02 | Centralが現在の値を読める | 状態、バッテリーレベル、設定 |
| Write | 0x08 | Centralが新しい値を書ける | 制御コマンド、設定 |
| Notify | 0x10 | Peripheralが確認なしで値を送信 | ストリーミングデータ(脈拍、温度) |
| Indicate | 0x20 | Peripheralが確認付きで値を送信 | 重要データ(アラート、状態) |
| Write Without Response | 0x04 | サーバーからの確認を待たずに書き込み | 高速コマンド送信 |
パーミッション(permissions)は、GATTサーバーレベルでのアクセスレベルです。特性宣言で宣言されるプロパティとは異なり、パーミッションは各操作においてチェックされます。および暗号化や認証の要件を含むことがあります。
Bluetooth SIGは、よくあるBLEのユースケースのほとんどをカバーする500以上の標準特性を指定しています。標準UUIDを使用することで、受信デバイスが事前設定なしでデータを正しく解釈できるようになります。
以下は、もっともよく使用される標準特性です:
| UUID | 名称 | データタイプ | サービス |
|---|---|---|---|
| 0x2A19 | Battery Level | uint8 (0–100%) | Battery Service |
| 0x2A37 | Heart Rate Measurement | uint8 + フラグ | Heart Rate |
| 0x2A6E | Temperature | int16 (0.01°C) | Environmental Sensing |
| 0x2A6F | Humidity | uint16 (0.01%) | Environmental Sensing |
| 0x2A00 | Device Name | UTF-8文字列 | Generic Access |
| 0x2A01 | Appearance | uint16 | Generic Access |
既存の標準特性がタスクをカバーしている場合は、それを使用してください。これにより Bluetooth認証が簡単になり、エコシステムの互換性が向上します。SIG登録にない独自のデータのためのみ、カスタム特性を作成してください。
特性の作成は、データを提供するデバイスであるPeripheral側で実行されます。iOS (Swift)およびAndroid (Java)での実装を見てみましょう。
Core Bluetoothは、UUID、プロパティ、および初期値を持つ特性を作成するための CBMutableCharacteristic クラスを提供します。
import CoreBluetooth
let characteristicUUID = CBUUID("2A19") // バッテリーレベル特性
let characteristic = CBMutableCharacteristic(
type: characteristicUUID,
properties: [.read, .notify],
value: nil,
permissions: [.readable]
)
// 変更時に値を更新
let batteryData = Data([batteryLevel]) // uint8
peripheralManager.updateValue(
batteryData,
for: characteristic,
onSubscribedCentrals: nil
)
Androidでは、UUID、プロパティ、およびパーミッションを持つ BluetoothGattCharacteristic を使用して特性が作成されます。
import android.bluetooth.*;
UUID charUuid = UUID.fromString("00002A19-0000-1000-8000-00805F9B34FB");
BluetoothGattCharacteristic characteristic =
new BluetoothGattCharacteristic(
charUuid,
BluetoothGattCharacteristic.PROPERTY_READ
| BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ
);
// 値を設定
characteristic.setValue(batteryLevel, BluetoothGattCharacteristic.FORMAT_UINT8, 0);
gattServer.notifyCharacteristicChanged(device, characteristic, false);
Characteristicに対する操作は、3つのタイプに分けられます:読み取り(read)、書き込み(write)、および通知(notify/indicate)。選択はシナリオによります。オンデマンドデータは読み取られ、コマンドは書き込まれ、ストリーミングデータは通知にサブスクライブします。
Read:Centralが特性の値を読むリクエストを送信します。Peripheralが現在の値で答えます。この操作は同期的であり、各側からの明示的なリクエストが必要です。めったに変更されないデータ(ファームウェアバージョン、シリアル番号、設定)に使用されます。
Write:CentralがPeripheralにデータを送信します。モードは2つあります:Write with Response(Peripheralからの確認付き)とWrite Without Response(確認なし)。Write with Responseは配信を保証します—Peripheralが書き込み後に確認を送信します。Write Without Responseはより高速ですが、配信を保証しません。
NotifyおよびIndicate:PeripheralがCentralへのデータ送信を開始します。Notifyでは、データが確認なしで送信されます—Centralがパケットを受け取れなかった場合、失われます。Indicateでは、Centralが確認(PDUレベル)を送信し、配信を保証します。Indicateは遅いが、より信頼性が高いです。通知をサブスクライブするには、CentralがCCCD(Client Characteristic Configuration Descriptor)に値0x0001を書き込みます。
MTU (Maximum Transmission Unit)は、単一BLEデータパケットの最大サイズを定義します。デフォルトのMTUは23バイトで、このうち3バイトがヘッダーであり、ペイロード(ATT payload)は20バイトです。これは、大部分のセンサーデータには十分ですが、ファイル送信や大きな設定には十分ではありません。
Bluetooth Core Specification 5.4はMTU交渉(MTU negotiation)をサポートしており、CentralとPeripheralは最大517バイトまでの大きなパケットサイズで合意できます。プロセスは次のように動作します:Centralが提案するMTUを付したMTU Exchangeリクエストを送信し、Peripheralが自分のMTUで答え、両方のうち小さいほうが使用されます。
// iOSが接続時にMTUを要求
// iOSの最大MTUは185バイト
func peripheral(
_ peripheral: CBPeripheral,
didDiscoverServices error: Error?
) {
// 特定のペリフェラルにMTUを要求
peripheral.maximumWriteValueLength(for: .withResponse)
}
Bluetooth SIG (2023)によると、MTUを23から185バイトに増やすことで、パケット数が減ることにより、データ送信のオーバーヘッドが最大80%減少します。高周波数の読み取り(例:心電図や加速度計)を送信するアプリケーションでは、ストリームの安定性にMTUの拡大が不可欠です。
よくある質問
BLE仕様は、サービス内の特性の数を制限していません。実際には、GATTサーバーの利用可能なメモリとパフォーマンス要件によって制限が決まります。エンベデッドデバイスの場合、サービスあたり10–15つ以上の特性は推奨されません。
Notifyは確認なしでデータを送信します—パケットが送信者に通知されることなく失われる可能性があります。Indicateはプロトコルレベルでの確認(ACK)を必要とし、配信を保証します。Indicateは遅いが、より信頼性が高いです。重要なデータ(アラート、コマンド)にはIndicateを使用してください。
はい、特性はプロパティの組み合わせを持つことができます。例えば、設定用特性は、Read(現在の値の読み取り)とWrite(設定の変更)の両方をサポートできます。ユースケースに応じてプロパティを組み合わせてください。
MTU交渉を使用してパケットサイズを185–517バイトに拡大します。データがまだ大きい場合は、アプリケーションレベルでフラグメンテーションを実装します。データを数つの連続リクエストに分け、整合性を管理します。
タスクが標準特性でカバーできる場合は、Bluetooth SIG登録のUUIDを使用してください。これにより認証が簡単になり、エコシステムの互換性が確保されます。独自のサードパーティのデータのためのみ、カスタムUUIDを作成してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。