けど、IRKitのファームウェアを改造して温度センサーを追加したで解説したセンサー追加のためのファームウェア変更はそのまま使えます。試した。
最新のmasterにgit rebaseで追従したので、tempe_sensorブランチやsensors_jsonブランチはv2.0.1にセンサー読み取り機能を追加した物になった。
v1.3.5からの変更点はモールス信号関係のコードの削除なので、あまり差は無かった。
こういうdiffとか見れるやつ
ブランチ間とか
https://github.com/shokai/irkit-device/compare/master…tempe_sensor
release tagとか
https://github.com/irkit/device/compare/v1.3.5…v2.0.1
とても便利だけどプルリク画面からしか見れない、表から辿りつけない画面な気がする。
よくURL忘れてたどり着けなくなるので、どこクリックしたらいいとか知ってる人は教えてほしい
友達に「Socket.IOはメモリリークヤバイから、新規開発なら迷わずEngine.IOを使え」と言われたのでEngine.IOを直接さわってみた。
Engine.IOはSocket.IOの内部で使われている部品で、「websocketでもajaxでも何でもいいのでとにかく通信ができる状態」を作るライブラリ。
もともとSinatra::RocketIOやlinda-socket.ioやRuby用socket.ioクライアントを作る時に中身は覗いてたけど単体で使った事はなかったし、どういう実装か忘れがちなのでメモする。
Chatを作った
とりあえずchatを作った。Herokuでwebsocketを動かしている。サーバーもクライアントも50行ぐらいで書けた。
感想としては、Engine.io単体で使うと、綺麗なアプリケーションを書くにはその上に(フル機能ではないにしても)Socket.IO的な物を実装しないと無理だなと思った。やっぱり通信がしたいのではなくて、メッセージングがしたい。
なお似たような実装でSocket.IOでのチャットも以前作った。ひと通りの機能や挙動を確認するのにはチャットを作るのがよいと思う。
Engine.IOに無い機能(Socket.IOが実装してる機能)
Engine.IOはSocket.IOの後継、ではなく内部部品で、wsというwebsocket npmをラップしつつhttpからのupgrade機能とxhr-pollingやjsonpでのフォールバックを付けたライブラリ。生のwsを直接使ってるのに近いので、バイナリのやりとりはしやすそうな気がする。
低レイヤーな分、気の利いた機能はない。そういうのはSocket.IOが担当している。
クライアントライブラリをpathに追加してくれる機能
自分でengine.io-clientからengine.io.jsを持ってきて、配置する必要がある。Socket.IOでは/socket.io/socket.io.jsとかがサーバーのpathに現れてくれる。
ちなみにこの部分、connectのリクエストを横取りするためにEventEmitterが埋め込んでるコールバックのevents配列を直接いじっててすごい事になっている。
websocket切断時の自動再接続
websocketが切断されても、クライアントライブラリは自動再接続してくれない。on(‘close’)などのイベントで自分で接続し直す必要がある。Socket.IOでは特に何も考えなくてもクライアントは再接続してくれる。サーバー側は60秒毎に全クライアントの生存確認を行っていて、そのためにクライアントは25秒ごとにheartbeatを送っている。
オブジェクトの自動シリアライズ・デシリアライズ
Socket.IOではオブジェクトをそのまま送りあえるけど、Engine.IOはsend(string or buffer)しかないのでJSONやmsgpackで自分でシリアライズ・デシリアライズしろという実装になっている。JSONじゃない物が来た時とか、try catchして〜とやってると一気にコードが長くなってつらい。
リモートのイベントをdispatchする機能
emit(イベント名, データ)でリモートのイベントを発火させられない。send(string or buffer)とon(‘message’, callback(string)) しかないので、受け取ったオブジェクトを自分でJSON.parseするなどして扱わなければならない。
EventEmitterとか使わないと巨大なswitch文が生まれるし、まあこの辺を自動的にやってくれてたのが、ものすごくコード量を減らしてくれてた事がわかる。
クライアント全員へのブロードキャスト
sockets.emitみたいなのは無いので、for client_id, client of engine.clientsのように自分でclients全員に送らなければならない
client.send JSON.stringify {type: "chat", message: "ハロー"}
rooms機能が無い
クライアントをグループ分けするrooms機能は無い。engine.io-roomsのようなプラグインを使う必要がある。
Engine.IOにある機能
on “packet”や”packetCreate”などの低レベルなイベントがあるので、デバッグに便利そう
dokkuを普段持ち歩いてるMacbook AirのVirtualBoxのUbuntu12.04に入れた。
dokkuはDocker環境をセットアップしてくれて、そこに個人用のHerokuのようなものを建立してくれる。
dokku本体は100行ぐらいのshellscriptで実装されている。そこから作者のprogrium氏が作った色々なツールが呼び出されるので、実体としてはもっと大きいけど。
vagrantとかchefとか全く使わずに、アプリをgit pushするとVMが建つ環境が簡単に作れる。
gitのhookでdockerコンテナが作られて、フロントのnginxのproxyが設定されて、websocketも通る。
コンテナ構築にはherokuのbuildpackが使われているので、アプリの内容に応じて自動的にnodeとかrubyとかの環境がセットアップされる。
buildpackはherokuがアップデートしていってくれるから、今後RubyやNodeが新しくなっても良い感じにフォローしてくれて、楽できる。
家のMacMiniにも似たようなセットアップをして、自宅をmini heroku化もできた。そっちの設定はまたあとで書く。
参考になる
なんだかんだでぐぐる前にgithubにあるREADMEちゃんと読むのが一番参考になる
Ubuntuインストール
Mac OSX上のVirtualBoxに、ubuntu12.04 64bit serverを入れた。あたらしくまっさらなUbuntuを用意する事が推奨されている。
2014年4月11日現在、ubuntu 13系+dockerの組み合わせでデッドロックしたりコンテナが止まらなかったりするらしい。
% sudo apt-get install openssh-server
% sudo apt-get install python-software-properties # 12.04だと必要
インストール時のオプションは全部デフォルトのままでよい。
自分のMacからは、Ubuntuが 192.168.56.103 として見えるようになった。(ホストオンリーアダプタを使っている)
普通にNATとかブリッジアダプタとかでもいいし、ネットワークは好きに設定すればいい。
なお起動する時にVirtualBoxのGUIからではなく、
% VBoxManage startvm "VM名" --type headlessで起動するとGUIなしでVMを起動できる。MacのLaunchDaemonに書けば便利
dokkuインストール
安定版を入れた。Ubuntuで
% wget -qO- https://raw.github.com/progrium/dokku/v0.2.2/bootstrap.sh | sudo DOKKU_TAG=v0.2.2 bashdokkuというユーザーが増えて、dockerやnginxなどが入る。
ssh鍵のインストール
ubuntuインストール時に作った普通のユーザーと、dokkuというユーザーそれぞれに同じ鍵をインストールしたMacから
% brew install ssh-copy-id
% ssh-copy-id -i ~/.ssh/id_rsa.pub sho@192.168.56.103
sshでubuntuに入ってから
% cat ~/.ssh/authorized_keys | sudo sshcommand acl-add dokku shokai/home/dokku/.ssh/authorized_keys に書き込まれる。
ホスト名の設定
Ubuntuに /home/dokku/VHOST を作り、dokku.192.168.56.103.xip.ioを書いた。
dokkuのnginxはリクエストのホスト名のサブドメイン部分でどのアプリケーションへのリクエストなのかを判別して振り分けるので、IPアドレスではなくドメイン名でアクセスできるようにしなければならない。
xip.ioを使うとサブドメイン部分をそのまま返してくれるのでLAN内のマシンにドメインが振られてるように見せかけられる。
ちゃんとグローバルIPでドメイン名ある環境だったら、xip.ioは必要ない。
デプロイする
試しにHerokuのnodejsサンプルをデプロイしてみる。Macから
% git clone git@github.com:heroku/node-js-sample.gitこれは
% cd node-js-sample
% git remote add dokku dokku@dokku.192.168.56.103.xip.io:node—js-sample
git remote add リモート名 dokku@ホスト名:アプリ名という事。
git pushでデプロイする
% git push dokku masterすると、Herokuにデプロイした時と同じようにbuildpackがNode環境を作ってる様子が流れて、
http://node-js-sample.dokku.192.168.56.103.xip.io
で起動する。
試しにsocket.ioでwebsocketを使っているアプリもデプロイしてみたら、ちゃんとwebsocket proxy通った。
dockerを0.10から0.9に戻す
dokku v0.2.2は、docker 0.10だと動かない。デプロイすると
Invalid namespace name (app), only [a-z0-9_]というエラーがでて失敗する。
issueが立ってた。
Dokku 0.10.0: Pre-receive hook declined: Invalid namespace name (app) · Issue #533 · progrium/dokku
docker 0.10からnamespaceが4文字以上必要に変更されたが、dokku v0.2.2が作るコンテナはappというnamespaceを使おうとするので失敗する。
とりあえずdockerを0.9.0に落とせば動くので、Ubuntuで
% sudo apt-get remove --purge lxc-docker
% sudo apt-get install lxc-docker-0.9.0
これでMacからgit pushしなおしたらデプロイ通った。
コンテナの管理
dockerコマンドとdokkuコマンドを併用する。詳しくはgithubのREADMEの下の方に書いてある
Ubuntuで
コンテナ一覧
% sudo docker ps
コンテナの削除。dokkuでの名前で指定して削除する
% sudo dokku delete アプリ名
コンテナのログを見る。tail -fみたいに追ってくれる。
% sudo docker logs -f コンテナ名
コンテナ名は、docker psしたら一番右にでてくるnostalgic_nobelとかsad_galileoみたいな厨二ネームっぽいやつがソレ。
手元のMacからログを見たりする
これらのコマンドはもちろんssh command proxyからも実行できる。自分をdockerグループに追加すれば /var/run/docker.sock の権限が得られるので、sudoが必要なくなる
% gpasswd -a sho docker
Macから
% ssh ホスト名 docker psでログが見れる。
% ssh ホスト名 docker logs -f コンテナ名
IRKitと、10行ぐらいのRubyでこんなに簡単にテレビ視聴が自動化できる。
見たい番組とか考えなくていいじゃないかみんなが実況してる番組は多分面白い。
手順
必要なgemをインストールし% gem install irkit httparty nokogiri
irkitコマンドで各テレビ局の名前で赤外線データを学習しておいて
% irkit -get テレビ東京
% irkit -get NHK総合
% irkit -get NHK教育
実況勢い観測 – 現在の勢いからスクレイピングしてきて、一番盛り上がってるチャンネルに合わせる。
irkit-2ch-tv.rb
require 'irkit'
require 'nokogiri'
require 'httparty'
page = Nokogiri.parse HTTParty.get("http://bc2ch.net/").body
td = page.xpath('//table[@class="sitetotal"]//td[@class="station"]')
channels = td.map{|i| i.text }
ch = channels.first # 一番盛り上がってるチャンネル
irkit = IRKit::Device.find.first
ir_data = IRKit::App::Data["IR"][ch] # 局名に対応した赤外線データ
irkit.post_messages ir_data # 赤外線発射
このスクリプトをcrontabとかに追加して、5分ごととか定期的に実行すれば自動的に一番盛り上がってる番組を追える。
% crontab -e
*/10 * * * * cd /path/to/irkit-2ch-tv/ && bundle exec ruby irkit-2ch-tv.rb > /dev/null 2>&1
若干エラーハンドリングなどを追加したバージョンをgithubに置いておいた。
https://github.com/shokai/irkit-2ch-tv
あとはテレビを買うだけだ・・・(大学にはある)