chakokuのブログ(rev4)

テック・コミック・ごくまれにチャリ

M5 Stick C PlusをBLE Keyboard風にしてみる->BLE KeyboardはiOSではまともに動かない

スマフォのシャッターは、BLE Keyboardの音量Up/Downで代用できることが分かっていて、M5 StickCPlusをBLE Keyboard風に仕立てたら、SitckCのボタン押下で、スマフォのシャッターが切れるはず。
KeyboardはHIDプロファイルと思っていたけど、BLEでは、HOGPと呼ばれるらしい。*1
MicroPythonのBLEサンプルでもKeyboardの実装例があるので、それを参考に音量Up/Downだけを実装したらいいのではと想像する。
Git上には、MicroPythonで実装したHIDの試作がいろいろ公開されているので、試して動くやつを選ぶ予定。
少し調べただけなのだが、HIDとして動かすには押下キーをプロファイルで伝えるだけではなく、バッテリー等のサービスも実装する必要があるようだ。公開されているサンプルにはその辺も実装されているのでよく読めばおおよそ分かるかと。
heerkog氏?のサンプルを動かしてみる。エラー無く起動できて、M5側はAdvertisingの状態
https://github.com/Heerkog/MicroPythonBLEHID/blob/master/examples/simple/keyboard_example.py

Server created
no secrets available
BLE on
Registering services
Writing service characteristics
Writing device information service characteristics
Writing battery service characteristics
Writing hid service characteristics
Advertiser created:  Keyboard  with services:  [UUID(0x1812)]
Server started
Started advertising

サンプルはエラー無く起動されるし、iOSでもデバイスを検出してconnectまでは進むのだが、、キー入力イベントを発生させてもiOS側ではキー入力したと判断されない。notifyのやり方が間違っているのだろうか。
BLEをスキャンして属性を表示させた時、バッテリーサービスは表示されるが、HIDサービスは表示されない。キー入力を扱うにはHIDサービスが見えるべきなのでは?と思うのだが、何が正しいのかよくわからない。
デバッグのためには、ArduinoとかBLEが正しく動くファームとアプリを走らせて、本来どう見えるべきかを把握しないと、何が問題なのか?分からない。

iOSとの接続ではうまくいかず、Androidで試すとキー入力ができた。Androidの場合、再接続が発生していて、これがうまくいくかどうかの違いなのだろうか。AndroidでBLEスキャナーで確認するとHIDサービスが正しく表示されている。やはり、iOSでHID
サービスが見えない状態になってるのがうまく動かない原因なんだろう。

AndroidではHIDサービスが正しく見えている

iOSではバッテリーサービスしか見えない

あてずっぽだが、、Androidで読めて、iOSで読めないというのは、HIDのプロファイルで何か非互換な書き方になっているのではと推測してみる。HOGPのキーボードでプロファイルを掲載してくれている人がいるので、このデータを使ってパケットを作ってみる。
BLE HID Keyboard(Surface キーボード) の Report Map (Report Descriptor)

作ってみたが、HIDは表示されないままであった。だとすると、、過去にArduino等で成功しているので、ArduinoでBLE Keyboardを動かして、その時の素のパケットをスキャナでキャプチャして、それをそっくりそのままMicroPythonのBLEライブラリで作るしかないか。。 本筋としては、BLEのHOGPの仕様書を探して、仕様書を満たすパケットを作るべきなんだろうけど

めざす、シャッターボタンを解析した人がいて、その記事によると、シャッタボタンはBLEのHIDとして認識されているそうなのだが、AdvertisingにはHIDが入っていて、サービス一覧にはバッテリーしかない。だから、iOSとしてはHIDサービスが表示されないのが正しい動作のようである。うーんわからん。そういうものなのか。
https://note.com/tomorrow56/n/n83cd108e65d5
ThousanDIY (Masawo Yamazaki)氏の記事より

C言語版でもiOSの互換性が問題になっている。こちらの対応策を読めば分かるかも
IoS 13 compatibility? · Issue #3 · T-vK/ESP32-BLE-Mouse · GitHub
Works with iPad Air2, iPad Pro 2, iPhone SE. Does NOT work with iPad 2 · Issue #2 · T-vK/ESP32-BLE-Keyboard · GitHub
List of supported / unsupported Apple devices (iPhones, iPads, Macs etc.) · Issue #51 · T-vK/ESP32-BLE-Keyboard · GitHub

■追記
Arduinoの世界?でも、BLE KeyboardとiOSとの接続は難航しているようで、以下の記事では、NimBLEを使うことで制御できると書かれていた。自分も同じように公開されているソースで実装したら、確かに動いた。(Arduino版ですが)
M5StickCでiPhoneのスクリーンキャプチャボタンを作る | Lang-ship

NimBLEのソースを見たり、BLEのパケットキャプチャして、MicroPython版とどう違っているのかを掘り下げたら、MicroPython版のBLE Keyboardが動くようになるかもしれない。たんなるパケットのフラグの違い程度なら直せるかもだけど、プロトコルのレベルで違っていたりしたらもうお手上げかと
NimBLE-Arduino - Arduino Reference

Gitのソースは以下。確かに、全部自力でライブラリを書いているようである。
https://github.com/h2zero/NimBLE-Arduino



■ご参考URL
https://www.renesas.com/jp/ja/document/apn/bluetooth-low-energy-protocol-stack-hogp-ascii-text-keyboard-rev100?language=ja
GitHub - Heerkog/MicroPythonBLEHID: Human Interface Device (HID) over Bluetooth Low Energy (BLE) GATT library for MicroPython.
WIP: examples/bluetooth: Add BLE HID mouse and keyboard examples. by dpgeorge · Pull Request #6559 · micropython/micropython · GitHub
WIP: examples/bluetooth: Add BLE HID mouse and keyboard examples. by dpgeorge · Pull Request #6559 · micropython/micropython · GitHub
https://www.usb.org/sites/default/files/hid1_11.pdf
https://www.renesas.com/jp/ja/document/mat/bluetooth-low-energy-protocol-stack-api-reference-manual-hogp-rev104?language=ja&r=488876

WIP: examples/bluetooth: Add BLE HID mouse and keyboard examples. by dpgeorge · Pull Request #6559 · micropython/micropython · GitHub

*1: HID over GATT Profile(HOGP)