Bluetooth LE (BTLE)のAdvertisement packet format
btstackのコードを追いかけていると、BTLEペリフェラルがadvertisementを行う際のパケットを規定している配列があります。具体的には、こんなのです:
const uint8_t adv_data[31]="\x02\x01\x05" "\x05\x09mbed" "\x03\x02\xf0\xff";
なんとなく、名前やUUIDを定義していると分かるのですが、この値をいじったときに、iOSのCoreBluetoothでスキャンできなくなるなどの動きになったため、どういう構造になっているのかを知りたいと思っていました。Google先生に聞いてもうまくヒットするコンテンツがなかったのですが、結局本家のBluetooth 4.0 Specificationドキュメントで答えを見つけました。2000ページ以上あるドキュメントなので、目次くらいしかみていませんが、Volume-3 (Core System Package), Part-C (Generic Access Profile), Section-11 “ADVERTISING AND SCAN RESPONSE DATA FORMAT”に必要な情報を見つけました。
小ネタですが、BTLEのadvertisement packet formatということで以下に記載します。
Packet Format
Bluetooth Specificationからの抜粋です。
- Advertisement dataは31byteで構成されます
- AD Structureと呼ばれる情報要素が31byteのpacketに詰め込まれます
- 個々のAD Structureは、Length – AD Type – AD Dataで構成されます
- 未使用部分は0で埋める
AD Type値の意味が分かれば、個々のAD Structureが何をしているのかが分かります
AD Type値の割り当て
AD TypeはAssigned Numberという別のドキュメントで定義しています(デバイス種別の追加などで新規割り当て値が増えていくため、規格文書本体とは分けて管理しているようです)。Assigned Numberを公開しているWebサイトはこちらで、そこから、Generic Access Profileに飛ぶと、目的の情報が出てきます。主な情報を記載すると:
値 | 名称 |
0x01 | Flag |
0x02 | Incomplete List of 16-bit Service UUIDs (more 16-bit UUIDs available) |
0x03 | Complete List of 16-bit Service Class UUIDs |
0x09 | Complete Local Name |
0x10 | Device ID |
Flagは各bitが意味を持っており、以下の定義になっています:
bit位置 | 意味 |
0 | LE Limited Discoverable Mode |
1 | LE General Discoverable Mode |
2 | BR/EDR Not Supported |
3 | Simultaneous LE and BR/EDR capable (Controller) |
4 | Simultaneous LE and BR/EDR capable (Host) |
5..7 | Reserved |
btstackでは0x05 = 0101bですので、「LE Limited Discoverable Mode & BR/EDR Not Supported」をadvertiseすることになります。
最終的なAdvertise Data
btstackのケースでは、以下のAD Structureをadvertiseしています(要素と記載した部分は、advertise dataには含まれません):
要素 | Length | Type | Data |
AD1 | 2 | 1 (flag) | 0x05: LE Limited Discoverable & BR/EDR Not Supported |
AD2 | 5 | 9 (Complete Local Name) | mbed |
AD3 | 3 | 2 (Incomplete List of 16-bit Service UUID) | 0xFFF0 (配列上では、上位下位バイトを逆に並べる) |
UUIDのType値を2 (Incomplete)としているのは、advertiseでは0xFFF0のみを広報しますが、GATT profileとして0x1800, 0x1801も別途通知できるようにしているためだと思います。
おわりに
AdvertiseにService UUIDを含めないことも出来るのですが、その場合、iOS CoreBluetoothのCBCentralManagerクラスインスタンスに対してscanForPeripheralsWithServices: メッセージを送った際に、引数としてUUIDを指定するとペリフェラルを検出してくれません(nil指定にする必要あり)。UUIDをadvertiseしていなので当たり前ですが、最初はbtstackが何をadvertiseしているのかを分かっていなかっため悩みました。Twitterで呟いたら、ランニングエレクトロニクスさん(@sibu2)にService UUIDを追加するように教えていただいた次第でした。
参考資料
- Bluetooth SIG – Specification, Core Version 4.0
- Bluetooth SIG - Assigned Numbers
« iPhoneからmbedをBluetooth LE (BTLE)で制御する | トップページ | ブログタイトル変更 »
「Bluetooth」カテゴリの記事
- 自宅iBeaconの改良(2014.09.17)
- REBL600FRで自宅iBeacon(2014.05.11)
- SBDBT/SBBLEとiPhoneでBLE通信を行う(2014.03.26)
- Bluetooth LE (BTLE)のAdvertisement packet format(2013.02.12)
- iPhoneからmbedをBluetooth LE (BTLE)で制御する(2013.02.11)
この記事へのコメントは終了しました。
コメント