HoGPでAndroid端末をBLEキーボード/マウスにする

この記事は，ドコモアドベントカレンダー１４日目の記事になります。 

ドコモ　山添です。 
業務では画像認識やIoTアーキテクチャの設計、それらを活用したVR/AR等に取り組んでいます。 

14日目のこの記事では、HoGP（HID over GATT Profile）でスマホからWindows・Mac・他のスマホ等の操作を、操作される側に何もソフトを入れずに実現し、それをスマホ上のWebAPIで自動化する方法を紹介します。 

 ※ただし、機能サポートの状況だけでなく相性の問題が大きく、実際に安定して動かせる環境は限定的です

## HoGPとは？

HID over GATT Profileの略で，BLEでキーボード・マウスをつなげるためのProfileです。 

名前の通り、ヒューマンインターフェース（Human Interface Device）がBLEの汎用的なプロファイル（Generic Attribute Profile）の上に乗っかっているという構造になっており、キーボード・マウスとして操作信号を送る側がHoGPサーバ、操作信号を受け取る側がHoGPクライアントとして動作します。

### Androidでの対応状況

Android端末でHoGPサーバを起動するには、Android 5.0以上で端末のチップセットがペリフェラル(BLE機器として動作)に対応している必要があります。HoGPクライアントは、Android 4.4からサポートされています。

HoGPクライアントのマウス操作の受け取り方には、

* absolute：絶対座標、タッチパネル操作のように画面上の座標を指定
* relative：相対座標、マウスやタッチパッドでカーソルを動かすように座標を指定

があり、Android端末では「relative」のみサポートしています。PCでも「absolute」の取り扱いはスクリーンキャスト等と組み合わせてスクリーン表示とタップ位置が合うように使用しないと難しいので、「relative」で説明を進めます。

 

## Android端末でHoGPを使う

### デバイスWebAPIのHoGPプラグイン

実際に何もソフトを入れておらずIPネットワーク的にも独立しているPCを，スマホのWebブラウザから操作してみます。本記事では、デバイスWebAPIというスマートフォン上のローカルホストにセキュリティも考慮したWebAPIを構築することができる仕組みで試します。デバイスWebAPIの詳細については、ドコモアドベントカレンダー７日目に[弊社 田中が書いた記事](https://qiita.com/dcm_tanaka/items/02f44af8a2ac7e2e041a)をご参照ください。

本記事で直接説明はしませんが、Android端末でのHoGP実装そのものに興味がある方は[こちら](https://github.com/DeviceConnect/DeviceConnect-Android/tree/master/dConnectDevicePlugin/dConnectDeviceHOGP/plugin/src/main/java/org/deviceconnect/android/deviceplugin/hogp)のソースコードを参考にしてください。

### HoGPの接続確認

まず、相性の問題が大きいので、以下の手順で動作確認画面から接続が可能かを確認します。ここでは、PCとしてパナソニックLet's note CF-RZ6(Windows10)を、Android端末としてドコモL-01Jを利用して進めていきます。

1. まず、PCを操作する（キーボード・マウスのふりをさせる）Android端末に必要な設定を行います。Android端末に[Device WebAPI Manager](https://play.google.com/store/apps/details?id=org.deviceconnect.android.manager)と[HoGPプラグインのAPK](https://github.com/DeviceConnectUsers/deviceconnectusers.github.io/releases/download/v2.4.1-release-20180330-Android/dConnectDeviceHOGP.apk)をインストールしてください。

2. BluetoothをONにした状態でDeviceWebAPI Managerのアプリを起動し、右上の設定から「デバイスプラグイン管理」⇒「HOGP（Device Connect Device Plug-in）」⇒「設定を開く」を選択してください。
![0.png](https://qiita-image-store.s3.amazonaws.com/0/320414/ab95abc5-1a8c-4ea9-3ece-f9c5396e5605.png)
   HOGPの設定画面で一番上に表示されるテキスト(以下の図の場合「V20 PRO」)がBLEデバイスとしてPCから発見される名称になります。HOGPサーバ設定の「Mouse」の項目を「relative」に、「Keyboard」の項目をONにしてから、設定の「HOGPサーバ」の項目をONにしてください。
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/933b4d76-f663-aecf-27ab-5a9af07eaf6d.jpeg)
3. 次に、PCの設定を行います。PCの設定⇒「デバイス」を選択⇒
![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/91a4082b-0d2d-cd1d-dda8-f6a6824bb2de.jpeg)
   「Bluetoothとその他のデバイス」を選択（「Bluetooth」が「オフ」なら「オン」にする）⇒「Bluetoothまたはその他のデバイスを追加する」を選択⇒
![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/c084fb92-543b-147a-ac01-a62efb2b1b4b.jpeg)
   ⇒「デバイスを追加する」から、手順２での名称のデバイス（以下の図の場合「V20 PRO」）を選択してください。この際、同じ名称のデバイスが二つ見つかりますが、四角が二つ重なったアイコンのほうを選択してください。
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/fef7c144-ecfe-e04b-3a67-17ab8a7f86e0.jpeg)
PC、Android端末の両方でペアリング要求のダイアログが出ますので、許諾を行ってください。
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/c66fae75-d08e-437f-1cfb-983853efd8c6.jpeg)

4. PCの「Bluetoothとその他のデバイス」の「マウス、キーボード、ペン」のところに手順２での名称のデバイス（キーボードのアイコン）が接続済みとして表示されていること、Android端末の手順２の設定画面一番下の「デバイス一覧」に「PC名称　接続」と表示されていることを確認してください。
   ![6.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/7317bb03-13d1-38f9-e3b8-01f4b57c7726.jpeg)
上記の手順がうまくいかない場合は、
   - PC、スマホの両方でのペアリング解除（PCでペアリング解除ができない場合はPC再起動後に行う）
   - スマートフォンの設定⇒アプリ⇒HOGP（Device Connect Device Plug-in）⇒ストレージ⇒データの削除を行ってから改めて接続手順を２から実施してください。
   以降でBLEの接続が切れた場合（一旦動かせたが動かせなくなった場合）は、PC側のBluetoothをオフにしてから再びオンにしてみてください。

5. Android端末で「デバイス操作」のボタンを押すと、タッチパッドとスクリーンキーボードが表示されます。これを使ってPCの操作が可能となります。
   ![7.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/b99aec6f-2ef3-b799-f9bc-768d1a80077d.jpeg)

6. さいごに、Android端末のWebアプリ(Chromeブラウザ)からマウスカーソルの操作をしてみましょう。http://deviceconnectusers.github.io/manager/#demo にアクセスし、「Search Device」⇒Device Listから「PCの名称」を選択⇒「mouse」で表示されるタッチパッドでPCのカーソル操作ができます。
   ![8.png](https://qiita-image-store.s3.amazonaws.com/0/320414/44ba2302-70fc-2a92-59bf-cda4dcc80337.png)

HoGPを試す分には以上となります。
次章では、上記WebアプリでのデバイスWebAPIの挙動を見ていきます。



## デバイスWebAPIでのキーボード・マウスの操作信号の送信

キーボード・マウスの操作信号を送信するデバイスWebAPIの中身を見ていきます。簡単に試すためにDeviceWebAPI Managerのセキュリティ設定は解除した状態で行いますので、信頼できないネットワーク環境では行わないでください。

1. まず同一ネットワーク上に、「操作をするAndroid端末」、「操作されるPC」、それに加えてもう一台「Android端末にアクセスするためのPC」を準備してください。「操作されるPC」上からでも動作は試せますが、キーボード・マウス操作がWebAPI経由で行われるので、意図しない操作にご注意ください。

2. HoGPの接続確認が出来ている状態でAndroid端末のDeviceWebAPI Managerのアプリを起動してください。右上の設定から「外部IPを許可」を有効、「Local OAuth」と「Origin有効化」を無効にし、
![9.png](https://qiita-image-store.s3.amazonaws.com/0/320414/501b173a-66db-3676-7b39-032f5e953cf1.png)
   「DeviceWebAPI Manager」の項目をオンにしてください（「DeviceWebAPI Manager」の項目が最初からオンの場合は、一旦オフにしてから設定してください）。
![10.png](https://qiita-image-store.s3.amazonaws.com/0/320414/2cd1aeb1-e7b9-c6d2-782c-36cb6d0ba52d.png)
3. 「Android端末にアクセスするためのPC」で、Chromeブラウザから
   http://deviceconnectusers.github.io/manager/?ip=[Android端末のIPアドレス]#demo
   にアクセスしてください。前章の6でのWebアプリがPCから試せます。Chromeブラウザのデベロッパーツール(CTRL+SHIFT+i)のNetworkタブを見ながら操作することで、実際のWebAPIの挙動が確認できます。「操作されるPC」から確認する際は、右クリック用のボタンくらいにしておいたほうがいいかもしれません（「右」のボタンを左クリックすると、右クリックでのメニューが出る）。

### デバイスWebAPIの記述について

Chromeブラウザのデベロッパーツールから確認できるWebAPIの記述について解説します。

デバイスWebAPIでキーボードの操作信号で送信するためのWebAPIは以下のような記述となっています。

* 例：キーボードで「A」（'a'＋shiftキー）を入力するWebAPI

```
POST [スマートフォンのIPアドレス:4035]/gotapi/keyboard?serviceId=[仮想キーボード・マウスのID]&keyCode=0x04&modify=shift
```

ここでのserviceIdとは、デバイスWebAPIマネージャで利用できる機能を指定するIDのことで、以下の機能一覧のWebAPIで取得できます。

```
GET [スマートフォンのIPアドレス:4035]/gotapi/servicediscovery
```

レスポンスは、以下のようなJSON形式で取得できます。

```
{
	"result":0,
	"product":"Device Web API Manager",
	"version":"2.3.1",
	"services":[
		{
			"online":true,
			"scopes":[省略],
			"id":"スマートフォン機能のID",
			"name":"Host"
		},
		{
			"online":true,
			"scopes":["hogp","serviceInformation"],
			"id":"HOGP機能のID",
			"name":"HOGP"
		},
		{
			"online":true,
			"scopes":["keyboard","mouse","serviceInformation"],
            "id":"仮想キーボード・マウスのID",
			"name":"接続先PCの名前",
			"type":"BLE"
		}
	]
}
```

このレスポンス例では、スマートフォン機能(name:Host)のserviceId、機能スコープ(scopes)としてhogpが規定されたHOGP機能(name:HOGP)のserviceId、機能スコープとしてkeyboard・mouseが規定された仮想キーボード・マウス機能(name:接続先PCの名前)のserviceIdが取得できています。

他の各種操作のWebAPIについては、[こちら](https://github.com/DeviceConnect/DeviceConnect-Android/tree/master/dConnectDevicePlugin/dConnectDeviceHOGP#%E3%83%9E%E3%82%A6%E3%82%B9%E6%93%8D%E4%BD%9C)や前章の３のWebアプリ＋Chromeブラウザのデベロッパーツールからご確認ください。また、本記事では設定画面からの接続確認でHoGPの接続をしているので省略していますが、HoGPの有効化もWebAPIから制御可能です。

* HOGPサーバの有効化するWebAPI

```
POST [スマートフォンのIPアドレス:4035]/gotapi/hogp?serviceId=[HOGP機能のID]&mouse=relative&keyboard=true
```

* HOGPサーバの無効化するWebAPI

```
DELETE [スマートフォンのIPアドレス:4035]/gotapi/hogp?serviceId=[HOGP機能のID]
```



## おわりに

市販の無線キーボード・マウスでもあまり使われていない気がするHoGP機能を使い、スマホとPCの連携を行ってみました。メーカー毎に接続時の挙動が異なり（実装上の問題があるかもしれませんが）、現状ではまだまだ使い勝手はよくないですが、今後の接続性の向上や対応機器の拡大に期待したいところです。

ちなみに、デバイスWebAPIにはスマートフォンに対するスクリーンキャストや画面表示、メディアプレイヤー制御等の機能も用意されていますので、複数の端末を連動させるプロトタイピングも容易です（本格的なアプリを作る場合は用意されているセキュリティモデルに基づく開発が必要です）。

スマホを二台つなげれば、なんちゃって２画面スマホも実現できます。

![11.jpg](https://qiita-image-store.s3.amazonaws.com/0/320414/78f799fa-63c8-6caf-7098-764b56090d08.jpeg)



## 参考情報

- [iOSでチャレンジされている方がいます](http://sassembla.github.io/Public/2014:09:14%2014-40-08/2014:09:14%2014-40-08.html)が、無理だった模様です。

- Qiitaの記事としては、[AndroidでHoGPクライアント（BLEマウス）が使えるようになった記事](https://qiita.com/eggman/items/f6c06433c67cc67fd57a)が、スマホ以外では[mbed-OSでの実装に関する記事](https://qiita.com/Kyomesuke3/items/ed3ef808758b3ba9a3fa)がありました。

- GooglePlayには以前，[実験的に作ったアプリを公開している方がいました](https://play.google.com/store/apps/details?id=powl1.smartmouse)が、消してしまったようです。



## 注意事項

* 最初にも書きましたが、相性の問題が大きく，実際に動かせる環境は限定的です。検証結果については[こちら](https://github.com/DeviceConnect/DeviceConnect-Android/tree/master/dConnectDevicePlugin/dConnectDeviceHOGP#%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E7%8A%B6%E6%B3%81)をご確認ください（ただし動作確認済みの組み合わせでもまともに動くとは限りません）。

* 信頼できないネットワーク環境では、DeviceWebAPI Managerのセキュリティ設定を解除して利用しないでください。また、試した後はセキュリティ設定を元に戻すことを忘れないでください。