3. トラブル発生時の処理フロー
トラブル発生時にはスマートグラスと監視端末双方のマイクをONにし、テキストメッセージや画像による指示を行います。これらの処理はすべて、DataConnectionを通じたデータ転送によって実現しています。
3-1. 転送データのシリアライズ
PeerJSはDataConnectionを確立する際のオプションとして、データのシリアライズ方式を選択できます。デフォルトはBinaryPack形式でpack/unpackを行うbinaryで、文字列や数値、配列、オブジェクトなどを含んだ複雑なJavaScriptオブジェクトもバイナリシリアライズして送信することができます。
binary 以外にも、UTF8文字列をバイナリ変換してpack/unpackすることで文字化けを防ぐ(が遅くなる)binary-utf8や、JSONとしてシリアライズするjson、および何もしないnoneが選択できます。今回の検証ではデフォルトのbinaryで問題ありませんでしたが、転送したデータが壊れてしまったり文字化けしてしまった場合には、シリアライズ方式もチェックしてください。
今回の遠隔作業支援システムでは、以下のようなオブジェクトを転送することにします。
{type:<転送されるデータの種類>, payload:<転送する実際のデータ>}
typeは転送されるデータの種類を示します。
TYPE = event: "event" message:"message" image: "image"
payloadは転送されるデータ自身です。テキストメッセージの場合は文字列そのものですし、画像データの場合はBase64でエンコードされたDataURIスキーム文字列を格納します。イベントの場合は、以下のような列挙型もどきのオブジェクトによって定義された文字列を与えます。
EVENT = mic: on: "mic-on" off: "mic-off"
今回の遠隔作業支援システムでは「マイクのON/OFF」というイベントしか定義していません。
3-2. 監視端末からのデータ送信
DataConnectionが確立していますので、DataConnection.send(data)メソッドを用いればデータを送信できます。
実際のデータ送信処理はMonitorClass.__send(type, payload)メソッドで実装されており、マイクON/OFFのイベント通知(MonitorClass.toggleMIC())やテキストメッセージの転送(MonitorClass.sendMessage(message))、画像の転送(MonitorClass.sendImage(image))は__sendを適切に呼び出すだけです。
class MonitorClass extends BaseClass ... toggleMIC: -> # マイクON/OFFのイベント送信 state = @ls.getAudioTracks()[0].enabled console.log "toggleMIC state:#{state}" @ls.getAudioTracks()[0].enabled = !state if state @__send TYPE.event, EVENT.mic.off else @__send TYPE.event, EVENT.mic.on sendMessage: (message) -> # テキストメッセージの送信 console.log "sendMessage: #{message}" @__send TYPE.message, message sendImage: (image) -> # 画像の送信 console.log "sendImage: #{image}" @__send TYPE.image, image __send: (type, payload) -> # 送信処理 if @edc? and @edc.open # DataConnectionが確立し利用可能な場合はデータを送信 data = {type:type, payload:payload} # 転送オブジェクト組み立て @edc.send data # データ送信 console.log "sent object:#{JSON.stringify data}" else # 何らかの理由でDataConnectionが利用できない場合はエラー発生 console.log "dataConnection is lost" @eh "dataConnection is lost" if @eh?
3-3. スマートグラスでのデータ受信
DataConnection経由でデータを受信するとDataConnection.on('data', callback)イベントが発生しますが、そのコールバック関数に受信したデータのtypeによって処理を分岐する実装を行います。
イベント受信時の処理はDeviceClassに定義されたDeviceClass.__eventHandler(event)メソッドに委譲していますが、テキストメッセージ受信時は、device.coffeeから渡されるmessageHandler(data.payload)へ処理を委譲します。同様に画像受信時も、device.coffeeから渡されるimageHandler(data.payload)へ処理を委譲します。
class DeviceClass extends BaseClass ... onConnection: (messageHandler = null, imageHandler = null)-> ... @peer.on 'connection', (dataConnection) => ... dataConnection.on 'data', (data) => # 接続相手先からデータを受信した際の処理 console.log "dataConnection.on 'data' #{JSON.stringify data}" switch data.type when TYPE.event # イベント受信時は、__eventHandlerに処理を委譲 console.log "event received:#{data.payload}" @__eventHandler data.payload when TYPE.message # テキストメッセージ受信時は、device.coffeeから渡されるmessageHandlerへ処理を委譲 console.log "message received:#{data.payload}" messageHandler data.payload if messageHandler when TYPE.image # 画像受信時は、device.coffeeから渡されるimageHandlerへ処理を委譲 console.log "image received:#{data.payload}" imageHandler data.payload if imageHandler else # 上記以外のtypeの場合は何もしない console.log "unknown data type" ... __eventHandler: (event) -> # イベント受信時の処理 console.log "__eventHandler event:#{event}" switch event when EVENT.mic.on # マイクONイベントを受信 console.log "event: mic-on" @ls.getAudioTracks()[0].enabled = true when EVENT.mic.off # マイクOFFイベントを受信 console.log "event: mic-off" @ls.getAudioTracks()[0].enabled = false else # 上記以外のイベントを受信した場合は何もしない console.log "event: unknown"
3-3. スマートグラスへ音声・テキストメッセージ・画像で指示を出す
このようにDataConnectionを活用することにより、トラブル発生時に音声やテキストメッセージ、画像によって監視端末から指示を出すことができるようになります。
※1 「MIC ON」イベント送信
監視端末の「MIC ON」ボタンをクリックすることで、スマートグラスと監視端末双方のマイクがONになり、作業者と支援者が音声で会話をすることが可能です。
※2 指示メッセージ送信
監視端末の入力フォームに指示メッセージを入力し「SEND MESSAGE」ボタンをクリックすることで、スマートグラスにはdevice画面④(上図)のようにメッセージが表示されます。
※3 指示画像送信
監視端末でリアルタイム映像をキャプチャして静止画にし、monitor画面⑤(上図右)のようにマウスで指示を描き「SEND IMAGE」ボタンをクリックすることで、スマートグラスにはdevice画面⑤(上図左)のような指示画像が表示されます。