JavaScriptでいいじゃなイカ
『Webアプリによるフィジカルコンピューティング』
ADK BOOTCAMP #3 ASAKUSA
2013/5/26
Yuuichi Akagawa
JavaScriptでいいじゃなイカ
Webアプリによるフィジカルコンピューティング
自己紹介
• Yuuichi Akagawa (あかがわ ゆういち)
• USBホストネタ大好き
• 本業は某SI企業でインフラ担当
• 電子工作やプログラミングは趣味での活動
• 仕組みを知ることが好きなので、最終的な作品に
至ることがほとんど無い
Copyright©2013 Yuuichi Akagawa 2
気分転換に
Copyright©2013 Yuuichi Akagawa 3
• たまにはADK/USB以外のネタでも
• がじぇるねでマイコンはおなかいっぱいだし
• Androidアプリ書く気力も無いし
• コンパイルしたりデバイスに転送したりは面倒だし
• 気晴らしにNode.jsで遊んでみたら意外と面白かった
• HTML5 + JavaScriptだけでも結構イケる
※Titanium MobileとかPhoneGapの話ではないでゲソ
Copyright©2013 Yuuichi Akagawa 4
WebSocketドロンくん
ドロンくんとは
今岡通博氏考案の
Android端末による
音声認識ロボット。
http://www.ospn.jp/press/20110516no10-useit-oss.html
DTMFによる制御や、
ブレッドボードで回路を
実装するというお手軽構成。
音声認識の代わりに
WebSocket経由でコントロール
できるようにしてみた。
WebSocketドロンくん
Copyright©2013 Yuuichi Akagawa 5
• Node.js + Socket.IOを利用した遠隔制御の実験
• Webアプリでフィジカルコンピューティングという提案
• みんなBluetoothでやってるからちょっと斜めで
• 実用性よりも「ネタ」を重視で(レイテンシー大なの)
• WebRTCの実装が進み、JavaScriptでカメラの画像も
取得できちゃう
• しかもマイコンいらない
DTMFモータドライバ回路図
Copyright©2013 Yuuichi Akagawa 6
ブレッドボードにちょうど載る規模
Copyright©2013 Yuuichi Akagawa 7
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に引っ越し
コマンドに
対応した
音声ファイル
を再生
Chromeβ for Androidに実装してみた
• 映像取得処理
getUserMedia()でカメラと接続
カメラからの映像をCanvasに描画
CanvasのデータをtoDataURL()でエンコード
上記で取得したデータをそのままWebSocketで送出
• 音声再生
音声ファイルは初回アクセス時にローカル保存
コマンドに応じて、Audioのsrcにパスを設定
autoplay非対応なので、最初だけ再生ボタンを押す
必要あり
Copyright©2013 Yuuichi Akagawa 9
Chromeβ for Androidに実装してみた
• こんな感じ
Copyright©2013 Yuuichi Akagawa 10
スマホのカメラの映像が
ここに表示されている
サーバサイドコード例
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);
// Configuration
app.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);
});
// Routes
app.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.IO
var sockets = {};
// broadcast function
function 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サーバとして動作する。
ここがサーバ
実装部分
・コネクション受付
・データ受信
・データ配信
全部やってる。
操作画面ページコード例
Copyright©2013 Yuuichi Akagawa 12
socket.on('control.video', function(data) {
var img = document.getElementById('camera_image1');
img.src = data.video;
});
div
img#camera_image1(src='')
画像表示周り抜粋
制御用ページコード例
Copyright©2013 Yuuichi Akagawa 13
div
video#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);
マイコンと一緒
Copyright©2013 Yuuichi Akagawa 14
マイコンと一緒
Copyright©2013 Yuuichi Akagawa 15
• DTMFだけでは限界が…
• やっぱりマイコンも使おう
• 接続方法はお手軽なUARTで決まり!
(無線化はXBeeで)
• マイコンでTCP/IPとか扱うの面倒でしょ。そういうのは
汎用OSにお願いしよう。
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
node serialport
Copyright©2013 Yuuichi Akagawa 17
• Node.jsでシリアルポートが使える
https://github.com/voodootikigod/node-serialport
• インストールはnpmで
• これだとちょっとプリミティブすぎるので…
$ npm install serialport
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チカ
RPi + Arduino
Copyright©2013 Yuuichi Akagawa 19
• Raspberry PiにArduino繋げてFirmataで制御
(スクリプトは前ページのもの)
Cloud9 IDE
Copyright©2013 Yuuichi Akagawa 20
• Node.jsに対応したJavaScript統合開発環境
https://c9.io/
https://github.com/ajaxorg/cloud9
• BeagleBoneは標準装備
PCでもNode.js
Copyright©2013 Yuuichi Akagawa 21
• わざわざワンボードPC買わなくても、手元のPCで
Node.jsを動作させれば良い
• 公式サイトでWindowsやMac OS X用のバイナリを
配布してる
• でもWindowsは(ry
Webブラウザ✕マイコン
Copyright©2013 Yuuichi Akagawa 22
chrome.serial
Copyright©2013 Yuuichi Akagawa 23
• Google Chrome Appでシリアルポートが使える
chrome.serial
Copyright©2013 Yuuichi Akagawa 24
• manifest.jsonでパーミッションを与える
• こんな感じで動く
"permissions": ["serial"],
chrome.usb
Copyright©2013 Yuuichi Akagawa 25
• USBホストも使える(ADKは作らないよ)
chrome.bluetooth
Copyright©2013 Yuuichi Akagawa 26
• Bluetoothも使えるようになるらしい
と、いうわけで
JavaScriptでやってみなイカ?
Copyright©2013 Yuuichi Akagawa 27
おしまい
Copyright©2013 Yuuichi Akagawa 28

More Related Content

PDF
サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
PDF
Web socketドロンくん その後-
PDF
Usb接続するアプリを開発した時に試行錯誤した事
PDF
A-Frameで始めるOculus Quest対応WebVR
PDF
HTMLを書くだけで誰でも簡単!A-FrameではじめるWeb AR/VR
PDF
IBDesignable / IBInspectable で UIプロトタイピンガブル
PDF
初めてのvue.js(2.x系)
PDF
Creators'night#13 tech#2今井
サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
Web socketドロンくん その後-
Usb接続するアプリを開発した時に試行錯誤した事
A-Frameで始めるOculus Quest対応WebVR
HTMLを書くだけで誰でも簡単!A-FrameではじめるWeb AR/VR
IBDesignable / IBInspectable で UIプロトタイピンガブル
初めてのvue.js(2.x系)
Creators'night#13 tech#2今井

What's hot (6)

PDF
jQuery Mobile 概要
KEY
東の方からきました@鹿駆動勉強会
PDF
スマホにおけるWebGL入門
PDF
オープンソースで始めるAR/VR開発
PDF
Native x Webでいいとこどり開発 ~ピグトーク~
PDF
A-Framで始めるWebAR (Blenderハンズオンの続きver.)
jQuery Mobile 概要
東の方からきました@鹿駆動勉強会
スマホにおけるWebGL入門
オープンソースで始めるAR/VR開発
Native x Webでいいとこどり開発 ~ピグトーク~
A-Framで始めるWebAR (Blenderハンズオンの続きver.)
Ad

Similar to JavaScriptでいいじゃなイカ (20)

PDF
わんくま同盟名古屋勉強会18回目 ASP.NET MVC3を利用したHTML5な画面開発~クラウドも有るよ!~
PDF
HTML5のCanvas入門 - Img画像を編集してみよう -
PPTX
Unityのポストエフェクトで遊ぶ!
PDF
初心者向けJavaScript/HTML5ゲームプログラミング
PPT
Core Animation 使って見た
PDF
Windows 11とNPUで実現するWindowsのAI
PPTX
JavaScriptで『漫画カメラ』的画像加工
PPTX
WebARで作るDukeが飛び出すカード
PDF
多分モダンなWebアプリ開発
PDF
How do you like knockout?
PPTX
自社クラウドサービスをAnsibleで作った話
PDF
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた
PDF
レスポンシブWebデザイン【発展編】
PDF
ソーシャルアプリ勉強会(第一回資料)配布用
PDF
HTML5の前のJavaScript入門
PDF
FlutterをRenderObjectまで理解する
PDF
FM音源をいじれるWebサービスを作った
PDF
福井スマートフォンハッカソン Titanium Mobileの紹介
PDF
3DCG(3Dコンピュータグラフィック)をWebGLで始めよう
PPTX
20241219_AWS_reInvet_reCap_dataautomation_kondo
わんくま同盟名古屋勉強会18回目 ASP.NET MVC3を利用したHTML5な画面開発~クラウドも有るよ!~
HTML5のCanvas入門 - Img画像を編集してみよう -
Unityのポストエフェクトで遊ぶ!
初心者向けJavaScript/HTML5ゲームプログラミング
Core Animation 使って見た
Windows 11とNPUで実現するWindowsのAI
JavaScriptで『漫画カメラ』的画像加工
WebARで作るDukeが飛び出すカード
多分モダンなWebアプリ開発
How do you like knockout?
自社クラウドサービスをAnsibleで作った話
【de:code 2020】 「あつまれ フロントエンドエンジニア」 Azure Static Web Apps がやってきた
レスポンシブWebデザイン【発展編】
ソーシャルアプリ勉強会(第一回資料)配布用
HTML5の前のJavaScript入門
FlutterをRenderObjectまで理解する
FM音源をいじれるWebサービスを作った
福井スマートフォンハッカソン Titanium Mobileの紹介
3DCG(3Dコンピュータグラフィック)をWebGLで始めよう
20241219_AWS_reInvet_reCap_dataautomation_kondo
Ad

JavaScriptでいいじゃなイカ

  • 1. JavaScriptでいいじゃなイカ 『Webアプリによるフィジカルコンピューティング』 ADK BOOTCAMP #3 ASAKUSA 2013/5/26 Yuuichi Akagawa JavaScriptでいいじゃなイカ Webアプリによるフィジカルコンピューティング
  • 2. 自己紹介 • Yuuichi Akagawa (あかがわ ゆういち) • USBホストネタ大好き • 本業は某SI企業でインフラ担当 • 電子工作やプログラミングは趣味での活動 • 仕組みを知ることが好きなので、最終的な作品に 至ることがほとんど無い Copyright©2013 Yuuichi Akagawa 2
  • 3. 気分転換に Copyright©2013 Yuuichi Akagawa 3 • たまにはADK/USB以外のネタでも • がじぇるねでマイコンはおなかいっぱいだし • Androidアプリ書く気力も無いし • コンパイルしたりデバイスに転送したりは面倒だし • 気晴らしにNode.jsで遊んでみたら意外と面白かった • HTML5 + JavaScriptだけでも結構イケる ※Titanium MobileとかPhoneGapの話ではないでゲソ
  • 4. Copyright©2013 Yuuichi Akagawa 4 WebSocketドロンくん ドロンくんとは 今岡通博氏考案の Android端末による 音声認識ロボット。 http://www.ospn.jp/press/20110516no10-useit-oss.html DTMFによる制御や、 ブレッドボードで回路を 実装するというお手軽構成。 音声認識の代わりに WebSocket経由でコントロール できるようにしてみた。
  • 5. WebSocketドロンくん Copyright©2013 Yuuichi Akagawa 5 • Node.js + Socket.IOを利用した遠隔制御の実験 • Webアプリでフィジカルコンピューティングという提案 • みんなBluetoothでやってるからちょっと斜めで • 実用性よりも「ネタ」を重視で(レイテンシー大なの) • WebRTCの実装が進み、JavaScriptでカメラの画像も 取得できちゃう • しかもマイコンいらない
  • 8. 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に引っ越し コマンドに 対応した 音声ファイル を再生
  • 9. Chromeβ for Androidに実装してみた • 映像取得処理 getUserMedia()でカメラと接続 カメラからの映像をCanvasに描画 CanvasのデータをtoDataURL()でエンコード 上記で取得したデータをそのままWebSocketで送出 • 音声再生 音声ファイルは初回アクセス時にローカル保存 コマンドに応じて、Audioのsrcにパスを設定 autoplay非対応なので、最初だけ再生ボタンを押す 必要あり Copyright©2013 Yuuichi Akagawa 9
  • 10. Chromeβ for Androidに実装してみた • こんな感じ Copyright©2013 Yuuichi Akagawa 10 スマホのカメラの映像が ここに表示されている
  • 11. サーバサイドコード例 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); // Configuration app.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); }); // Routes app.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.IO var sockets = {}; // broadcast function function 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サーバとして動作する。 ここがサーバ 実装部分 ・コネクション受付 ・データ受信 ・データ配信 全部やってる。
  • 12. 操作画面ページコード例 Copyright©2013 Yuuichi Akagawa 12 socket.on('control.video', function(data) { var img = document.getElementById('camera_image1'); img.src = data.video; }); div img#camera_image1(src='') 画像表示周り抜粋
  • 13. 制御用ページコード例 Copyright©2013 Yuuichi Akagawa 13 div video#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);
  • 15. マイコンと一緒 Copyright©2013 Yuuichi Akagawa 15 • DTMFだけでは限界が… • やっぱりマイコンも使おう • 接続方法はお手軽なUARTで決まり! (無線化はXBeeで) • マイコンでTCP/IPとか扱うの面倒でしょ。そういうのは 汎用OSにお願いしよう。
  • 16. 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
  • 17. node serialport Copyright©2013 Yuuichi Akagawa 17 • Node.jsでシリアルポートが使える https://github.com/voodootikigod/node-serialport • インストールはnpmで • これだとちょっとプリミティブすぎるので… $ npm install serialport
  • 18. 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チカ
  • 19. RPi + Arduino Copyright©2013 Yuuichi Akagawa 19 • Raspberry PiにArduino繋げてFirmataで制御 (スクリプトは前ページのもの)
  • 20. Cloud9 IDE Copyright©2013 Yuuichi Akagawa 20 • Node.jsに対応したJavaScript統合開発環境 https://c9.io/ https://github.com/ajaxorg/cloud9 • BeagleBoneは標準装備
  • 21. PCでもNode.js Copyright©2013 Yuuichi Akagawa 21 • わざわざワンボードPC買わなくても、手元のPCで Node.jsを動作させれば良い • 公式サイトでWindowsやMac OS X用のバイナリを 配布してる • でもWindowsは(ry
  • 23. chrome.serial Copyright©2013 Yuuichi Akagawa 23 • Google Chrome Appでシリアルポートが使える
  • 24. chrome.serial Copyright©2013 Yuuichi Akagawa 24 • manifest.jsonでパーミッションを与える • こんな感じで動く "permissions": ["serial"],
  • 25. chrome.usb Copyright©2013 Yuuichi Akagawa 25 • USBホストも使える(ADKは作らないよ)
  • 26. chrome.bluetooth Copyright©2013 Yuuichi Akagawa 26 • Bluetoothも使えるようになるらしい