Windows C#でBLE HID(HoGP) Peripheral コンソールアプリを作成する

# bleHID
C#、.NetFrameworkを使い、Bluetooth LEのHIDリモコンデバイスとして動作するWindowsコンソールアプリです。
HoGPでWindowsと他の機器を接続する場合、WindowsはCentral側となりBLE接続キーボード等のPeripheralからの入力を受ける使い方が一般的ですが、今回はWindowsをPeripheral側としてHIDリモコンの機能を実装します。
![win_HoGP_Peripheral.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/673957cf-2aad-59b5-7114-01b164f1ba03.png)

## Requirement
### ハードウェア動作環境
Windows上でBluetooth LEが使用できるハードウェアが必要です。Windowsに実装されているBluetoothのデバイス(USBドングル等)によっては、Central側としては使えてもPeripheral側としては使えないものも存在しますので確認が必要です。

確認方法としては、microsoft製ツール: Bluetooth LE ExplorerでVertual PeripheralやVertual Keybordが正常に動作すれはPeripheral側として動作できていると言えます。

https://apps.microsoft.com/store/detail/bluetooth-le-explorer/9N0ZTKF1QD98

Peripheral側として動作しない場合は、USBドングルを調達します。TP-Link UB500は動作確認が取れています。

https://www.amazon.co.jp/dp/B098K3H92Z

### ソフトウェア開発環境
@gpsnmeajpさんの記事に従ってコンソールアプリケーションの開発環境を整えます。

* Visual Studio 2019 Communityをインストール
* Windows SDKをインストール
* .Net Framework 4.7 コンソールアプリケーションのプロジェクトを作成
* Microsoft.Windows.SDK.ContractsをNuGetでインストール
* packages.config を PackageReference に移行

https://qiita.com/gpsnmeajp/items/481fd731851e0e538263

開発環境が整ったら、ソースコードをビルドし実行します。

## Source code
### bleHID.exe
HIDリモコンデバイスとして動作し、UDPサーバーが別プロセスから受信したキーコードをCentral機器へ通知します。
ビルド時の注意点として、BLEのリセットの目的でBluetoothハードウェアのOFF/ONを行うライブラリを使用しているためAnyCPUでは動作しません。x86, x64などでビルドする必要があります。

https://github.com/fknaopen/WindowsHoGPPeripheral/tree/master/src/bleHID

### bleHIDsockClient.exe
UDPクライアントでbleHID.exeへキーコードを送るサンプルです。

https://github.com/fknaopen/WindowsHoGPPeripheral/tree/master/src/bleHIDsockClient

## Usage

まず、Windows上でbleHID.exeを起動します。
起動すると、bleHID.exeはHID機器としてAdvertiseを開始します。
![ble1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/61ccb527-6cb9-5a35-218d-2f82d1c87ce1.png)
Central機器で、Advertiseを受けたらConnectします。
![ble_c1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/65e27bed-77d0-74d8-11b2-b4a6baf42275.png)
![ble2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/62e31986-5b00-b343-cb00-97fea820a292.png)
次に、Windows上でbleHIDsockClient.exeを起動すると、サンプルでは自動でbleHID.exeへUDPで接続してキーコードを送信します。
![ble3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/78f45eaa-e4bc-f8d4-3ce4-61e47d221b5f.png)
![ble_c2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6824/898192b5-b665-5a9e-d0d5-3ff1dac48140.png)
このプログラムを実際に使うときには、bleHID.exeは最小化して起動しておき、作成するアプリ側にはUDPクライアントを実装しキーコードを送ると良いです。

参考: 今回接続テストに使用したCentral機器は以下のものです。

https://qiita.com/nfukuoka/items/5515d34779ee8b264334

# Note

* 市販のリモコン等のデバイスは電池で動き省電力化のためTypeはPUBLICになっているものが多いのですが、このアプリのようにWindowsをPeripheralにした場合のBD_ADDRESSのTypeはRANDOMが使われるようです。よって、Central側の実装にはBD_ADDRESSが変更される事への対応が必要です。
* Windows上で動作しているこのアプリを再起動した場合、Central側も再起動しないとAdvertiseを受けた後、Connectしようとして ErrorCode 574や532で失敗するようです。
-> E NimBLEClient: "Connection failed; status=574"--> 0x 23E
-> E NimBLEClient: "Connection failed; status=532"--> 0x 214
https://github.com/h2zero/NimBLE-Arduino/issues/140
今回は業務要件的にCentral側の再起動は不可能なため、このアプリの起動時にBluetoothDeviceをOFF->ONする処理を入れて対策しましたが、これは正しい方法ではないかもしれません。より良い方法があれば教えていただけると嬉しいです。

# 参考文献
C#でWindowsをBLEデバイスにする(Peripheral & GATT Server)
https://qiita.com/gpsnmeajp/items/481fd731851e0e538263

Bluetooth LE Explorer::Vertual Keybord
https://github.com/microsoft/BluetoothLEExplorer

備忘録 - BLE - 概要
https://shizuk.sakura.ne.jp/bluetooth/ble/overview.html