[C#/WinRT]Bluetooth v4(BLE)機器と通信する（BLE基礎メモ）

# BLE関連記事

- [[C#/WinRT]Bluetooth v4(BLE)機器と通信する（BLE基礎メモ）](https://qiita.com/tera1707/items/e04d86a68a9f96e02fe9)
- [[C#/WinRT]Bluetooth v4(BLE)機器と通信する（C#で実装メモ）](https://qiita.com/tera1707/items/5505ed22b5ddf93795f4)
- [[C#/WinRT] WPFでBluetooth v4(BLE)機器とペアリングする](https://qiita.com/tera1707/items/1c066934774e0dd74cac)

# やろうとしていること
Bluetooth v4(BLE)で、WindowsのPCから温度センサに接続して、温度の情報をとるということがしたい。またプログラムの実装はC#で行いたい。

が、BLEについて全く知識がなかったので、プログラミングをする前にまずはBLEについて、どのようなものなのかを調べた。そのまとめ。

# 前提
実験用の機器として、OMRONの環境センサ「形2JCIE-BL　環境センサ(EnvSensor-BL01)」を使う。
その環境センサから温度を採りたいが、そもそもBLEの知識がなくさっぱり何をしてよいかわからないから調べようというのが趣旨。

# ざっくりBluetooth v4(BLE)の最低限の知識
Bluetooth v4(BLE)では、`GATT`というプロファイル(**※**)を使って、通信を行う。
※ここでいう「プロファイル」は、下に出てくる「GATTのプロファイル」とはまた別の、「Bluetoothのプロファイル」。SPPとかHIDとか、[ここ](https://ja.wikipedia.org/wiki/Bluetooth%E3%83%97%E3%83%AD%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%B8%80%E8%A6%A7)に書かれているものの並び。(ややこしい)


BLEの通信では、`セントラル`と`ペリフェラル`というものがあって、今回やろうとしているWindowsPCと温度センサをBLEでつないで温度を計測しようという構成であれば、WindowsPCが`セントラル`、温度センサが`ペリフェラル`になる。
(「ペリフェラル」というのは英語で「周辺機器」という意味。)

その2つの機器が、ルールにのっとって通信するが、そのルールには、`GATTのプロファイル`、`サービス`、`キャラクタリスティック`が定められている。

一般的な機器構成で、どのような機器構成であるか、またどのようなサービス、キャラクタリスティックを使うか(実装するか)というルールは、[SIG](https://www.bluetooth.com/about-us/)という団体が決めている。

どのような機器構成であるか、また各機器がどのようなサービス、キャラクタリスティックを備えているべきか(実装しているべきか)、というのを定めたものを、`GATTのプロファイル`という。


## GATTのプロファイルとは？
GATTのプロファイルとは、そのひとまとまりのシステムが、どのような機器(セントラル/ペリフェラル...)とそれがもつサービス、キャラクタリスティックで構成されるか、という取り決め。(以下、単に「プロファイル」という)

イメージとしては、「このプロファイルを名乗るんだったら、このサービス(機能)とキャラクタリスティック(値)をあなたが作る機器に実装してね」という感じ。

世の中には、SIGの公式プロファイルというものと、メーカー独自のプロファイルがある。

## サービスとは？キャラクタリスティックとは？
サービスの中に、複数のキャラクタリスティックが含まれている。

サービスは「機能」のイメージで、どういう機能か？ということを表す。
キャラクタリスティックは、setやgetできる「値」のイメージで、その機能からどういう値を取得できるか、または設定できるか、を表す。

イメージは、下記のような構成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/89ecebca-47fc-aed0-6eeb-cc574969b5ff.png)

## UUIDとは？
ペリフェラルのサービスと、その中のキャラクタリスティックを指定するときに使うIDのようなもの。

SIGの公式プロファイルは、よく4桁で描かれている。
https://www.bluetooth.com/specifications/gatt/services/
例）Alert Notification Service であれば`0x1811`

これは、下記のようなUUID（これを「ベースUUID」という）の「XXXX]の部分に、その4桁の短縮UUIDを入れたもの。

`0000XXXX-0000-1000-8000-00805f9b34fb`

SIGの公式プロファイルのUUIDについては、短縮形の4桁のUUIDを使うことが許されている。
通信にUUIDを載せるときに、短いほうがデータ容量節約できるから、ということで、短縮形を許しているらしい。
(短縮しなくても、フルで使ってもOK。)

SIGの公式でない、メーカー独自プロファイルやサービスのUUIDは、各メーカーがUUIDを作成して振っている。
その場合は短縮不可。


# SIG公式プロファイル「Alert Notification Profile(ANP)」の場合

プロファイルやサービス、キャラクタリスティックにどういうものがあるか、をちょっと見てみるために、SIGが定めている公式プロファイルのうちの一つを見てみる。

`Alert Notification Profile`というプロファイルは、電話やメールなどの着信を通知するプロファイルで、そのようなシステムを作るならどのような機器構成にするか、どのようなサービスやキャラクタリスティックを実装する必要があるか、を決めている。


## ANPのプロファイル

https://www.bluetooth.com/specifications/gatt/
の`ANP Alert Notification Profile`に資料がある。

ANPのプロファイルの資料の冒頭には、ざっくり下記のようなことが書かれている。

- このプロファイルを構成する機器には、2つの役割を持った機器がある
 - アラート通知のサーバー(= セントラル)
 - アラート通史のクライアント(= ペリフェラル)
- ペリフェラル側には、Alert Notification Serviceというサービスを実装すること
- セントラル側には、これこれの機能が必要(今回あまり関係なさそうなので読み飛ばし)


## ANPのサービス

https://www.bluetooth.com/specifications/gatt/
の`ANS Alert Notification Service`に資料がある。

プロファイルで必要とされた`Alert Notification Service`について書かれている。
乱暴にまとめると、下記の通り。

- サービスのUUIDは「Alert Notification Service」のものにすること。※Alert Notification ServiceのUUIDは、SIGによってきめられており、[こちら](https://www.bluetooth.com/specifications/gatt/services/)に書かれている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/bc79f2a0-5fc1-3ddb-a731-4adde3e6e540.png)

- また、サービスに含めるキャラクタリスティックは下記のものにすること。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/319b933c-1df3-4b9d-b152-58ee4e437aba.png)

## ANPのキャラクタリスティック
各キャラクタリスティックのUUIDは、SIGの決めたものにすること。
SIGの決めたUUIDは、下記のような感じで[こちら](https://www.bluetooth.com/specifications/gatt/characteristics/)に書かれている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/d6357d42-4591-65c4-ae12-7aba5bf3787c.png)

そのページのキャラクタリスティックをクリックして得られる.xmlファイルに、そのキャラクタリスティックの中身の定義？が書かれているっぽい。(今回はここの中身まではみなかった)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/060e96b5-5fad-a5cb-af38-392286c93d67.png)


# メーカー独自プロファイルの場合
今回実験で使うOMRONの環境センサ「形2JCIE-BL　環境センサ(EnvSensor-BL01)」は、SIG公式プロファイルには乗っ取らず、独自のプロファイル(=独自のサービス構成とUUID、独自のキャラクタリスティック構成とUUID)を使っている。

そのため、温度をとるためのサービスやキャラクタリスティックはSIGの公式資料にはサービスのUUIDなどは書かれていないが、代わりにメーカー(OMRON)の製品仕様の資料を見てサービスやキャラクタリスティックを調べる。[（仕様はこちら）](https://omronfs.omron.com/ja_JP/ecb/products/pdf/CDSC-015.pdf)
GATTの構成(サービスがあって、その中にキャラクタリスティックがある)は同じなので、それぞれのUUIDと仕様がわかれば、データが取れる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/b04a5073-6aff-46a0-85f1-2725c726fe1d.png)
※環境センサのユーザーズマニュアルより。
https://www.omron.co.jp/ecb/product-detail?partId=73062 の
＞![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/e1d46b43-a846-69ad-3549-51cfaa6ce59d.png) より。


メーカー独自のUUIDの場合でもベースUUIDが決まっている。
今回のOMRONの環境センサだと、`0C4CXXXX-7700-46F4-AA96D5E974E32A54`

SIG公式UUIDと同じように、XXXXの部分を、各サービス、キャラクタリスティックで指定された値に置き換えて使う。
(上の表でいうところの0x3001など)

# まとめ
上を踏まえて、今回実験で使おうとしているOMRONの環境センサの仕様の資料([参照](https://omronfs.omron.com/ja_JP/ecb/products/pdf/CDSC-015.pdf))を読むと、(ペリフェラルとして)下図のようなサービスとキャラクタリスティックの構成になっている様子。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/461a8e27-2a9c-2488-86cd-7434ff7c69cf.png)
※「最新ページ」や「ページ指定」は、センサ内に蓄えた過去のセンサ値を読み出すための機能っぽい。今回は最新データさえ取れればよいと思っているので見てない。

ここから、現在のセンサ値(温度や湿度等)をとるには、**UUID=0x3000のサービスの中の、UUID=0x3001の「センサ最新値」のキャラクタリスティックの値を読めばいい**と思われる。

次回は、そのキャラクタリスティックの値を、実際にWindowsで、C#でプログラミングして取得するということを行う。


# 用語

|用語|説明|
|:--|:--|
|BLE|**Bluetooth v4**が正式名称。Bluetooth Low Energyの略。[参考](https://micro.rohm.com/jp/techweb_iot/knowledge/iot02/s-iot02/01-s-iot02/175)|
|UUID|Universally Unique Identifier。端末などのオブジェクトを一意に識別するために使用される。[参考](https://qiita.com/4_mio_11/items/bb9da89dce629527a64b)|
|GUID|Globally Unique Identifier。マイクロソフトによるUUIDの実装の一つ。有名なのでUUIDの別名としても使われる。(なので、「世界で重複しないID」という意味ではUUIDもGUIDもほぼ同じ意味だと個人的にとらえている)|
|Gatt|Bluetooth v4(BLE) で使用している通信方式。Generic attribute profileの略。BLEのアプリケーションは、すべてこのGATTを使用して構築される。Bluetooth SIGが公式に提供しているプロファイルと、機器メーカなどの独自提供のものがある。|
|Bluetooth SIGが公式に提供しているプロファイル|Alert Notification（アラート通知）、Blood Pressure（血圧計）、Health Thermometer（体温計）、Heart Rate（心拍数）、Location and Navigation（位置とナビ）など。Bluetooth v3以前のプロファイルとは互換性がない。|
|サービス|機器の機能を表すもの。|
|キャラクタリスティック|機器の内部状態、動作指示、外部センサ値などを読み書きするもの。|
|ディスクリプタ|キャラクタリスティクスのバリューの変数の型や単位などの情報の追加と、そのバリューが変更された時にクライアントへの通知の有無といった動作指示に使う。ディスクリプタを含まないキャラクタリスティックもある。|

# コード一式
https://github.com/tera1707/BleSample

# 参考
■GATT公式
公式ページトップ
https://www.bluetooth.com/

公式プロファイルとサービス一覧
https://www.bluetooth.com/specifications/gatt/

公式サービスとUUID一覧
https://www.bluetooth.com/specifications/gatt/services/

公式キャラクタリスティックとUUID一覧
https://www.bluetooth.com/specifications/gatt/characteristics/

公式UUID
https://www.bluetooth.com/specifications/assigned-numbers/

■実験につかうオムロンBL01の仕様
BAG型
https://www.omron.co.jp/ecb/product-detail?partId=73062
https://omronfs.omron.com/ja_JP/ecb/products/pdf/CDSC-015.pdf

USB型
https://www.omron.co.jp/ecb/product-detail?partId=73063

■MSページ
CreateWatcherで使うProtocolIdの一覧
https://docs.microsoft.com/ja-jp/windows/uwp/devices-sensors/aep-service-class-ids

AQS(ウォッチャーのselector)の書き方
https://docs.microsoft.com/ja-jp/windows/uwp/devices-sensors/enumerate-devices-over-a-network

■MSサンプル
サービス/キャラクタリスティック接続と取得/設定
https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/BluetoothLE/cs

デバイス検索とペアリング
https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/DeviceEnumerationAndPairing/cs


■非公式解説ページ
以下のページを見れば、だいたいBLEがどういう構造なのかわかる。
下記のページで勉強させていただきました。ありがとうございます。
どのページも、むちゃくちゃわかりやすいです。

BLEの説明
http://jellyware.jp/kurage/bluejelly/ble_guide.html

UUIDとは？
http://jellyware.jp/kurage/bluejelly/uuid.html

BLE v4とは
https://micro.rohm.com/jp/techweb_iot/knowledge/iot02/s-iot02/01-s-iot02/39

Gattの構造
https://micro.rohm.com/jp/techweb_iot/knowledge/iot02/s-iot02/04-s-iot02/3792

NotifyとIndicateの違い
http://yegang.hatenablog.com/entry/2014/08/09/195246