2

赤外線学習リモコンKURO-RSのWebコントロールパネル作った

赤外線学習リモコンをWebブラウザから使えるようにした。SinatraとMongoDBで、RubyでBuffalo/玄人志向の赤外線学習リモコンを操作するで作ったkuro-rs-serverを操作する。


shokai/kuro-rs-control-panel – GitHub


これでアプリから様々な機器を操作できる。家に帰る前に暖房つけたりとかNFCでテレビ動かしたりとか。


機能はこれだけ。全部GUIとJSON APIがある。

  1. 赤外線を読む
  2. 赤外線データに名前をつけて保存する
  3. 名前を指定して赤外線を発射させる
  4. データ内容を指定して赤外線を発射させる


■画面
保存した赤外線データの一覧と、新規データの保存ボタンがある
KURO-RS Control Panel


赤外線データのpermalink。 /ir/(名前) にある。
学習ボタンを押してすぐKURO-RSに赤外線を当てると
KURO-RS Control Panel


読み取られる。保存したりその場で試し撃ちしたりできる。
KURO-RS Control Panel
画面下にAPIのヘルプがあって、
curl -d 'name=tv/ch2' http://localhost:8787/kuro-rs.json
のようにHTTP-POSTで名前を指定して赤外線発射、などの方法が書いてある。



■使ってみよう
Sinatraの他にMongoDBと、KURO-RSが必要。
このコントロールパネルはkuro-rs-serverと通信するので、サーバーとは別プロセスでkuro-rs-serverも起動して使う。

git clone git://github.com/shokai/kuro-rs-control-panel.git
cd kuro-rs-control-panel
bundle install
cp sample.config.yaml config.yaml
config.yamlを編集する。kuro-rs-serverのアドレスぐらいしか編集する必要ない。


kuro-rs-serverを起動する
kuro-rs-server /dev/tty.usbserial-00012a34b5 --port 8786


コントロールパネルも起動する
ruby development.rb
もしくはpassenger使うとよい。

2

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 Tag Server



■NFCタグリーダー

これ使ってる。USB接続で、けっこうどこででも売ってる。これじゃなくてもlibnfcで動くデバイスならいけるはず。
ただしlibnfcでFeliCaが読めなかった。MIFAREタグなら読めた。

I-O DATA FeliCa&MIFAREカード対応 NFCリーダー・ライター「ぴタッチ」 USB2-NFC
アイ・オー・データ (2008-05-30)
売り上げランキング: 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 args_parser
これで必要なライブラリがインストールされる。

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
## JavaScript
var ws = new WebSocket("ws://localhost:8081");
ws.onmessage = function(e){
Console.log(e.data);
};
websocket clientを使えばすぐ試せる



Socket
telnet localhost 8082

のような感じに接続して、tagのIDが読める。

2

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と同じハードウェアで箱と付属ソフトが違うだけなのでどちらでも動かせます。

BUFFALO PCastTV2対応 PC用学習リモコンキット PC-OP-RS1
バッファロー (2006-09-10)
売り上げランキング: 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から赤外線読み書きしてみる
# read
% curl 'http://localhost:8080'
# => hex dump (ffffffff0300f0e0018083...)


# write
% curl -d 'ffffffff0300f0e0018083...' 'http://localhost:8080'
readもwriteも正常に行われるとstatus 200が返ります。失敗すると200以外。

kuro-rs-serverを内部APIとしてRailsやSinatraから、あるいはAjaxから使うのが良いと思います。

0

canvasで画像処理

html5のcanvasのピクセル単位の処理を試してみた。ここで動かせる → http://dev.shokai.org/test/canvas/cv/

ソースはここ https://github.com/shokai/js-canvas-test/tree/master/cv


輪郭抽出とかしてみた
html5 canvas edge detect


■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倍遅い。
html5 canvas qunatize

0

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毎に部屋分けを行っている。