web socketドロンくん その後-

27
WebSocketドロンくん ~その後~ Webアプリによるフィジカルコンピューティング』 SAKURAボードユーザ会 あなたの心もSAKURA色 葉桜の木の下de交流会 2013/4/4 Yuuichi Akagawa

Upload: yuuichi-akagawa

Post on 05-Dec-2014

1.007 views

Category:

Documents


3 download

DESCRIPTION

nodejsを利用し、マイコンを使わずにモータで動くおもちゃを遠隔制御してみる実験。

TRANSCRIPT

Page 1: Web socketドロンくん その後-

WebSocketドロンくん~その後~

『Webアプリによるフィジカルコンピューティング』

SAKURAボードユーザ会 あなたの心もSAKURA色 葉桜の木の下de交流会

2013/4/4

Yuuichi Akagawa

Page 2: Web socketドロンくん その後-

自己紹介

• Yuuichi Akagawa (あかがわ ゆういち)

• USBホストネタ大好き

• 本業は某SI企業でインフラ担当

• 電子工作やプログラミングは趣味での活動

• 仕組みを知ることが好きなので、最終的な作品に至ることがほとんど無い

Copyright©2013 Yuuichi Akagawa 2

Page 3: Web socketドロンくん その後-

OSC2012東京Fallで発表しました

Copyright©2013 Yuuichi Akagawa 3

• WebSocket(Node.js + Socket.IO)を利用した遠隔制御の実験

• Webアプリでフィジカルコンピューティングという提案

• みんなBluetoothでやってるからちょっと斜めで

• 当初はAndroid側をアプリとして実装したものの、後にJavaScriptのみでイケるということに気付く

• 実用性よりも「ネタ」を重視で

• 昨年の東京Node学園祭2012に出せればウケたのに

Page 4: Web socketドロンくん その後-

ちょっとおさらい

Copyright©2013 Yuuichi Akagawa 4

Page 5: Web socketドロンくん その後-

WebSocketとは

• リアルタイムWeb

– 現在多く利用されている、XMLHttpRequest(XHR)によるAjaxポーリングやCometを代表とするロングポーリングではTCPハンドシェイクが都度発生したりHTTPコネクションを長時間占有するなど、Webサーバの負荷が高いという欠点がある。

– これを解決するためにHTML5の一部としてブラウザから直接TCP接続を実現する独自プロトコルの策定が始まった。(現在はHTML5とは独立。RFC6455)

– 2011年末にようやく仕様確定し、メジャーなブラウザでは問題無く利用できる状況にある。

Copyright©2013 Yuuichi Akagawa 5

Page 6: Web socketドロンくん その後-

主要ブラウザのWebSocketサポート状況

プラットフォーム ブラウザ バージョン

Desktop OS Internet Explorer 10以上

Firefox 6以上

Chrome 14以上

Safari 6以上

Opera 12.1以上

Android 標準ブラウザ 未サポート

Chrome 18以上

Firefox 7以上

Opera mobile 12.1以上

iOS Safari 6以上

Copyright©2013 Yuuichi Akagawa 6

ほぼどれでも使える。Android版ChromeはOSが4.0以上で無いと動作しないが、Firefoxであれば2.2以上で使えるので、なんとかなるかと。

Page 7: Web socketドロンくん その後-

Node.jsとは

• サーバサイドJavaScript実行環境

http://nodejs.org

Google V8 JavaScriptエンジン採用

シングルスレッド(JavaScriptだもんね)

イベント駆動(非同期)モデル

nvmというバージョンマネージャやnpmというパッケージマネージャが揃っている

サーバサイドもJavaScriptでコードが書けるのは素敵だと思う

Copyright©2013 Yuuichi Akagawa 7

Page 8: Web socketドロンくん その後-

Socket.IOとは

• クロスプラットフォームリアルタイムWebライブラリ

http://socket.io

Node.js用のライブラリ

サポートプロトコルWebSocketが使えないブラウザでもXHR等に自動フォールバック

• WebSocket

• XHR

• Flash Socket

• JSONP Polling

Copyright©2013 Yuuichi Akagawa 8

Page 9: Web socketドロンくん その後-

Copyright©2013 Yuuichi Akagawa 9

WebSocketドロンくん

ドロンくんとは今岡通博氏考案のAndroid端末による音声認識ロボット。

http://www.ospn.jp/press/20110516no10-useit-oss.html

DTMFによる制御や、ブレッドボードで回路を実装するというお手軽構成。

今回は音声認識の代わりにWebSocket経由でコントロールできるようにしました。

Page 10: Web socketドロンくん その後-

Copyright©2013 Yuuichi Akagawa 10

DTMF (Dual-Tone Multi-Frequency)

• 説明するまでもないとは思いますが、電話の「ピ・ポ・パ」ってやつです

• 正式には「ITU-T勧告Q.24」

• これを4bitのI/Oとして取り出すDTMFデコーダを活用する(2個 ¥300)

高群(Hz)

1209 1336 1477 1633

低群(Hz) 697 1 2 3 A

770 4 5 6 B

852 7 8 9 C

941 * 0 # D

Page 11: Web socketドロンくん その後-

DTMFモータドライバ回路図

Copyright©2013 Yuuichi Akagawa 11

Page 12: Web socketドロンくん その後-

ブレッドボードにちょうど載る規模

Copyright©2013 Yuuichi Akagawa 12

Page 13: Web socketドロンくん その後-

Copyright©2013 Yuuichi Akagawa 13

コマンド送信

HTML5 ready Web Browser(スマホのブラウザでもOK)

Socket.IO module

EC2

コマンド配信(ブロードキャストも可能)

プロトコルはWebSocket

orXHR(Ajax)

DTMF

Node.js + Socket.IOを利用したWebSocketによる遠隔制御

DTMFデコーダ+

モータードライバ

DTMF_0.ogg...

DTMF_#.ogg

Firefox var audio = new Audio(“/sounds/”+file);audio.play()

DTMF音声ファイルダウンロード

Page 14: Web socketドロンくん その後-

サーバサイドコード例

Copyright©2013 Yuuichi Akagawa 14

var express = require('express‘) , routes = require('./routes');

var app = module.exports = express.createServer();

// Configurationapp.configure(function(){

app.set('views', __dirname + '/views');app.set('view engine', 'jade');app.use(express.bodyParser());app.use(express.methodOverride());app.use(app.router);app.use(express.static(__dirname + '/public'));

});

app.configure('development', function(){app.use(express.errorHandler({ dumpExceptions: true, showStack:

true }));});

app.configure('production', function(){app.use(express.errorHandler());

});

// Routesapp.get('/control', function(req, res) {

res.render('control', {title:'Socket.IO Control'});});app.get('/recv', function(req, res) {

res.render('recv', {title:'Socket.IO Receiver'});});

// Socket.IOvar io = require('socket.io').listen(app);var chats = [];var sockets = {};

// broadcast functionfunction broadcast(method,message) {

for (var n in sockets) {sockets[n].emit(method,message);}chats.pop;

}

io.of('/in').on('connection', function(socket) {

sockets[socket.id] = socket;socket.on('control.add', function(data) {

data.time = Date.now();chats.push(data);broadcast('control.add', data);

});socket.on('disconnect', function() {

delete sockets[socket.id];});

});

app.listen(8001);

app.js

これだけでWebサーバとして動作する。

ここがサーバ実装部分

・コネクション受付・データ受信・データ配信全部やってる。

fork()とかpthread_create()とかなにそれって感じ。

Page 15: Web socketドロンくん その後-

操作画面ページコード例

Copyright©2013 Yuuichi Akagawa 15

script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js')script(src='/socket.io/socket.io.js')script(type='text/javascript')

// add chat logfunction addlog(data) {var date = new Date(data.time);console.log(date);$('li#log').replaceWith( '<li id="log">' +data.cmd+ ' (' + date.getHours() + ':' + date.getMinutes()+ ':' + date.getSeconds() + ')</li>');

}var socket = io.connect('http://example.com:8001/in');

socket.on('control.add', function(data) {addlog(data);

});function send(data) {socket.emit('control.add', {cmd:data} );return false;

}

h3 WebSocketドロンくんdiv

tabletrtd

input(type='button',class='btn',value='FwdL', onClick='send(1)')td

input(type='button',class='btn',value='Forward', onClick='send(2)')td

input(type='button',class='btn',value='FwdR', onClick='send(3)')trtd

input(type='button',class='btn',value='Turn L', onClick='send(4)')td

input(type='button',class='btn',value='Stop', onClick='send(5)')td

input(type='button',class='btn',value='Turn R', onClick='send(6)')trtd

input(type='button',class='btn',value='BkL', onClick='send(7)')td

input(type='button',class='btn',value='Back', onClick='send(8)')td

input(type='button',class='btn',value='BkR', onClick='send(9)')div

ulli#log

views/control.jade

Express(Webフレームワーク)+ Jade(テンプレートエンジン)を利用。

※http://example.com:8001/controlにアクセスするとこれを返す。

Page 16: Web socketドロンくん その後-

制御用ページコード例

Copyright©2013 Yuuichi Akagawa 16

script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js')script(src='/socket.io/socket.io.js')script(type='text/javascript')//DTMF mapvar DTMFtable = [];DTMFtable['1'] = '4';DTMFtable['2'] = '5';DTMFtable['3'] = '1';DTMFtable['4'] = '6';DTMFtable['5'] = 'D';DTMFtable['6'] = '9';DTMFtable['7'] = '8';DTMFtable['8'] = '0';DTMFtable['9'] = '2';//DTMFaudiovar DTMFaudio = null;var SOUND_PATH = "/sounds/";// Get supported sound formatvar AUDIO_EXT = (function(){

var audio = new Audio();var ext = "";if (audio.canPlayType("audio/ogg") == 'maybe') { ext="ogg"; }return ext;

})();//Sound playvar play = function(tone) {

// Get Filenamevar name = 'DTMF_' + DTMFtable[tone];var file_path = SOUND_PATH + name + '.' + AUDIO_EXT;if(DTMFaudio != null){

DTMFaudio.pause();DTMFaudio.currentTime = 0;DTMFaudio = null;

}DTMFaudio = new Audio(file_path);DTMFaudio.play();

};

//Sound playvar play = function(tone) {

// Get Filenamevar name = 'DTMF_' + DTMFtable[tone];var file_path = SOUND_PATH + name + '.' + AUDIO_EXT;if(DTMFaudio != null){

DTMFaudio.pause();DTMFaudio.currentTime = 0;DTMFaudio = null;

}DTMFaudio = new Audio(file_path);DTMFaudio.play();

};

var socket = io.connect('http://176.34.45.101:8009/in');

socket.on('control.add', function(data) {play(data.cmd);

});function send(data) {

socket.emit('control.add', {cmd:data} );return false;

}

h1 HTML5 Delonkun

views/tank.jade ※http://example.com:8001/tankにアクセスするとこれを返す。

Page 17: Web socketドロンくん その後-

今後の予定

• Android端末側

Android端末のカメラの画像をWebSocketで送信して操作画面に表示したい。

音声ファイル再生ではなく、Web Audio APIで自力発音したい。

• サーバ側スクリプト

操作側と操作される側のペアリングを実現したい

Copyright©2013 Yuuichi Akagawa 17

Page 18: Web socketドロンくん その後-

で、それから半年が過ぎた。

Copyright©2013 Yuuichi Akagawa 18

Page 19: Web socketドロンくん その後-

要素技術の動向

• WebRTC (getUserMedia)

Desktop OSでのサポート状況はまずまず

AndroidではChromeβとOpera mobileで利用可能

• Web Audio API

Desktop OSのサポート状況はまずまず

Androidでは未だ使えない

iOSのSafariではサポート→DTMFダイヤラの実装例あり!

Copyright©2013 Yuuichi Akagawa 19

Page 20: Web socketドロンくん その後-

主要ブラウザのサポート状況

プラットフォーム ブラウザ WebScoketAudioのAutoPlay

WebRTCgetUserMedia

Web Audio API

Desktop OS Internet Explorer ○ ○ × ×

Firefox ○ ○ ○ ×

Chrome ○ ○ ○ ○

Safari ○ ○ × ○

Opera ○ ○ ○ ×

Android 標準ブラウザ × × × ×

Chrome ○ × △ ×

Firefox ○ ○ × ×

Opera mobile ○ × ○ ×

iOS Safari ○ × × ○

Copyright©2013 Yuuichi Akagawa 20

2013/4/3現在

Page 21: Web socketドロンくん その後-

主要ブラウザのサポート状況

プラットフォーム ブラウザ WebScoketAudioのAutoPlay

WebRTCgetUserMedia

Web Audio API

Desktop OS Internet Explorer ○ ○ × ×

Firefox ○ ○ ○ ×

Chrome ○ ○ ○ ○

Safari ○ ○ × ○

Opera ○ ○ ○ ×

Android 標準ブラウザ × × × ×

Chrome ○ × △ ×

Firefox ○ ○ × ×

Opera mobile ○ × ○ ×

iOS Safari ○ × × ○

Copyright©2013 Yuuichi Akagawa 21

どちらかが両方サポートされてないと困る。

2013/4/3現在

○○

○×

××

××

×

Page 22: Web socketドロンくん その後-

モバイルでの対応はもう一息

• Desktop OSでは動作可能なレベル

• ○が2つ付いてるブラウザが無いんだな

• Androidはブラウザ毎にWebRTCかAudio APIのどちらかしかサポートされていない

• しかも、Audioのautoplayに対応しているのはFirefoxだけ→その他ブラウザではユーザの介入が必要

Copyright©2013 Yuuichi Akagawa 22

Page 23: Web socketドロンくん その後-

Chromeβ for Androidに実装してみる

• 映像取得処理

getUserMedia()でカメラと接続

カメラからの映像をCanvasに描画

CanvasのデータをtoDataURL()でエンコード

上記で取得したデータをそのままWebSocketで送出

• 音声再生

コマンドに応じて、Audioのsrcにパスを設定

autoplay非対応なので、最初だけ再生ボタンを押す必要あり

Copyright©2013 Yuuichi Akagawa 23

Page 24: Web socketドロンくん その後-

Copyright©2013 Yuuichi Akagawa 24

コマンド送信

HTML5 ready Web Browser(スマホのブラウザでもOK)

Socket.IO module

さくらのVPS

コマンド配信

DTMF

WebSocketを利用したJavaScriptによる遠隔制御

DTMFデコーダ+

モータードライバ

DTMF_0.ogg...

DTMF_#.ogg

Chrome for Android

DTMF音声ファイルはキャッシュマニフェストを利用してローカルに保存

キャプチャ画像送信

キャプチャ画像配信

WebRTCを利用して内蔵カメラからの映像を取得する

急激な円安進行により、AWSが割高になったのでさくらのVPSに引っ越し

Page 25: Web socketドロンくん その後-

まとめ

• JavaScriptだけでなんとか画像配信までできた

• なぜか画像がモノクロだけど

• ちょっと荷が重いので高レイテンシーだぞ

• あと半年くらい待てば、Androidでもフル機能がサポートがされるのではないかと期待

• WebRTCがきちんと実装されれば、WebSocetではなくStreaming APIで滑らかな映像配信ができるはず

• 次回はWeb Audio APIでDTMFもね❤Copyright©2013 Yuuichi Akagawa 25

Page 26: Web socketドロンくん その後-

マイコンもコンパイラもいらない

Webアプリでフィジカルコンピューティング

。*:゜☆ヽ(*’∀’*)/☆゜:。*。

Copyright©2013 Yuuichi Akagawa 26

Page 27: Web socketドロンくん その後-

おしまい

Copyright©2013 Yuuichi Akagawa 27