僕はRxJS(+noble)を使ってスマートロックを開けたかったということに気づいた
ソースを載っけることはできないんですが、手元のラズパイ的なデバイスでRxJSとnobleというnodeからBLEを制御するためのライブラリをつかってAkerunの開閉に成功しました。
かねてよりリアクティブプログラミング自体には興味があって、ずっとこれを使ってAkerun開けてみたいなぁって思っていたんですが、ついに成功しました。 (というか別に昨日ちょっとやっただけですが)
なんの説明にもならない図なんですが、以下の通りAkerunは中間のゲートウェイデバイスにより間接的にインターネットにつながるデバイスです。 ゲートウェイデバイスとはライズパイ的なデバイスのことでBluetoothやらWi-Fi/3Gやら積んであって、ネットにつながっていないセンサーデバイスから情報を吸い出す役目をすることが多いです。最近ではラズパイ3も出て標準でBluetoothとWi-Fiが搭載されたことは記憶にあたらしいですね。
普通はスマフォアプリを使って開閉を行うんですが、Akerunにも専用のゲートウェイデバイスを用意しているので、今回はそれでやってみました。 単にLinuxなのでAkerunやスマフォ端末とは違い普通にLLが動きます。
今回はBLE搭載ゲートウェイ界隈では最も使われそうなnode製のBLE制御ライブラリであるnobleを使ってみました。
AkerunのIoTをかっこよく言うと
Akerunはよくあるセンサー情報吸い上げ型のIoTデバイスと違い、
「人間が行った操作によってインターネットを通して現実世界に物理的な現象を引き起こすデバイス」
です。
※BLEを使って間接的にネット通信し最終的に錠につながったモーターを回しているだけです
なぜRx?
APIを叩くだけなら単にPromise使っていても良い気がします。asyncでもいいと思います。
ただAkerunの場合は開閉までに数えてみたら10(!!)を越えるくらいの非同期処理があります。
主には以下です。
- MQTT系(Sub/Pub)
- BLE系(電源ON/スキャン/接続/GATTの探索/データの書き込み/データの受け取り)
- WebAPI系(ごにょごにょ)
これがそれぞれの括弧の項目含めて何度かやる必要があるのと、場合によってはリトライも必要です。
上記を実現するときにコールバック地獄になるのはゴメンです。
やってみてわかりましたが、すべての処理をストリームとして流した結果、ほぼ一本の綺麗な処理で記述することができました。 あっちにいったりこっちにきたりを全くせずに記述できるのが良かったです。
特に各ノード間で連続で複数回信号を送る必要があるのですが、それを束ねる操作がとてもうまく書けました。
またほとんど知らない状態でやってみましたので、いくつかベストプラクティスをスルーしてると思いますが、 EventEmitterで書かれたnobleのラップと独自のcreateの作成やflatMapを何個も重ねた非同期処理の一本化、filterやmapやreduceなどの基本的なリスト処理の操作など交えつつ最後まで書けたので一旦いいのかなと思っています。
まとめ
今回の僕の目的は、RxJSを使ってリアクティブプログラミング自体の習得と、今後がっつりスマフォアプリがRx化されてもいつでも即戦力としてヘルプできるようになることでしたが、下手にbacon.jsなど亜種のようなものを使わずに書いてみて正解でした。
ドキュメントを見に行くと他の言語の記述の方法もあるので、一つがわかっていると頭の中の概念を転用できて便利です。
実はAkerunスマホアプリはすでにRx化されています
Androidアプリは開発当初からRxJava/RxAndroidを使って開発されていました。 iOSも現在順次RxSwiftを使って作りなおされている段階です。
がんがんRxでUIやAPIとの通信、BLEの制御やってみたい人はご応募待ってます!