BLEアドバタイズパケットの中身を調べてみた

#はじめに
BLEのアドバタイズパケットをスキャンして中のデータがどうなっているか調べた時のメモです

#参考
- [オライリー Bluetooth Low Energyをはじめよう](https://www.oreilly.co.jp/books/9784873117133/)
Webの情報だけではかなりわかりづらかったですが、この本をみるとかなりスッキリするのでモヤモヤしている方は読むことをお勧めします

- [Qiita：iBeaconをスキャンするWindowsデスクトップアプリ](https://qiita.com/gebo/items/469dd49ddd1e24ce7a42)

#環境
- OS=Windows10
- 開発環境=Visual Studio 2015
	- C#
	- .Net Framework 4.6.1
	- WPFアプリケーション
- BLEデバイス
	- iPhone [Light Blue-Explorer](https://itunes.apple.com/jp/app/lightblue-explorer/id557428110?mt=8) でのVirual Peripherals(BLEデバイスエミュレータ)UUID

#プログラム
GitHubにソース上げています。
[コチラ](https://github.com/gebogebogebo/BLEAdvertiseScanner)

#解説
要は **BluetoothLEAdvertisementReceivedEventArgs の中はどうなっているのか**、という話ですね。
以下でメンバの説明を簡単にします。

### Timestamp
スキャン日時

### BluetoothAddress
アドバタイズパケット発信元の Bluetoothデバイスアドレス
48bit(6byte)

### RawSignalStrengthInDBm
シグナル強度、いわゆるRSSI。数値が大きいほどシグナルが強い、近くから発信されている、ということ。

### AdvertisementType
- アドバタイズパケットの種別
- [BluetoothLEAdvertisementTypeのenum](https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementtype)
- コネクト可能とか、スキャン可能とかわかる。ここでコネクト×になっているデバイスへはコネクトしてもエラーになるだけとおもわれます。
- ~~スキャンしてGETしているのでスキャン×の場合はとれないはずかとおもわれますです。~~
- スキャン可能のときはスキャン要求して追加情報を取得することができます。（詳細はこの次のセクションで）

|定義|説明|Bluetooth LE仕様での定義
|:--------|:----------|:----------|
|ConnectableUndirected|コネクション可能、スキャン可能|ADV_IND|
|ConnectableDirected|コネクション可能、スキャン×|ADV_DIRECT_IND|
|ScannableUndirected|コネクション×、スキャン可能|ADV_SCAN_IND|
|NonConnectableUndirected|コネクション×、スキャン×|ADV_NONCONN_IND|
|ScanResponse|スキャン要求に対するスキャン応答|SCAN_RSP|

#### スキャン要求／応答について

- アドバタイズパケットは最大サイズが決まっていて、より多くの情報をアドバタイズする方法として「スキャン要求」があります。
- `AdvertisementType`が`ConnectableUndirected`、`ScannableUndirected`なパケットはスキャン要求⇒スキャン応答として追加情報をGETできます。
- スキャン要求の結果として`ScanResponse`で追加データがGETできます。
- **じゃあ、どうやってスキャン要求するのか？**ということですが、アドバタイズを開始するときに設定すると自動的にスキャン要求してその応答をGETしてくれます。（楽）
- 具体的には`BluetoothLEAdvertisementWatcher`で`Start()`する前に`ScanningMode`に`BluetoothLEScanningMode.Active`をセットするだけです。
- 詳細はGitHubのソースにも書いてあります。

```C#:スキャン応答受信_ScanningModeをアクティブスキャンにする
// https://docs.microsoft.com/ja-jp/windows/uwp/devices-sensors/ble-beacon よりPickUp
BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
watcher.Received += OnAdvertisementReceived;
watcher.ScanningMode = BluetoothLEScanningMode.Active;
watcher.Start();
```


## Advertisement.DataSections
- アドバタイズデータ本体
- リスト構造で複数データあり
- データ数＝Advertisement.DataSections.Count
- 各データはBluetoothLEAdvertisementDataSectionクラス
- プログラムで処理するとき、中を一個一個なめていくのはめんどいですよね。よく使われるものは別のメンバに展開されているのでそちらをみるといいです。

### データ(BluetoothLEAdvertisementDataSection)
#### DataType
- データの種類を示す1byteのデータ
- AD TypeとしてBLE仕様で定義されている、一覧はBLE仕様を参照のこと
	- [BLE仕様：Generic Access Profile](https://www.bluetooth.com/ja-jp/specifications/assigned-numbers/generic-access-profile)
- よく使われるAD Type

|DataType|定義|説明|備考
|:--------|:----------|:----------|:----------|
|0x01|Flags|設定情報|Advertisement.Flagsに展開されている
|0x03|Service UUID|サービスUUID、1個辺り2byteで複数個入っている場合がある|Advertisement.ServiceUuidsに展開されている
|0x08|Local Name|デバイスの名前(UTF8 - Shortened local name)|Advertisement.LocalNameに展開されている
|0x09|Local Name|デバイスの名前(UTF8 - Complete local name)|Advertisement.LocalNameに展開されている
|0xFF|Manufacture Specific|先頭2バイトがBluetooth SIGが企業に発行した識別子、以降は任意長のバイナリ・データ|Advertisement.ManufacturerDataに展開されている

- サービスUUIDについて
	- BLEデバイスがどんな機能（サービス）を持っているかを示す
	- BLE仕様で定義されている2Byteの値
	- サービスUUIDの一覧は以下BLE仕様を参照すべし
		- [BLE仕様：GATT Services](https://www.bluetooth.com/specifications/gatt/services)

#### Data
- DataTypeに対応するデータ
- Data.Lengthがデータのバイト数
- Windows.Storage.Streams.DataReaderをつかってデータを読み出しましょう

## Advertisement.Flags
- DataType=0x01のFlagsデータがここにBluetoothLEAdvertisementFlagsというEnumに展開されて入っています
- これの意味がまだわかりません・・・
- マイクロソフトの説明 → [BluetoothLEAdvertisementFlags Enum](https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementflags)

## Advertisement.LocalName
- DataType=0x08 または 0x09 のLocalNameデータがここにstring展開されて入ります
- データセクションでどっちがあるかわかりませんが、ええ感じにチョイスしていれてくれるようです
- なので、DataType=0x08とか0x09のデータをいちいち検索する必要はないです

## Advertisement.ServiceUuids
- DataType=0x03のサービスUUIDデータがここに展開されて入っています

## Advertisement.ManufacturerData
- DataType=0xFFのフリーデータがここに展開されて入っています
- CompanyIdに企業識別子が入っている。なので、企業識別子の2Byte分はここに、3Byte目以降がDataメンバにちゃんと分割されて入ってます
- 企業識別子の一覧は以下BLE仕様を参照すべし
	- [BLE仕様：Company Identifiers documents](https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers)
- ちなみにiBeaconはこの中にデータを格納しています

# おつかれさまでした
BLEはWebの情報があまりないので苦労しますが、まとめてしまうとけっこう簡単です。
もっとわかりやすいまとめサイトがほしいところです。