Tech Sketch Bucket of Technical Chips by TIS Inc.

WebRTC(PeerJS)で遠隔作業支援システムを作る(5)

Pocket

WebRTCを用いた遠隔作業支援システムを作ります。 前回 はシグナリング処理からスマートグラスのカメラ映像をリアルタイムで監視端末に表示する部分までを解説しました。最終回の今回は、DataConnectionを用いたテキストメッセージや画像の転送処理、及び接続終了処理について解説し、遠隔作業支援システムとして完成させます。

DataConnectionによるデータ転送の処理フロー

前回 までで、信頼性の有る状態でDataConnectionのP2P接続が確立しました。では実際に、監視端末からスマートグラスへデータを転送します。
遠隔作業支援システムではDataConnectionを通じて以下3種類のデータを転送しますが、P2Pの通信経路を通すためにはデータをシリアライズしなければなりません。

  • イベント通知
  • テキストメッセージの転送
  • 画像の転送

転送データのシリアライズ

PeerJSはDataConnectionを確立する際のオプションとして、データのシリアライズ方式を選択できます。デフォルトはBinaryPack形式でpack/unpackを行う binary で、下記のような複雑なJavaScriptオブジェクトもバイナリシリアライズして送信することができます。

binary 以外にも、UTF8文字列をバイナリ変換してpack/unpackすることで文字化けを防ぐ(が遅くなる) binary-utf8 や、JSONとしてシリアライズする json 、及び何もしない none が選択できます。今回の検証ではデフォルトのbinaryで問題ありませんでしたが、転送したデータが壊れてしまったり文字化けしてしまった場合には、シリアライズ方式もチェックすべきでしょう。

転送データの形式

今回の遠隔作業支援システムでは、以下のようなオブジェクトを転送することにします。
type は転送されるデータの種類、 payload は転送する実際のデータです。

type

以下のような列挙型のようなオブジェクトによって、転送されるデータの種類を示します。
(JavaScriptには列挙型が無いため、実際は普通のStringオブジェクトが転送されるだけですが)

payload

転送するデータ自身です。テキストメッセージの場合は文字列そのものですし、画像データの場合はBase64でエンコードされたDataURIスキーム文字列を格納します。イベントの場合は、以下のような列挙型もどきのオブジェクトによって定義された文字列です。

今回の遠隔作業支援システムでは「マイクのON/OFF」というイベントしか定義していません。

監視端末:データ送信処理

DataConnectionが確立していますので、 DataConnection.send(data) メソッドを用いればデータを送信できます。
実際のデータ送信処理は MonitorClass.__send(type, payload) メソッドにて実装されており、マイクON/OFFのイベント通知( MonitorClass.toggleMIC() )やテキストメッセージの転送( MonitorClass.sendMessage(message) )、画像の転送( MonitorClass.sendImage(image) )は__sendを適切に呼び出すだけです。

入力フィールドから転送すべきテキストメッセージを取得する機能や、videoタグに表示されるリアルタイム映像をcanvasにキャプチャしマウスで指示を描く機能、及びその画像データをDataURIスキームで文字列化する機能はmonitor.coffeeで実装しています。
ただしWebRTCには依存しない部分ですので、本稿ではその部分の解説を省略します。詳細な実装は monitor.coffeeのコード を参照ください。

スマートグラス:データ受信処理

前回 解説しましたが、DataConnection経由でデータを受信すると DataConnection.on('data', callback) イベントが発生します。そのイベントハンドラ内で、受信したデータの type によって処理を分岐します。
イベント受信時の処理は DeviceClassに定義された DeviceClass.__eventHandler(event) メソッドに委譲していますが、テキストメッセージ受信時は、device.coffeeから渡される messageHandler(data.payload) へ処理を委譲します。同様に画像受信時も、device.coffeeから渡される imageHandler(data.payload) へ処理を委譲します。

テキストメッセージ受信時に画面にそのメッセージを表示する機能や、DataURIスキームで文字列化された画像データを画面に表示する機能はdevice.coffeeで実装しています。
ただしWebRTCには依存しない部分ですので、本稿ではその部分の解説を省略します。詳細な実装は device.coffeeのコード を参照ください。

スマートグラスへ音声・テキストメッセージ・画像で指示を出す

このようにDataConnectionを活用することにより、トラブル発生時に音声やテキストメッセージ、画像によって監視端末から指示を出すことができるようになります。

WebRTC_11-thumb-640x609-2882.png

監視端末の「MIC ON」ボタンをクリックすることで、スマートグラスと監視端末双方のマイクがONになり、作業者と支援者が音声で会話をすることが可能となります。

監視端末の入力フォームに指示メッセージを入力し「SEND MESSAGE」ボタンをクリックすることで、スマートグラスにはdevice画面④(下図)のようにメッセージが表示されます。

device_04-thumb-320x180-2841.png

また監視端末でリアルタイム映像をキャプチャして静止画にし、monitor画面⑤(下図右)のようにマウスで指示を描き「SEND IMAGE」ボタンをクリックすることで、スマートグラスにはdevice画面⑤(下図左)のような指示画像が表示されます。

device_05-thumb-320x180-2844.png monitor_05-thumb-320x180-2847.png

作業終了時の処理フロー

最後に作業終了時の処理です。

P2P接続経路の破棄

スマートデバイスと監視端末のどちらでもかまわないので「END CALL」をクリックすると、DiveceClassやMonitorClassの closeCall() メソッドが実行されます(下図はスマートデバイスから「END CALL」した場合です)。

WebRTC_12-thumb-640x368-2898.png

DiveceClassやMonitorClassの closeCall() メソッドでは、MediaConnectionとDataConnectionをcloseします。
MediaConnectionやDataConnectionはどちらかの側からcloseされると、双方で MediaConnection.on('close', callback) イベントや DataConnection.on('close', callback) イベントが発生するため、 前回 説明したように逆側の MediaConnection.close()DataConnection.close() も実行されて通信経路が破棄されることになります。

シグナリングサーバとの接続破棄+MediaStreamの破棄

最後にスマートデバイスと監視端末双方で「TERMINATE」をクリックすると、DeviceClassやMonitorClassの terminate() メソッドが起動します。

WebRTC_13-thumb-640x296-2888.png

DeviceClassやMonitorClassの terminate() メソッドを呼び出した後、自身のHTML自体を閉じることで、initialize時に接続したMediaStreamが破棄されます。

DeviceClassやMonitorClassの terminate() メソッドでは、もしまだP2P接続が確立していたら切断した後、 @peer.destroy() を実行します。これにより、Peer初期化時にpeerjs-serverに登録されたユニークIDが破棄され、WebSocket接続も閉じられます。

これらの終了処理を適切に実行することで、クライアント側・サーバ側共にリソースの再利用が可能となります。

最後に

全5回( 第1回 第2回 第3回 第4回 今回 )に渡った「WebRTC(PeerJS)で遠隔作業支援システムを作る」シリーズも、これで最終回となりました。
P2P通信を旨とするWebRTCを用いることで、これまで扱うことが困難だったリアルタイムデータの送受信が簡単に実現できます。これまでのWebの常識にとらわれないエキサイティングなシステムの実現に向け、本稿が一助になれば幸いです。

エンジニア採用中!私たちと一緒に働いてみませんか?