0

縦分割して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の方が作りやすいですね。

5

Sinatra+Haml+jQuery入門

研究室の後輩にSinatraとhamlとjQueryを教えるために作ったテンプレートについて、ここにも書いておく

ソースコード https://github.com/shokai/sinatra-template
実際動いているもの http://masui.sfc.keio.ac.jp/sinatra-template/


git clone git://github.com/shokai/sinatra-template.git


■Sinatraを何に使うか
Sinatra+haml+jQueryが便利。
Railsと似てるけど、ちょっと違う。

個人的には
Rails → HTMLのページをいっぱい作るのに便利
Sinatra → 画面遷移あまりしなくて、同じURLのままjsonのAPIをjQueryのajaxで取得して動的に表示を変えるwebページを作るのには便利

に感じる。
でもSinatra自由すぎるので、ある程度実装パターンを知らないとメチャクチャになるのでこのテンプレートを参考にすると良いよ

個人的にはserial-http-gatewayと一緒に使ってデバイスと連動したwebページを作る、とかが手軽にできてよく使う。



■動かし方
gemでsinatra入れて、ruby development.ru
詳しくはREADME嫁


■テンプレートの解説
最低限の動作するおみくじアプリです
おみくじ結果をJSONで返すAPIがある
jQueryでajaxでJSON読んで表示する
hamlでhtmlを作る
開発用とデプロイ用の2種類のRackUp(*.ru)ファイル付き


■ファイルの説明
・README.md
 まず読め
・development.ru
 開発サーバーを起動し、main.rbとhelper.rbを読み込んでSinatraアプリを実行するスクリプト
・config.ru
 本番サーバーのapacheやnginxでsinatraアプリを実行するためのPassenger用スクリプト
・config.yaml
 ”やむる”形式の設定ファイルです。アプリのタイトルしか書いてない。
 ここに設定値を書くようにするとアプリを配布するのに便利
 (必要になったら)DBの接続設定などを書くと良い。
・Gemfile
 アプリで使うgemを書いておく
 bundlerでgemを管理する時に使う
・helper.rb
 起動時に一回だけ読み込まれる
 必要なライブラリをロードするコードはここに書く
 (必要になったら)データベースへの接続などをここで行うと良い。
 app_rootという関数が定義されている(重要)
 これにより、開発サーバー・サブドメインでの運用・サブディレクトリでの運用でも内部のURLがズレない
 jsからサーバーのAPIにアクセスする時、hamlでcssを読み込む時などに便利
・main.rb
 Sinatraアプリ本体
 HTTPでアクセスしてきた時のresponseを書く
 app_root/omikuji.json でアクセスしてきた時に、ランダムなおみくじを返す
・views/
 hamlを置くディレクトリ
・views/index.haml
 http://(app_root)/ にアクセスした時に表示されるhamlファイル
 index.hamlをどのURLの時に表示するかは、main.rbで指定している
 main.js, main.cssを読み込んでいる
 rubyの変数のapp_rootをjsの変数app_rootに渡している(重要)
・public/
 画像やjavascriptなどの静的ファイルを置くディレクトリ
・public/js/jquery.js
 最新版のjquery
・public/js/main.js
 index.hamlから読み込まれるJavaScript
・public/css/main.css
 index.hamlから読み込まれるcss

SinatraやjQueryの基本的な使い方についてはググる。ライブラリの入門サイトとかを頭から読むよりも既に動いているアプリのソースを読んでわからない所を調べるのが一番速い。


■工夫しているところ
そんなに多いわけでもないけど、
・config.ruとdevelopment.ruを分ける。developmentから起動した時だけsinatra/reloaderを使ってアプリを毎回リロードさせている
・helper.rbの中身は1プロセス毎に1回しか呼ばれないので、DBとの接続や設定ファイルの読み込みはmain.rbと分けてここに書いておくといい
・app_rootという関数を定義してあって、開発環境や本番環境でAPIのURLがずれないようにしている
haml内に書かれたRubyコードの動作についてはここにまとめた


■アプリの動作
ruby development.ruする→helper.rb読む→helperがyamlの設定ファイルを読む、app_rootという関数を作る→port8080でサーバーがthinに設定される→Sinatraアプリ(main.rb)を起動→main.rbは”/”へのアクセスにindex.hamlを返す、”/omikuji.json”にはランダムなおみくじと時刻を返す

ブラウザで”/”にアクセスする→cssとjsを読む、ajaxでおみくじを取得する関数がボタンに関連付けられる→ボタン押す毎におみくじ表示される



こんな感じで、ajaxでデータ取ってきてhtmlを書き換えるアプリの最低限のテンプレートを用意しました。
意外とDB無くてもglitchtweetTweetButton増井研オーディオAPIのようなものは作れるので、まずはDBなしでSinatra+Haml+jQueryで何か作ってみるのが良い。


DB使うときは、SQL系ならActiveRecordsかSequelかDataMapperあたりがメジャーなのかな?多分。そのへんをまず単体で使ってみて、適当にtwitterのクローラーとか作ってみると良い。
それからSinatraの中に混ぜて使ってみる。いきなりjsで画面が書き換えて、Sinatraもいじって、DBも使うとかやると確実に破滅するので一つずつやるのオススメします

3

iPhone JavaScript Console作った

作った → https://github.com/shokai/iphone-js-console

iPhone用のJavaScript shellのようなもの。FirebugやChromeの開発パネルみたいな感じで使う。

chrome拡張やiPhoneシミュレータでiPhone用のwebページの動作は確認できるが、加速度センサやGeo Location APIなんかは実機で動かさないとデバッグできない。
しかしデバッグをしようにも、iPhone上で大量のalertを出すと気が狂ってしまう。iPhoneで実行中のwebページ上の任意のオブジェクトの中身を、Macから覗いたり値を書き換えたり関数を実行したりするツールが必要だったので作った。

なお、Androidのブラウザにはwebsocketが無いのでこのツールは動かない。Androidではlogcatで

adb logcat | grep "^./browser" --color=auto
すればconsole.log、console.errorの出力は見れるので、それで何とか我慢している。



■セットアップ
MacとiPhoneを用意する。MacとiPhoneは同じ無線LANの下に接続して、互いに通信できるようにしておく。

github.com/shokai/iphone-js-consoleからcloneしてくる。

iphone-js-console.jsをhtmlに読み込ませる。JsConsole.startで自分のMacに接続させるようにする。
<script src='iphone-js-console.js' type='text/javascript' />
<script type='text/javascript'>
JsConsole.start('ws://192.168.1.38:8088'); // Addr of Console Server
</script>
(あらかじめconsoleを起動するMacのIPアドレスは調べておこう)


Macで、iphone-js-consoleを起動する
./iphone-js-console

iphone-js-consoleの起動時に、rubygemsが足りないという警告がでたら足りないgemをインストールする。
gem install eventmachine em-websocket
多分これで足りる。
あとreadlineを使っているけど、Macの最初から入っているreadlineは腐ってた気がするので、brewかportsで入れるといい。(わからなかったら飛ばしても多分良い)



■使う
Macのiphone-js-consoleで
alert(document.title)
と打つと、


このようにiPhoneのSafari上でJavaScriptが実行される。


また、iPhoneのSafariの変数を参照することもできる。
> window.navigator.appVersion
<1> "5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"


中身が複雑なオブジェクトは整形されて表示される。
> location
<1>
{"href"=>"http://192.168.1.38:8080/debug-sample.html",
"hash"=>"",
"port"=>"8080",
"protocol"=>"http:",
"origin"=>"http://192.168.1.38:8080",
"pathname"=>"/debug-sample.html",
"hostname"=>"192.168.1.38",
"host"=>"192.168.1.38:8080",
"search"=>""}


もちろん、エラーも出力される。
> homu
<1> "error : Can't find variable: homu"
> 1+2
<1> 3
> 1+
<1> "error : Parse error"


iPhoneのJSで、あらかじめ
console.log(foo);
とか書いておけばもちろんMacのiphone-js-consoleにfooの値が表示される。


一度入力したコマンドは、キーボード上下で履歴を呼び出したりできる。
大変便利ですね。




■技術的なこと
iPhoneとiphone-js-consoleの接続にはWebSocketを使っている。EventMachine::WebSocketが便利だった。

iphone-js-consoleからiphoneへ送信された文字列は、そのままiPhone上でevalで実行させている。
iphoneからiphone-js-consoleへのオブジェクトの送信は、iPhone上でJSON.stringifyでシリアライズして送信して、iphone-js-consoleでparseして適当に整形して表示している。

別に難しいことはしていない。

0

PhoneGap NFC Plugin作った

PhoneGapでAndroidのNFCを使えるpluginを作った。



JavaScriptから簡単にNFCタグのIDが読める。
<script src='./phonegap.nfc.js' type='text/javascript' />
document.addEventListener('deviceready', function(){
window.plugins.nfc.id(
function(tag){
var id = tag.id; // get Tag ID;
},
function(e){
log(e);
});
}, true);


インストール方法はgithubに書いた。サンプルプロジェクトもある。
普通のPhoneGap pluginと同じく、phonegap.nfc.jsとNfcPlugin.javaを所定の場所に置くのだけど、NFCを使うためにguava librariesとAndroidManifest.xmlの修正も必要。

とりあえず、NFCでタグのIDを読むだけしか機能は無い。もちろん他にも色々データは取れるんだけど、どこまでwrapしたらいいのかよくわからないのと俺がIDしか使う予定が無いので、とりあえずIDだけにしておいた。(要望あれば追加する)




PhoneGap pluginの作り方は、phonegap / PhoneGap Pluginsが参考になった。JavaScriptからJavaのコードを呼びだす方法が書かれている。


既に公開されているプラグインがいくつかあって、それも参考になった。


0

glitchtext.js作った

作った。https://github.com/shokai/js-glitchtext

ここで試せる → glitchtext.js sample
jsのサイズが圧縮しても385Kbもあるんだけど、9割以上がインターネットをクロールして取得した装飾用顔文字になってしまった。必要ない人は後述するビルド方法に基づいてsrc/plugins/face.jsを除外してビルドするともっと小さくなるはず。


元々は、去年の夏にRubyで作ったglitchtweetというtwitterクライアントがあって、それの機能をJavaScriptに移植したもの。

glitchtweetについてはずっと使ってるんだけどblogに書くの忘れてた。ふつうの発言を入れると適当に装飾・変形させてtweetするもので、20個ぐらいのプラグインがランダムに作用して壊れた文字列を作るというもの。
後輩のぽわわがTogetter – 「奇跡のglitchtweet開幕だ」にまとめてた。


■glitchtext.jsの使い方
まずTinySegmenterとglitchtext.jsを読み込んで

<script src="tiny_segmenter-0.1.js" type="text/javascript" />
<script src="glitchtext.js" type="text/javascript" />


javascriptでGlitchTextオブジェクトを作って、randomすると適当にランダムに変形される。
2〜3回randomを繰り返すとより強力に変形する。
var g = new GlitchText();
var source = '今日はかずすけ楽しかったねー また遊ぼうねー 今度はお弁当持って行こう';
var result = g.random(source);
もしくはglitch_を先頭に持った関数で任意の変形ができる。関数の一覧はmethods()関数で取得できる。

TinySegmenterが無くても動くが、いくつかのプラグインが有効化されない。



工夫したことについて書いておく

■プラグイン
今のところ、22のプラグインが入っている。
こんな感じ
glitch_addspace : こ こ に ソ ー ス 置 い た   h t t p s : / / g i t h u b . c o m / s h o k a i / j s - g l i t c h t e x t
glitch_atai : \ここにソース置いた https://github.com/shokai/js-glitchtext/
glitch_cmabridge : ここにーソスい置た htpts://github.com/shokai/js-giltchtext
glitch_double : ここにソース置いた https://github.com/shokai/js-glitchtext ここにソース置いた https://github.com/shokai/js-glitchtext
glitch_doubleChar : ここここににソソーースス置置いいたた hhttttppss::////ggiitthhuubb..ccoomm//sshhookkaaii//jjss--gglliittcchhtteexxtt
glitch_dullness : ごごにゾーズ置いだ https://github.com/shokai/js-glitchtext
glitch_face : ここにソース置いた https://github.com/shokai/js-glitchtext ォヵェリ☆彡..._〆(`・∀・´o)
glitch_fill140 : ここにソース置いた https://github.com/shokai/js-glitchtextここにソース置いた https://github.com/shokai/js-glitchtextここにソース置いた https://github.com/shokai/js-glitchtext
glitch_hiragana : ここにそーす置いた https://github.com/shokai/js-glitchtext
glitch_hirakata : ココニそーす置イタ https://github.com/shokai/js-glitchtext
glitch_ignoreSearch : こ/こ/に/ソ/ー/ス/置/い/た/ /h/t/t/p/s/://///g/i/t/h/u/b/./c/o/m///s/h/o/k/a/i///j/s/-/g/l/i/t/c/h/t/e/x/t
glitch_insertWave : こ〜こに〜ソー〜ス置〜いた h〜ttp〜s://g〜ithu〜b〜.com/shok〜a〜i/j〜s-g〜litch〜text
glitch_kaibu : ここにソース置いた https://github.com/shokai/js-glitchtextxethctilg-sj/iakohs/moc.buhtig//:sptth たい置スーソにここ
glitch_katakana : ココニソース置イタ https://github.com/shokai/js-glitchtext
glitch_kirakira : .'。:。'★。.:゜。*:*゜*'ここにソース置いた https://github.com/shokai/js-glitchtext'*゜*:*。゜:.。★'。:。'.
glitch_linePrefix : ────ここにソース置いた https://github.com/shokai/js-glitchtext
glitch_reverse : txethctilg-sj/iakohs/moc.buhtig//:sptth たい置スーソにここ
glitch_sekine : ここにショーシュ置いた https://github.com/shokai/js-glitchtext
glitch_speak : (ここにソース置いた https://github.com/shokai/js-glitchtext)
glitch_updown : ここにソー↓ス↑置いた ↓h↑t↓tps://g↑i↓t↑hub.com/shoka↓i↑/↓j↑s-gli↓tch↑t↓e↑xt
glitch_vertical_reverse : ここにソース置いた ɥʇʇds://bıʇɥnb.ɔoɯ/sɥoʞɐı/ظs-b1ıʇɔɥʇǝxʇ



■Rakeでビルドする
RakeはRubyで書けるMakefile。

今回は文字列を操作する関数をたくさん作りたかったが、1つのjsファイルに追記していくとメンテナンスがしづらい。
動作テストまでは関数群はpluginsディレクトリに置いてあって、リリース時にRakeで一つのglitchtext.jsに合体させる様にした。

今までJSのオブジェクト指向的な機能はあまり使ったことがなかった。
忘れないうちにメモしておく
  • 先にクラスを定義しておけば後からprototypeで関数を追加できる
  • for(i in object)でオブジェクトのメソッドの名前のリストを取れる
  • メソッド名がわかれば、object[メソッド名]()で関数を実行できる
  • メソッドとプロパティの区別があまり無いので高階関数が簡単に作れる
  • if(typeof hoge == ‘function’)でプロパティかメソッドか判別できる
このへん今回重要だった。



■TinySegmenterでcmabridge
cmabridgeというプラグインにTinySegmenterを使った。TinySegmenterはJavaScriptで実装されたわかち書きエンジンで、つまり日本語を単語レベルに分割してくれる。

cmabridgeはcambridge大学で発見されたという人間の認知の穴を突いた手法。単語中の隣接する1文字が入れ替わっていてもなぜか文章として読めてしまうというもの。
こんなの↓
日今はかずけすし楽かったーね たま遊ぼうーね 度今はお弁持当ってこ行う
tinysegmenterでは品詞は分類できないが、この用途には十分だった。
あとArray.prototype.mapにRubyのArray.mapを追加したので、メソッドチェーンでどんどん文字列操作できて書いてて楽しい。



■デバッグ
chromeのjsエンジンのv8を使った。Macでは
brew install v8
でインストールできる。v8はchromeの開発パネルみたいにどのファイルの何行目でエラーが起こったかを確かめられるので良い。

glitchtext.jsは、文字列を入れたら文字列を返す関数をたくさん作る必要があったので、ブラウザでデバッグするよりもterminalからたくさん文字を入れてまとめてテストできるようにした方が効率的だったので使ってみた。
rake test
すると、プラグインディレクトリとテストコードのディレクトリを総ざらいしてこんな風に実行する
v8 /Users/sho/src/js/glitchtext/libs/tiny_segmenter-0.1.js /Users/sho/src/js/glitchtext/src/glitchtext.js /Users/sho/src/js/glitchtext/src/plugins/addspace.js /Users/sho/src/js/glitchtext/src/plugins/atai.js /Users/sho/src/js/glitchtext/src/plugins/cmabridge.js /Users/sho/src/js/glitchtext/src/plugins/double.js /Users/sho/src/js/glitchtext/src/plugins/double_char.js /Users/sho/src/js/glitchtext/src/plugins/dullness.js /Users/sho/src/js/glitchtext/src/plugins/face.js /Users/sho/src/js/glitchtext/src/plugins/fill140.js /Users/sho/src/js/glitchtext/src/plugins/hiragana.js /Users/sho/src/js/glitchtext/src/plugins/hirakata.js /Users/sho/src/js/glitchtext/src/plugins/ignore_search.js /Users/sho/src/js/glitchtext/src/plugins/insert_wave.js /Users/sho/src/js/glitchtext/src/plugins/kaibun.js /Users/sho/src/js/glitchtext/src/plugins/katakana.js /Users/sho/src/js/glitchtext/src/plugins/kirakira.js /Users/sho/src/js/glitchtext/src/plugins/line_prefix.js /Users/sho/src/js/glitchtext/src/plugins/reverse.js /Users/sho/src/js/glitchtext/src/plugins/sekine.js /Users/sho/src/js/glitchtext/src/plugins/speak.js /Users/sho/src/js/glitchtext/src/plugins/updown.js /Users/sho/src/js/glitchtext/src/plugins/util.js /Users/sho/src/js/glitchtext/src/plugins/vertical_reverse.js /Users/sho/src/js/glitchtext/test/test.js

v8は、引数に複数のjsファイルを指定できて、先に指定した物から読み込まれる。先にGlitchTextクラスの定義を読み込んで、続けてプラグインを読み込んでGlitchTextクラスをprototype拡張し、最後にテストコードを実行している。

こうすると、どのプラグインの何行目でエラーが起きたかがちゃんとv8が教えてくれる。複数のプラグインを試行錯誤しながら作っている場合でも、できた物からgitにcommitできるし、別のパソコンで他のプラグインが欠けている状態からでもテストを実行できる。


■ビルド
v8に渡したのと同じく、glitchtext本体→プラグインの順にjsファイルを連結させれば単体の.jsファイルにできる。
jsminを使うとjsファイルを圧縮できた。
Macではhomebrewでインストールできる。
brew install jsmin
jsmin < input.js > output.js