IO-DATAのNFCタグリーダーをHTTP、WebSocket、Socketから使えるようにした
NFCタグリーダーをサーバーにした。
shokai/nfctag-server – GitHub
特殊なデバイスはみんなサーバーにしてHTMLとJSから使えるようにすればいい。
1つのハードウェアにいくつもアプリをぶら下げれるし、アプリはハードウェアと別のマシンで動かせるし、JavaScript書けるし、とにかく楽だ。
下は以前作ったWebSocket clientでnfc-tag-serverに接続してtagを読んでいるところ。
タグがある時はhex dumpされた文字列が、無い時はfalseが送信されてくる。同じ値がHTTPや普通のTCP Socketでも取れるようになっている。

■NFCタグリーダー
これ使ってる。USB接続で、けっこうどこででも売ってる。これじゃなくてもlibnfcで動くデバイスならいけるはず。
ただしlibnfcでFeliCaが読めなかった。MIFAREタグなら読めた。
売り上げランキング: 12161
■インストール
git clone git://github.com/shokai/nfctag-server.git
cd nfctag-server
Macの場合
brew install libnfcこれで必要なライブラリがインストールされる。
gem install nfc eventmachine eventmachine_httpserver em-websocket ArgsParser
Mac以外はlibnfcを自分でインストールすればたぶんok。Ubuntuは意外にもaptにlibnfc無かった。
■起動
./nfc-tag-server --http_port 8080 --websocket_port 8081 --socket_port 8082
これでHTTPとWebSocketと普通のTCP Socketのサーバーが同時に起動する。
それぞれ
HTTP-GET
curl 'http://localhost:8080'
WebSocket
## JavaScriptwebsocket clientを使えばすぐ試せる
var ws = new WebSocket("ws://localhost:8081");
ws.onmessage = function(e){
Console.log(e.data);
};
Socket
telnet localhost 8082
のような感じに接続して、tagのIDが読める。
RubyでBuffalo/玄人志向の赤外線学習リモコンを操作する
11月22-23日にSFC ORFというSFCの研究室の発表会があって、そこでデモするブツに使う部品としてBuffaloの赤外線学習リモコンのRubyラッパーを書きました。これで家に帰る前に暖房つけたりできてうれしいですね。
玄人志向のKURO-RSとBuffaloのPC-OP-RSを操作できます。
MacとLinuxと、試してないけどたぶんWindowsでも動く気がする。コードはgithubに置いてる。
学習リモコン/KURO-RS/(1)使ってみる – 脳みそ沸騰中!のPerlのコードを参考にしました。
■PC-OP-RSを買う
気がついたらKURO-RSがどこにも売ってないんだけど、PC-OP-RSがKURO-RSと同じハードウェアで箱と付属ソフトが違うだけなのでどちらでも動かせます。
売り上げランキング: 4538
■インストール
gem install kuro-rs
そしてKURO-RSをMacやLinuxに刺す。
Windowsの人はドライバを入れてBuffaloアプリが動くことを確かめてからUSBポートに刺す。
KURO-RSはUSBポートに接続するとシリアルデバイスとして認識されます。MacやLinuxなら/dev/tty.usb****という名前になる。WindowsならドライバをインストールしていればCOM1とかCOM2とか名前がつく。
■赤外線リモコンを学習する
kuro-rsというコマンドがgemと一緒にインストールされています。
terminalで実行する
% kuro-rs /dev/tty.usbserial-0012a3b4そして15秒以内に赤外線をKURO-RSの本体に当てると、termialに16進数で赤外線データが出力されます。
学習した赤外線を発射しましょう
% kuro-rs /dev/tty.usbserial-0012a3b4 ffffffff0300f0e0018083...のように第二引数に16進数でデータを与えます。
これでテレビのチャンネルが切り替わるはず。
■自分のプログラムから使う
こんな感じでIOっぽく使えます。くわしくはexamplesディレクトリを見るといい。
require 'rubygems'
require 'kuro-rs'
# open KURO-RS
kr = KuroRs.open('/dev/tty.usbserial-0012a3b4')
# read
puts kr.read
## => hex dump (ffffffff0300f0e0018083...)
# write
kr.write 'ffffffff0300f0e0018083'
# close
kr.close
# block
KuroRs.open('/dev/tty.usbserial-0012a3b4'){|k|
k.verbose = true
puts k.read
## => hex dump (ffffffff0300f0e0018083...)
}
■Webアプリから使う
シリアルポートは複数プロセスで共有できないし、また複数スレッドから同時に書き込んだりもできないのでRailsやSinatraアプリにkuro-rs gemをそのまま組み込むのはオススメできません。
そういう時はkuro-rs-serverを使いましょう。
こうすると8080番portでhttpサーバーが起動します
% kuro-rs-server /dev/tty.usbserial-0012a3b4 --port 8080
curlから赤外線読み書きしてみる
# readreadもwriteも正常に行われるとstatus 200が返ります。失敗すると200以外。
% curl 'http://localhost:8080'
# => hex dump (ffffffff0300f0e0018083...)
# write
% curl -d 'ffffffff0300f0e0018083...' 'http://localhost:8080'
kuro-rs-serverを内部APIとしてRailsやSinatraから、あるいはAjaxから使うのが良いと思います。
canvasで画像処理
html5のcanvasのピクセル単位の処理を試してみた。ここで動かせる → http://dev.shokai.org/test/canvas/cv/
ソースはここ https://github.com/shokai/js-canvas-test/tree/master/cv
輪郭抽出とかしてみた

■canvasでのピクセル処理方法
canvasはgetContext(’2d’)してからgetImageDataするとImageDataオブジェクトが手に入る。
あとの処理はこんな感じ(画像をグレースケールにする例、cv/main.jsの39行目あたり)
var canvas = $('canvas#img');
var ctx = canvas[0].getContext('2d');
var img = ctx.getImageData(0, 0, canvas[0].width, canvas[0].height);
for(var i = 0; i < img.data.length; i+=4){
var r = img.data[i]&0xFF;
var g = img.data[i+1]&0xFF;
var b = img.data[i+2]&0xFF;
// var a = img.data[i+3]&0xFF;
var gray = (r+g+b)/3;
img.data[i] = gray;
img.data[i+1] = gray;
img.data[i+2] = gray;
}
ctx.putImageData(img, 0, 0);
データが1次元配列になっていて、RGBAの順に値が格納されている。なのでImageData.dataの要素数はピクセル数の4倍になる。x,y座標でデータを取れる関数が無いので、自分で色々試して作ってみたけどどうしても3〜6倍ぐらい遅くなってしまうので1次元配列のまま扱う事にした。
JavaScriptで多値を扱うには配列やオブジェクトを使わなければならないんだけどどうやらそれらの生成コストがかなり高いらしく、1ピクセルずつ処理したらひどく遅くなった。
■クロスドメイン
別ドメインの画像をcanvasに読み込んで、getImageDataはできない。chromeだと “Uncaught Error: SECURITY_ERR: DOM Exception 18″ というエラーが開発パネルに出る。
ローカルでの開発時にローカルのhtmlからローカルの画像を読み込んでgetImageDataしてもこのセキュリティエラーが出るので、rubyで簡単なhttpサーバーを作っておいたのでコレ使うといい。
実行するとそのディレクトリでhttpサーバーが起動する。
■実行速度
端末によって実行速度が違う。
下の画像は、今年の2月に買った11インチMacbook Airのchromeで、1000×1000の画像を4段階量子化したところ。
だいたい50ミリ秒で量子化できた。遅いパソコンでも毎秒数回は実行できそう。
iPodTouch 4Gや初代iPadはMacbook Airより30倍ぐらい遅くて2秒弱かかる。Nexus Sが意外なことに更に遅くて25秒ぐらいかかる。Macの500倍遅い。

canvasとwebsocketでお絵かき共有
http://canvas.shokai.org
HTML5のcanvasを使ってみたかったので作った。
websocketも使っているので、chromeかsafariで動く。ブラウザ2つ開いてみると、同期しているのがわかりやすい。
画像のURLを末尾につけるとその画像が読み込めて、マウスで線を引くとみんなでリアルタイムに描ける。Gyazoと合わせて使うと便利。
http://canvas.shokai.org/http://gyazo.com/365d02afdf4953d40ec904df5019aa13.png
ソースはgithubに置いた https://github.com/shokai/shared-canvas
こんな風に、オンラインゲームのマップを置いて、友達と「ここ攻めろ」みたいな指示を共有したいなと思って作ってみた。
http://canvas.shokai.org/http://gyazo.com/1b2f1f6b0df60aa2d0dfe3da79106a4e.png
canvasのプラグインは色々あるけど、canvasのAPIの操作感が変わりすぎる物ばかりだったので、とりあえず何も使わないで操作してみた → draw.js
Imageオブジェクトで画像を読み込んで、onloadイベント発生時にcanvasのサイズを変更するとぴったりのサイズになる。かならずdrawImage前にサイズ変更をすること。
(92行目あたり)
var draw_img = function(img_url, onload){
var img_tag = $('canvas#img');
ctx = img_tag[0].getContext('2d');
var img = new Image();
img.onload = function(){
img_tag.attr('width', img.width).attr('height', img.height);
ctx.drawImage(img, 0, 0, img.width, img.height);
if(onload && typeof onload == 'function') onload();
};
img.src = img_url; // 読み込み開始
};
rubyとem-websocketで作ったwebsocketサーバーは、daemontoolsで自動起動・復活するようにしてある。DBは無くて、最近10万本のlineの色と太さと座標データを保存している。
また線にはどの画像URLの線か、というデータも付いているので、これで画像URL毎に部屋分けを行っている。
縦分割してgrepできるwebsocket client、あるいはADKのデバッグ方法
AndroidでADK開発している時に便利なツールを作った → http://dev.shokai.org/js/websocket-client/
ADKをAndroidに挿すと、1つしかないUSBポートが埋まってしまって、logcatでデバッグ情報を見れなくなってしまう。しかし、俺の使っているNexusSはネットワーク越しのADB(Android Debug Bridge)はrootを取らないと使えない。
素晴らしいことにブラウザからlogcatを見る – 明日の鍵で、「LogcatSocketServer」というlogcatを全てwebsocketに流してくれるサーバーを作ってくれていた。これは凄く良い。
俺は普段はlogcatを複数開いて、 ^[DE]/ やアプリ名などでgrepしてエラーだけを表示したりしている。LogcatSocketServerの出力を分割してそれぞれgrepできるしくみがあれば、普段と同じ快適なAndroidアプリ開発環境が手に入る・・・ので作った。
webブラウザでwebsocketを受信して、縦分割で複数表示し、それぞれgrepできる。(クリックで拡大)
「+」ボタンを押す毎に分割パネルが増える。
この例では4分割して、左から順に「全て表示」「IOIOに関するものだけ表示」「DebugとErrorだけ表示」「バッテリー情報を表示」している。

Androidのデバッグだけではなく普通のwebsocketを使ったwebアプリのテストにも使えるはず。
■LogcatSocketServerのインストール
ブラウザからlogcatを見る – 明日の鍵にあるLogcatSocketServerをAndroidにインストールする。
バイナリがあるのでダウンロードして、AndroidにUSBケーブルつないでインストール。
wget http://tomorrowkey.googlecode.com/svn/trunk/LogcatOnBrowser/LogcatSocketServer/bin/LogcatSocketServer.apk
adb install -r LogcatSocketServer.apk
起動させ、start serverボタンを押すとAndroidがwebsocketサーバーになる。
■webブラウザでlogcatを見る
http://dev.shokai.org/js/websocket-client/を開く。Google ChromeかSafariでしか動かない。
LogcatSocketServerの画面に表示されているIPアドレスとポート番号を、左上に入力してに接続する。
「+」ボタンを押すとパネルが増える。あとはgrep欄に正規表現を書けば表示をフィルタできる。
^[VEW]/アプリ名 とかでgrepしたりすると便利ですぞ。
ローカルで実行するならgithubに置いたのでどうぞ https://github.com/shokai/websocket-client
git clone git@github.com:shokai/websocket-client.git
open websocket-client/index.html
こういうGUIアプリ、VisualStudioとかで作ってたけど無名関数をばしばし使えるJavaScriptの方が作りやすいですね。



最近のコメント