javascriptでいいじゃなイカ

28
JavaScriptでいいじゃなイカ Webアプリによるフィジカルコンピューティング』 ADK BOOTCAMP #3 ASAKUSA 2013/5/26 Yuuichi Akagawa JavaScriptでいいじゃなイカ Webアプリによるフィジカルコンピューティング

Upload: yuuichi-akagawa

Post on 11-Jun-2015

998 views

Category:

Technology


1 download

DESCRIPTION

ADK BOOTCAMP#3 ASAKUSAで発表した資料です。

TRANSCRIPT

Page 1: JavaScriptでいいじゃなイカ

JavaScriptでいいじゃなイカ『Webアプリによるフィジカルコンピューティング』

ADK BOOTCAMP #3 ASAKUSA2013/5/26

Yuuichi Akagawa

JavaScriptでいいじゃなイカWebアプリによるフィジカルコンピューティング

Page 2: JavaScriptでいいじゃなイカ

自己紹介

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

• USBホストネタ大好き

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

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

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

Copyright©2013 Yuuichi Akagawa 2

Page 3: JavaScriptでいいじゃなイカ

気分転換に

Copyright©2013 Yuuichi Akagawa 3

• たまにはADK/USB以外のネタでも

• がじぇるねでマイコンはおなかいっぱいだし

• Androidアプリ書く気力も無いし

• コンパイルしたりデバイスに転送したりは面倒だし

• 気晴らしにNode.jsで遊んでみたら意外と面白かった

• HTML5 + JavaScriptだけでも結構イケる

※Titanium MobileとかPhoneGapの話ではないでゲソ

Page 4: JavaScriptでいいじゃなイカ

Copyright©2013 Yuuichi Akagawa 4

WebSocketドロンくん

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

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

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

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

Page 5: JavaScriptでいいじゃなイカ

WebSocketドロンくん

Copyright©2013 Yuuichi Akagawa 5

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

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

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

• 実用性よりも「ネタ」を重視で(レイテンシー大なの)

• WebRTCの実装が進み、JavaScriptでカメラの画像も取得できちゃう

• しかもマイコンいらない

Page 6: JavaScriptでいいじゃなイカ

DTMFモータドライバ回路図

Copyright©2013 Yuuichi Akagawa 6

Page 7: JavaScriptでいいじゃなイカ

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

Copyright©2013 Yuuichi Akagawa 7

Page 8: JavaScriptでいいじゃなイカ

Copyright©2013 Yuuichi Akagawa 8

コマンド送信

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 9: JavaScriptでいいじゃなイカ

Chromeβ for Androidに実装してみた

• 映像取得処理

getUserMedia()でカメラと接続

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

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

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

• 音声再生

音声ファイルは初回アクセス時にローカル保存

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

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

Copyright©2013 Yuuichi Akagawa 9

Page 10: JavaScriptでいいじゃなイカ

Chromeβ for Androidに実装してみた

• こんな感じ

Copyright©2013 Yuuichi Akagawa 10

スマホのカメラの映像がここに表示されている

Page 11: JavaScriptでいいじゃなイカ

サーバサイドコード例

Copyright©2013 Yuuichi Akagawa 11

var express = require('express'), app = express(), path = require('path'), http = require('http'), server = http.createServer(app), io = require('socket.io').listen(server);

// Configurationapp.configure(function(){

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

});

app.configure('production', function(){app.use(express.errorHandler());io.set('log level', 1);

});// Routesapp.get('/controlv', function(req, res) {

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

res.render('tankv', {title:'HTML5 Delonkun'});});

// Socket.IOvar sockets = {};// broadcast functionfunction broadcast(method,message) {

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

}

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

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

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

});socket.on('control.video', function(data) {

broadcast('control.video', data);});socket.on('disconnect', function() {

delete sockets[socket.id];});

});

server.listen(8009);

app.js

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

ここがサーバ実装部分

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

Page 12: JavaScriptでいいじゃなイカ

操作画面ページコード例

Copyright©2013 Yuuichi Akagawa 12

socket.on('control.video', function(data) {var img = document.getElementById('camera_image1');img.src = data.video;

});

divimg#camera_image1(src='')

画像表示周り抜粋

Page 13: JavaScriptでいいじゃなイカ

制御用ページコード例

Copyright©2013 Yuuichi Akagawa 13

divvideo#camera(width='160', height='120', autoplay)canvas#camera_canvas(style='display:none;', width='160', height='120')

映像配信部分抜粋

$(function(){navigator.getMedia = ( navigator.getUserMedia ||

navigator.webkitGetUserMedia ||navigator.mozGetUserMedia ||navigator.msGetUserMedia );

var video = document.getElementById('camera');var canvas = document.getElementById('camera_canvas');var ctx = canvas.getContext('2d');var image1 = document.getElementById('camera_image1');navigator.getMedia ({ video:true, audio:false }, function(stream) {

video.src = window.URL.createObjectURL(stream);}, function(err){console.log(err);});

setInterval(function(){if(navigator.getMedia){var canvas_image = ctx.drawImage(video,0,0,160,120);canvas_image = ctx.getImageData(0, 0, 160, 120);ctx.putImageData(canvas_image, 0, 0);var dataURL = canvas.toDataURL("image/octet-stream");socket.emit('control.video', {video:dataURL});

}, 500);

Page 14: JavaScriptでいいじゃなイカ

マイコンと一緒

Copyright©2013 Yuuichi Akagawa 14

Page 15: JavaScriptでいいじゃなイカ

マイコンと一緒

Copyright©2013 Yuuichi Akagawa 15

• DTMFだけでは限界が…

• やっぱりマイコンも使おう

• 接続方法はお手軽なUARTで決まり!(無線化はXBeeで)

• マイコンでTCP/IPとか扱うの面倒でしょ。そういうのは汎用OSにお願いしよう。

Page 16: JavaScriptでいいじゃなイカ

Raspberry PiでNode.js

Copyright©2013 Yuuichi Akagawa 16

• Linuxだから当たり前の様に動く

• だけど、非力なのでビルドに時間かかる

• インストールは以下の手順で$ git clone git://github.com/creationix/nvm.git ~/.nvm

$ . ~/.nvm/nvm.sh

$ nvm install v0.8.23

$ echo '. ~/.nvm/nvm.sh' >> ~/.bashrc

$ echo 'nvm use v0.8.23' >> ~/.bashrc

Page 17: JavaScriptでいいじゃなイカ

node serialport

Copyright©2013 Yuuichi Akagawa 17

• Node.jsでシリアルポートが使えるhttps://github.com/voodootikigod/node-serialport

• インストールはnpmで

• これだとちょっとプリミティブすぎるので…

$ npm install serialport

Page 18: JavaScriptでいいじゃなイカ

node firmata

Copyright©2013 Yuuichi Akagawa 18

• Firmataが使えるよhttps://github.com/jgautier/firmata

• こちらもnpmでインストール可能$ npm install firmata

var ledPin = 5;var firmata = require('firmata');

var board = new firmata.Board('/dev/ttyUSB0', function(err) {if (err) {

console.log(err);return;

}var ledOn = true;board.pinMode(ledPin, board.MODES.OUTPUT);setInterval(function(){

if (ledOn) {board.digitalWrite(ledPin, board.HIGH);

}else {

board.digitalWrite(ledPin, board.LOW);}ledOn = !ledOn;

},500);});

スタンドアローンなLチカ

Page 19: JavaScriptでいいじゃなイカ

RPi + Arduino

Copyright©2013 Yuuichi Akagawa 19

• Raspberry PiにArduino繋げてFirmataで制御(スクリプトは前ページのもの)

Page 20: JavaScriptでいいじゃなイカ

Cloud9 IDE

Copyright©2013 Yuuichi Akagawa 20

• Node.jsに対応したJavaScript統合開発環境https://c9.io/https://github.com/ajaxorg/cloud9

• BeagleBoneは標準装備

Page 21: JavaScriptでいいじゃなイカ

PCでもNode.js

Copyright©2013 Yuuichi Akagawa 21

• わざわざワンボードPC買わなくても、手元のPCでNode.jsを動作させれば良い

• 公式サイトでWindowsやMac OS X用のバイナリを配布してる

• でもWindowsは(ry

Page 22: JavaScriptでいいじゃなイカ

Webブラウザ✕マイコン

Copyright©2013 Yuuichi Akagawa 22

Page 23: JavaScriptでいいじゃなイカ

chrome.serial

Copyright©2013 Yuuichi Akagawa 23

• Google Chrome Appでシリアルポートが使える

Page 24: JavaScriptでいいじゃなイカ

chrome.serial

Copyright©2013 Yuuichi Akagawa 24

• manifest.jsonでパーミッションを与える

• こんな感じで動く

"permissions": ["serial"],

Page 25: JavaScriptでいいじゃなイカ

chrome.usb

Copyright©2013 Yuuichi Akagawa 25

• USBホストも使える(ADKは作らないよ)

Page 26: JavaScriptでいいじゃなイカ

chrome.bluetooth

Copyright©2013 Yuuichi Akagawa 26

• Bluetoothも使えるようになるらしい

Page 27: JavaScriptでいいじゃなイカ

と、いうわけでJavaScriptでやってみなイカ?

Copyright©2013 Yuuichi Akagawa 27

Page 28: JavaScriptでいいじゃなイカ

おしまい

Copyright©2013 Yuuichi Akagawa 28