【JavaScript】micro:bitをプレゼンリモコンにするワンライナー

この記事は[IoTLT Advent Calendar 2018(neo)](https://qiita.com/advent-calendar/2018/iotlt_neo)の6日目の記事です。

ちょっと前に[スイッチのJoy-Conをプレゼンリモコンにするワンライナー](https://qiita.com/mascii/items/ad17ffa962bc82b9c4f6)を書いたのですが、今回は勉強がてらmicro:bitをプレゼンリモコンにするワンライナーを書いてみました。

# 動作環境
* macOS High Sierra
* Chrome 70
* micro:bit

# micro:bit側準備
## 設定
[MakeCode](https://makecode.microbit.org/)で新しいプロジェクトを作成します。

設定ボタンをクリックし、プロジェクトの設定から `No Pairing Required: Anyone can connect via Bluetooth.` を選択して事前のペアリングなしでBLEリンクできるようにしておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/ce32e69b-8fc3-2eaa-02b2-e844a827777e.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/b56ff57c-2f9f-95da-b179-e00da9b27c92.png)

設定ボタンをクリックし、拡張機能からBluetoothを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/a7611bd1-9c70-8fe0-a258-21428fecd25b.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/e7ae9eb8-3a33-b04c-e71f-8748223ba979.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/c9cf9845-67a3-1c1f-06f0-707fdb63bc47.png)

## プログラムを書く
「最初だけ」に「Bluetooth ボタンサービス」を追加しておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/703663c4-7186-c288-8a45-dd74f0fb5906.png)

たったこれだけです。

## 転送
micro:bitにプログラムを転送します。

通常は「ダウンロード」ボタンをクリックし、ダウンロードされたHEXファイルをPC側でUSBメモリのように認識しているmicro:bitにファイル転送するのですが、Chromeであれば「ペアリングしてワンクリック書き込み」(WebUSB API利用)が利用できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/1188b2c9-b105-20a3-34ba-48f833ca5bf4.png)

ペアリング後、「ダウンロード」ボタンをクリックするとプログラムを転送することができます。

# micro:bitをプレゼンリモコンにするワンライナー
以下のスクリプトをデベロッパーツール(Macであればcommand+option+I)の Console に貼り付け Enter で実行します

```javascript
(async()=>{const a="e95d9882-251d-470a-a062-fa1922dfa9a8",b="e95dda90-251d-470a-a062-fa1922dfa9a8",c="e95dda91-251d-470a-a062-fa1922dfa9a8",[d,e]=[37,39],f=a=>{const b=document.activeElement,c="IFRAME"===b.tagName?b.contentDocument:document;["keydown","keyup"].forEach(b=>{c.body.dispatchEvent(new KeyboardEvent(b,{keyCode:a,bubbles:!0}))})},g=async(a,g)=>{const h=await a.getCharacteristic(g);await h.startNotifications(),h.addEventListener("characteristicvaluechanged",a=>{1!==a.target.value.getUint8(0,!0)||(g===b?f(d):g===c&&f(e))})},h=await navigator.bluetooth.requestDevice({filters:[{namePrefix:"BBC micro:bit"}],optionalServices:[a]}),i=await h.gatt.connect(),j=await i.getPrimaryService(a);if(g(j,b),g(j,c),navigator.wakeLock){const a=b=>{"visible"!==document.visibilityState||navigator.wakeLock.request("screen").then(()=>{b&&(document.addEventListener("visibilitychange",a),document.addEventListener("fullscreenchange",a))}).catch(()=>{})};a(!0)}})();
```

デバイスを選択してペアリングします
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137045/cb7f3b17-a4b5-bf33-0378-5c211e6868b0.png)

micro:bitのBボタンでスライドを進めることができ、Aボタンでスライドを戻すことができます。

## 対応サイト
以下の対応サイトで利用できます(スイッチのJoy-Conのときと同様)

* [Google スライド](https://www.google.com/intl/ja_jp/slides/about/)(プレゼンモードのとき)
* [SlideShare](https://www.slideshare.net/)
* [Speaker Deck](https://speakerdeck.com/)
* [Qiita](https://qiita.com/)

## コード
minify前のコードはこちらです:
https://github.com/mascii/presentation-microbit
`git clone`, `npm install`, `npm run minify` でminifyしたワンライナーを出力可能です。

# WebUSB と Web Bluetooth のお話
## ブラウザに繋がるモノたち
2018年12月現在、WebUSB API や Web Bluetooth API に対応したブラウザは数少なく Chrome と Opera くらいしかないようです。
ですが、ブラウザ上でUSBやBluetoothが使えるようになることでこんな未来が来るかもしれません:

* WebUSB API: USBデバイスがブラウザとつながる
    * OSに対してのドライバーのインストールが不要になる未来がくる？
    * PaSoRi(カードリーダー)で読み込んだカードIDをブラウザ上に表示したりできるらしい[^1]
* Web Bluetooth API: Bluetoothデバイスがブラウザとつながる 
    * センサーデータなどをブラウザ上に表示したりできる
    * ブラウザ上でヘルスケアをしたりする未来がくる？
* GamepadAPI: ゲームパッドがブラウザとつながる 
    * ブラウザ上でゲームパッドを使ったゲームができる未来がくる？

ブラウザとモノが直接繋がること、これもIoTなのだと僕は思っています。

# まとめ
* micro:bitで WebUSB API によるプログラム転送と Web Bluetooth API によるブラウザとの通信を試すことができる
    * 実はmicro:bitはWebエンジニアにとって、良い教材だったりします
* JavaScriptの話になってしまいますが、Web Bluetooth APIを使うときはPromise-thenよりもasync/awaitの方が書いてて見やすかったです

# 参考サイト
* [Chromeブラウザとmicro:bitをBLE接続 - kosakalab](https://make.kosakalab.com/education/chrome_microbit/)
    * ブラウザ上で加速度センサー、磁気コンパス、温度センサー、ボタンA,B状態読み取りを試すことができます

[^1]: e-TaxがActiveXというInternetExplorerくらいでしか動かない過去の技術を使っているそうなので、いつかWebUSB APIで置き換えられて欲しいです