LoginSignup
6
2

More than 5 years have passed since last update.

えっWebRTCって Web Real-Time Christmastreeのことだよね??【後編】

Last updated at Posted at 2018-12-25

こちらはSkyWay Advent Calendar 2018の最終日、25日目の記事です。
【前編】は、IoTLT Advent Calendar 201824日目の記事になります。


昨晩プレゼントをもらえたみなさまも、サンタクロースをやっていたみなさまも、おはようございます。
この記事は、Webリアルタイムクリスマスツリーをつくり、ローカルPCのブラウザからリモートのPCを経由してクリスマスツリーのLEDを制御し、そのリアルタイム映像をWebRTCを経由して虚ろに眺めるというプロダクトの後編となります。(長い)
いきなりこちらに来た方は、まずはじめに【前編】をご覧ください。

なにをつくるんだっけ

組み込みWebRTCに心が折れ、WebBluetoothに浮気して、最終的にこんな感じにしたくなったのでした↓

fig2.png

前編の記事では、WebからBluetoothでクリスマスツリーを操作するところまでできました。
では次にWebRTCとつなげるところからはじめましょう。

SkyWayで簡単にWebRTCを試す

SkyWayとは、WebRTCにおけるサーバサイドを全部なんとかしてくれる素敵なシステムです。
知らなかった方は以下をどうぞ。

SkyWay - Enterprise Cloud WebRTC Platform

ところで、僕はSkyWay Advent Calendar 2018の23日目にも1つ記事を書かせてもらっております。

テキスト送受信機能つきビデオチャットのサンプルをつくる

書くことになった経緯は忘れたのですが、Qiitaから通知があって思い出して頑張って書きました。
そうしたら、こんなにもWebRTCって簡単にできるのか?という気持ちになり、じゃあクリスマスツリーぐらいリアルタイムできるよね🎄🎉となって今に至るわけです。

さて、上述の記事を要約すると

  • サンプルプログラムには「ビデオチャット」と「テキストチャット」がある
  • しかしビデオとテキストの両方を同時に送るサンプルがない
  • 作った

というものになります。
つまり、この時点ですでに

  • 映像・音声・文字列が同時に送受信できる
    →制御コマンドの送信と、相手の映像の受信が同時にできる

ということになります。これはもう勝ったも同然ですね🍷🍾

テキスト送受信機能つきビデオチャットを改造する

まずは拙作のこちらのリポジトリのソースをもとに改良を加えてゆきます。

GitHub: ukkz/skyway-video-and-text-chat

HTML

index.html
<!-- Video area -->
<div class="pure-u-2-3" id="video-container">
  <div style="text-align:left;">
    BLE Local Connection: <span id="ble_dev_name">none</span> <button id="btn_ble_ctrl">Connect</button><br>
    Command destination: <button id="command_send_to">LOCAL</button><br>
    <br>
    Mouse - X <input type="text" id="mouse_x" size="20"> Diff: <input type="text" id="mouse_x_diff" size="20"><br>
    Mouse - Y <input type="text" id="mouse_y" size="20"> Diff: <input type="text" id="mouse_y_diff" size="20"><br>
    Moving: <input type="text" id="mouse_moving" size="20"> State: 🎄<span class="tree_state" hidden></span><br>
  </div>
  <div id="their-videos"></div>
  <video id="my-video" muted="true" autoplay playsinline></video>
</div>

もともとのHTMLのビデオ表示部分に、以下の項目を追加しました。

  • BLEデバイス接続・切断ボタン
  • コマンド送信先選択(このブラウザにつながったデバイスか、WebRTCのPeerに送信するか)
  • マウスポインタX座標と移動差分
  • マウスポインタY座標と移動差分
  • XY移動速度の積とツリーLED発火インジケータ

前編記事の最後では、マウスを動かすとツリーに直接コマンドが送られるように作りましたが
そのUI部分を移植したものになります。

JS

JavaScriptについては、WebBluetooth部分と、WebRTC(SkyWay SDK)部分にわけました。

WebUI部分

ble.js
// コマンド送信先切り替え
// 表示だけ切り替えて、あとは実際に送信の直前に参照
$('#command_send_to').on('click', () => {
  if ($('#command_send_to').text() == 'LOCAL') {
    $('#command_send_to').text('PEERS');
  } else {
    $('#command_send_to').text('LOCAL');
  }
});

コマンド送信先選択ボタンは、単純にDOMのテキストをtoggleしているだけです。
実際に送信する前に参照してどちらに送るか決めています。

script.js
// マウス位置取得
$(window).mousemove(function() {
  // 差分取得
  var diffX = posX-event.clientX;
  var diffY = posY-event.clientY;
  var moving = diffX * diffY;

  // Aチャンネル
  if (diffX >= 50)
    sendCommandWithSwitch('A0');
  else if (diffX <= -50)
    sendCommandWithSwitch('A1');

  // Bチャンネル
  if (diffY >= 50)
    sendCommandWithSwitch('B0');
  else if (diffY <= -50)
    sendCommandWithSwitch('B1');

  // Cチャンネル
  if (moving >= 150)
    sendCommandWithSwitch('C0');
  else if (moving <= -150)
    sendCommandWithSwitch('C1');
  else
    sendCommandWithSwitch('X0');

  // ブラウザ側の表示を更新
  $('#mouse_x_diff').val(diffX);
  $('#mouse_y_diff').val(diffY);
  $('#mouse_x').val(event.clientX);
  $('#mouse_y').val(event.clientY);
  $('#mouse_moving').val(moving);
  posX = event.clientX;
  posY = event.clientY;
});

マウスが動くたびに発火するイベントはWebRTCスクリプト側に記述しました。
イベントの発火レートの上限がどこまであるか、というか一定であるかすらわからないので、まさかずっとゼロのままなのでは…… と思いながら試してみたらそれなりに差分は抽出できました。詳しい人教えてくださいな。

コマンドの送信

script.js
// 送信先切り替え用
function sendCommandWithSwitch(code) {
  // ボタンの文字列を参照してLOCALかPEERSで切り替える
  if ($('#command_send_to').text() == 'LOCAL') {
    // LOCALのとき:通常コマンドを使う
    sendToLocalTree(code);
  } else {
    // PEERSのとき:コマンド用の接頭辞をつけて送信する
    room.send('COMMAND_' + code);
  }
}

こちらの関数では、先ほどの送信先切り替えボタンのtextを読んで、ローカルに接続されたBLEに送るか、それともWebRTCで送るか、を判断しています。
WebRTCで送るときはRoomオブジェクトでroom.send()をするだけでOKですが、テキストチャットの通常メッセージと区別するために、COMMAND_を先頭に付加しています。

コマンドの受信

script.js
room.on('data', message => {
  if (message.data.substring(0,8) == 'COMMAND_') {
    // COMMAND_ で始まるメッセージはコマンド扱い
    // ツリー操作に利用する
    sendToLocalTree(message.data.substring(8)); // コマンド部分のみ送る
  } else {
    // ふつうのメッセージ
    messages.prepend('<div><span class="peer">' + message.src.substr(0,8) + '</span>: ' + message.data + '</div>');
  }
});

room.on('data', コールバック)の部分で、まずmessage.dataの先頭8文字がCOMMAND_であるかどうかで制御コマンドかどうか判定します。で、到着メッセージをそのままDOMに追加していくとコマンド文字列まみれでえらいことになるので、コマンドじゃない場合にのみDOMにprependするようにします。

できた

5caf91dd-6d45-498b-ba33-b3393b847a88.png

こんな画面になりました。
使い方としては、自分のPCと、クリスマスツリーの前に別のPCをもう一つ用意し、両方からこのページをブラウザで開いて同じルームに参加します。

fig3.png

クリスマスツリー前PCは、WebBluetoothでNefryに接続し、コマンド送信先をその接続したNefry宛て(LOCAL)にしておきます。ツリーを眺めるための自分のPCは、WebBluetoothは接続しませんが、コマンド送信先をPEERにしておくことで、マウスカーソルの動きがデータとしてWebRTCでツリー前PCに送信されます。

試してみた動画

WebRealTimeChristmastree at holy night - YouTube

クリスマスの夜に、部屋を真っ暗にして撮ってみました。
みんなもNefryBTやSkyWayでレッツクリスマスナイッ🎄✨

サンプル

まずお手持ちのNefry BTに以下のスケッチを書き込んでください。
ピン配置などはお手持ちのクリスマスツリーにあわせて適宜変更してくださいねー
NefryXmasSkyWay.ino

あとはこちらのページを2台のPCで表示して、クリスマスツリーとの対話を楽しんでください。
GitHub Pages

まとめ

  • クリスマスツリーはWebでリアルタイムになれる!!!!!(?)
  • WebRTC畑の方も、SkyWayな方も、ぜひマイコンボードとかWebBluetoothにも触れてみてください。
  • IoT勢のみなさんも、SkyWayがなかなか簡単で楽しいので、ハードウェア監視などにいかがでしょうか。
  • ここまで読んでいただき非常にメリークリスマスです🍖🍺よいお年をお過ごし下さいませ🎍
6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2