LINE BeaconのためにBLE (Bluetooth Low Energy)についていろいろ調べた備忘録

# はじめに
Bluetoothはよく聞いたことがあると思いますが、BLE(Bluetooth Low Energy)についてはご存知でしょうか。IoT界隈などでは有名らしいです。Rasberry Pi を LINE Beaconにしたいということで、そこで鍵になるBLEについて調べました。動作に関係することに重きをおいて調べたので書かれていない内容などあるかもしれませんがご了承ください。

# BLEの動作

### BLEの機器
- **Peripheral**(周辺機器)と**Central**(中央)がある。
- その名の通りだが、Peripheralはスピーカーやセンサーなどの子機、Centralはコンピューターなどの親機の役割。
- Centralが要求を出して、Peripheralがデータを返すのが通信の一区切り

--- 
### 帯域・チャンネル
- BLEの通信はWi-Fiと同じ2.4GHz帯だが、Wi-Fiとの干渉を防ぐため、それを40個のチャンネルに分けて利用している。
- 40個のうち3つ(始め、中、終わりの３つ)は**Advertisementチャンネル**、その他が**データチャンネル**

--- 
### 通信のモードのようなもの
BLEの通信には**Advertisement**、**Scan**、**接続関係**、**通常のデータ送受信関係**がある。

#### Advertisement
- Peripheral機器が一定間隔で自分についての情報を発信し続ける。
- その電波を感知してCentralは周りにBLE端末があることを知る。
    - スマホやPCのBluetooth設定で周辺にある機器のリストが出るのはこれのおかげ。
- この通信は上記のAdvertisementチャンネルで行われる。
- **Beaconの動作もこのAdvertisementを利用している。**

#### Scan 
- 文字通り周辺のAdvertisement機器をスキャンする。
- スマホなどでBluetooth設定を開くと出てくるローディングの正体。

#### 接続関係・データ通信関係

接続要求を出すと接続する、のような感じだと思います。
今回はあまりが関係なかったので調査しませんでした。ご了承ください。

--- 

### Service, Charachteristic
- Bluetoothヘッドホンに再生停止ボタン・音量調節ボタンなどがついているなど、一つの機器(Peripheral)でも複数の機能、データを持つ場合がありますが、それを区別する名称が**Service**になります。
- データ、その書き込み権限などが入っているのが**Charachteristic**になります。
- この２つをフォルダとファイルだと考えるといいそうです。

このService・Charachteristicに一つずつついたIDが**UUID**になります。

--- 
### 電波の強さ(RSSI)
ここだけ話の毛色が変わります。

- 無線通信の電波強度を表したものが **RSSI** (Received Signal Strength Indicator)です。
- 単位は[dBm / デシベルミリワット]で、おおよそ-30から-50で安定、-70より小さいものは遠い機器と言えそうです。
- ちなみにパソコンなどに直付けでRSSIを測定すると-15とかでした。

## AdvertismentがどうBeaconに使われているか

このあたりをRasberry Piで制御する必要があったため話が細かくなります。

### Advertismentのパケット

通信の全体としては
1. Preamble (まえがき)
2. Access Address (Advertismentなら指定値)
3. PDU (**Protocol Data Unit** : データのbodyに当たる部分です。)
4. CRC (**Cyclic Redundancy Check** : データの欠損とかがないかを確かめるための情報らしい)

で構成されます。とりあえず**PDU**をいじっておけばデータが送れるらしいです。実際、LINE Beaconでも既存のライブラリなどを用いればPDUの一部だけをこちらで指定して、他の部分は自動的にうまくやってくれます。

### PDUの詳細

ここから出てくる数字は16進法になります。基本は"0x"をつけていませんがたまにつけます。

PDUはとりあえず、**Header**(2オクテット) 、**Advertiser's Adress(AdvA)**(6オクテット)、 **Advertisement Data(AdvData)**(31オクテット)に分かれます。 

- **Header**には通信モード、機器の送受信の可不可などの情報が入っています。
- **AdvA**にはMACアドレスのようなものが入るそうです。 詳しくはよくわからなかったです。
- **AdvData**にはデータが入っています。ここをいじります。

#### AdvDataの詳細
※ここでは**Advertisement**のデータ内容なのでご注意ください。

基本的に` データの長さ | Ad Type | 値 `で1セットとなっていて、そのセット(Ad Structureというそうです。)がいくつも連なってAdvDataを形成しています。

例としてLINE Beaconで発するAdvertisementの内容を見てみます。

`02 01 06 03 03 nn nn 0b 16 nn nn 02 mm mm mm mm mm 7f 00`

(nn nn には**uuid**が、mm mm mm mm mmには**ハードウェアID**が入ります。ハードウェアIDはLINE Beaconで使うものなのでここではあまり関係がないです。)

--- 

#### まずAd Structureの１つ目が`02 01 06`です。

##### 0x02: データ長
このあと2オクテット来ますという印です。

##### 0x01: Ad Type
ここのAd Structureがなにを示しているかを表す値です。詳しくは仕様書などに記されています。
0x01は**Flags**を表しているそうです。今機器は発見できる状態か、BR/EDRがサポートされているかのような状態を次で示すことを伝えています。

ほかにも0x02, 0x03 ...とあり、後にも出てきます。

##### 0x06: 上記Flagsの値
0x06なので `0000 0110`を表しており、〜という状態であるということが読み取れます。詳しくは仕様書などを御覧ください。

--- 

#### Ad Structureの2つ目が`03 03 nn nn`です。

##### 0x03: データ長
このあと3オクテット来ますという印です。

##### 0x03: Ad Type
Ad Structureがなにを示しているかを表す値です。
0x03は**16-bit Service UUIDs**を表しているそうです。UUIDを流します。という意味です。

##### 0xnn 0xnn: 上記UUID
上記で示したとおりUUIDの値が入ってきます。

--- 

#### Ad Structureの3つ目が`0b 16 nn nn 02 mm mm mm mm mm 7f 00`です。

##### 0x0b: データ長
このあと11オクテット来ますという印です。

##### 0x16: Ad Type
Ad Structureがなにを示しているかを表す値です。
0x16は**SERVICE DATA**を表しているそうです。まずUUIDが2オクテット、その後自由なデータを流します、という意味です。

##### 0xnn 0xnn: 上記UUID
上記で示したとおりUUIDの値が入ってきます。

##### 0x02 0x[ハードウェアID] 0x7f 0x00: 自由データ

これらはLINE Beaconの仕様になるのでここでは詳しく説明しません。くわしくは [line-simple-beacon](https://github.com/line/line-simple-beacon) などを御覧ください。

# あると便利なツール・アプリ
iPhone利用者向けです。

[LightBlue](https://apps.apple.com/jp/app/lightblue/id557428110): Bluetooth周辺機器をスキャンして表示してくれるものです。上で出てきたUUIDやAdvertising Dataなども表示してくれます。ただ、(特にRasberry Piなどは) **発見モード**をオンにしておかないと表示されないのでご注意ください。

# おわりに
BLE、特にLINE Beaconで必要になりそうなパーツを自分なりにまとめてみました。後から同じようなことをやる方々のお役に立てば幸いです。


# 参考にした記事など
BLEの仕組みなどがわかりやすく説明されています。
https://houwa-js.co.jp/blog/2018/06/20180629/

用語などがわかりやすく説明されています。
https://jellyware.jp/kurage/bluejelly/ble_guide.html

Advertismentの仕様(値の設定の仕方など)が細かく記載されています。
https://sites.google.com/a/gclue.jp/ble-docs/advertising-1/advertising