重い処理が終わったらgoogle talkで通知する – 橋本詳解
が便利で、サーバーでの処理が終わったらIM通知するのに使っている。
IMはポップアップして音も鳴るので、Terminalを睨んでなくても良くなる
(サーバーで使う物と、自分が普段使うのとでGoogleアカウントが2つ必要)
追記:どうやらtoもuserも同じアドレスを指定して大丈夫らしい
Read more
LDR unread countがchumby.comのwidgetとして公開された。
Livedoor Readerのアカウント名を設定すると、未読数が表示されて焦らされるが、1万超えたあたりからどうでもよくなった。
アップロードしたwidgetは基本privateで、publicにした後審査が入ってwidgetsの検索画面から他のユーザに使ってもらえるようになる。今回はだいたい4時間ぐらいで審査が通ったみたい。
ダウンロード → SourceCode(Flash AS2 / CS3)
(うおお、前の記事書いてから1週間たってる・・・)
前のTwitter widgetより前に作って投稿してあったものなんだけど、これは数字が出るだけなので、Flash的にも手抜き。
Flashは手抜きだけど、chumby widget固有のノウハウである
1.クロスドメイン許可されていない外部のサーバーのデータを読みに行く
2.chumby.comにデータを保存できる設定画面を作る
3.chumby.comに保存したデータをwidgetから読み込む
という事をやってみたので、まとめておこう。
■1.クロスドメイン許可されていない外部のサーバーのデータを読みに行く
Livedoor Readerの未読数を取得するAPIを使う。
パラメータにuser=shokaishokaiなどすると未読数が出てくる。
特にXMLとかではないので、AS2の場合LoadVarsを使えば良い。
ローカルドメインで動かす分にはこれで構わないが、セキュリティの事もあってサーバーに置いてあるFlashは別のサーバーにあるデータを読みに行く事ができないようになっている。そのため、rpc.reader.livedoor.comを読みに行けない。前のtwitterで使ったXMLクラスなんかは例外。
そのため、大学院棟のサーバーにchumby.comからのアクセスを許可するcrossdomain.xmlを置いて、RubyでproxyするCGIを置いてそれをchumby上のFlashから読むようにした。
crossdomain.xml
*.chumby.com からのアクセスのみ許可すればよい
このサーバーにRuby適当に作ったproxyを置いて、Flashから読ませる。
これで外部ドメインのデータを読めるようになった。
■2.chumby.comにデータを保存できる設定画面を作る
widgetの管理画面で、設定値を入力するダイアログを出すようにした。
データはchumby.comに保存され、自作widgetがchumby上でロードされたしばらく後に設定値が_root直下の変数として現れるという仕様らしい。
この辺のドキュメントを参考にした。
- Developing widgets for chumby – ChumbyWiki
- Widget Parameter Example – ChumbyWiki
- Adobe – Developer Center : Developing widgets for Chumby with Flash Lite 3
サイズは320×240 pixelで、Sample Parameter Example(AS2)に同梱されてた com.Chumby.WidgetParams.as を使うのが楽らしいので作ってみた
→ configure.fla
まあ今回はユーザ名を保存するだけなのでサンプルを削っただけなんだけど、送信が終わったらgetURLでjavascriptを呼んで自分自身を閉じたりとかしていて面白い。
■3.chumby.comに保存したデータをwidgetから読み込む
chumby.comに保存されたデータは、widgetが画面に読み込まれてからしばらくたってから、_rootに現れる。
どうやら毎回読み込みに行っているらしい。
値が_rootに現れるまで待たないと、undefinedになってしまうので待つ。
this.onEnterFrame=function(){
if(username==null)return;//待ちます
ldr_loadUnread(username);
deletethis.onEnterFrame
}
こんな感じで、chumby+サーバーサイドができました。
blogを書けなくて(MTが再構築できなくて)もう1ヶ月ぐらい前に作ったものになるけど、春休みにRuby on Railsのお勉強をしていて、その最終成果物としてGoogleEarth上でFlickrのGeoTag付き写真を見れるサービスを作ったのでまとめておく。
ついでに、緯度経度でFlickrの写真を検索できるAPIも公開してある。
■実装方法
1.Flickrのタグ検索で、geotagが付いている写真を定期的にクロールしてきて、写真のURL、緯度経度をRailsのDBに溜める(photo modelに溜める)
2.GETパラメータで緯度経度をRailsに渡して、photo modelを検索する
3.検索結果をGoogleEarthで表示できるように、kml出力のViewを作る
4.GoogleEarthで視点が変わる毎にサーバーに問い合わせて、返ってきたkmlを表示するkmlを作る
5.mongrelでRailsを動かして、apache2のmod_proxy_balancerでRailsのURLをサブディレクトリに見せかける
こんな感じで。一番時間がかかったのが1のクローラの実装で、これは俺がRuby初心者すぎて2日ぐらいかかった。あとは、デンマーク行きの飛行機と帰りの空港からのバスでやったので5時間ぐらい。この辺は、データを溜めて、クライアントからのリクエストに基づいてフォーマットを決めて吐き出す部分が最初からできてるRailsのおかげ。
■1.geotag付き写真クローラ
まずFlickrはタグ検索ができるけど、数値じゃなくて「〜〜を含む文字列」としてしか検索できないので、例えば「北緯35度東経135度周辺の写真が欲しい」という時は使えない。なので、あらかじめメタデータを集めておいて、数値として範囲を指定して検索できるようにしておく。
geotagは小数点ありの値(geo:lat=35.2341など)なんだけど、普通にgeo:latやgeo:lonを含む写真一覧をFlickr APIから検索しても小数点無しのタグしか手に入らない。
小数点ありのタグを手に入れるために、Net::FlickrでFlickrAPIからタグ検索して、
→ Net::Flickrで全public photoからタグ検索 – shokaiの日記
“geotagged”タグを含む写真をリストアップして、それから再度photo_idを使ってFlickrAPIのphotos.getInfoメソッドを使ってtagのraw attributeを見なければならなかった。
→ s.h.log RubyでFlickr APIのphotos.getInfoを呼ぶ
クローラ自体はRailsで実装されていなくて、ActiveRecordだけを使ってcronで1時間毎に実行されている。
→ s.h.log RailsなしでActiveRecordだけ使って、SQLiteを読み書きする
SQLiteのファイルがRailsと共有されているだけ。今回は、Rails側からの書き込みが無いので特に問題は起こらないだろうと判断した。
いまのところ10万枚の写真が集まった。SQLiteのファイルが欲しい人はあげます。
あと、クローラは連続でHTTPアクセスするとFlickrに悪い気がするので、適当にsleepを入れてみてるんだけど、そうすると実行に結構時間がかかる。これが、クローラを作って動かして直して作って…と繰り返す時に面倒だったが、和田さんに言われてscreenをデタッチ/アタッチするという技を覚えた。デタッチしておくと、sshを切断してもクローラが止まらなくて、アタッチしたら普通に続きからできる(もしくは結果が出てる)screenはクローラ作ってるときに重要。
■2.緯度経度をGETパラメータでRailsに渡して検索する
photos.kml?lat=35&lon=135&size=thumb
みたいな形式で、パラメータを渡してDBに溜めた写真を検索する。
→ KMLを全部出すと多すぎたので、緯度経度を指定してその周囲の写真だけ出す – shokaiの日記
paramsで受け取れる。パラメータ名はシンボルになっているので注意。
controllerで、ActiveRecord::Baseのfind_by_sqlメソッドで普通に検索。(この方法だと四角い。PostgreSQLやMySQLの空間型を使えば丸くできるらしいがとりあえずSQLiteでやる)
そしてmodelの配列をViewに渡してやる。
■3.検索結果をGoogleEarthで表示できるように、kml出力のViewを作る
kml形式のviewを作る。views/photos/index.html.erb を参考にして、index.kml.erbを作ればok
mime-typeにkmlを追加しておく必要があった。
→ flickrのgeotagついてる写真を収集してたので、kml出力するようにした – shokaiの日記
結果は巨大なkmlになるので、Rails標準搭載のWEBrickだときつい。でかいときはhttpサーバーをmongrelに換える。
→ MongrelでRailsをデプロイ – shokaiの日記
→ apache2のサブディレクトリをmongrelで起動してるrailsにプロキシする – shokaiの日記
■4.GoogleEarthで移動する毎に検索するkmlを作る
GoogleEarthの表示を作っているkmlは、静的な表示だけでなく、NetworkLinkタグで別のKMLの内容をURLを指定して読み込める。さらにViewRefleshModeをonStopにすると、画面の移動が止まった時に再読み込みできる。
再読込時に、視点の緯度経度を[lookatLat][lookatLon]で取得できるので、
lat=[lookatLat]&lon=[lookatLon]
としてNetworkLinkで読み込むkmlのURLの後ろにくっつけてやる事で、GETパラメータになる。
→ GoogleEarthで表示している場所の緯度経度から検索する – shokaiの日記
■5.mongrelでRailsを動かして、apache2のサブディレクトリに見えるようにする
デプロイ。
4まではMac OSX上でやって、ここからは大学院棟に置いたUbuntuに移し替えた。RailsをSQLite+Mongrel環境で動かして、URLをapacheで隠すようにすると、Railsプロジェクトのディレクトリをそのまま移し替えるだけでほぼ動くので超楽。
→ Flickrのgeotag写真を検索する – shokaiの日記
→ apache2のサブディレクトリをmongrelで起動してるrailsにプロキシする – shokaiの日記
→ MongrelでRailsをデプロイ – shokaiの日記
→ Mongrel入れる – shokaiの日記
———–
こんな感じで、クローラの実装と、バックエンドのサービスとしてAPIを吐くためのRails、というのを覚えた。
今まで戦略的に「長い時間をかけたインタラクション」をするモノや、「データを共有した複数のモノと人とのインタラクション」を作る事を避けていたんだけど(ややこしくてプロトタイピングできないものは作らない方針なので)
Rails使うとサクサクとこのぐらいまではいけるようになったので、自分の得意なフィジカルなデバイス作成と合体させて何か新しい物を作る予定。
Railsのscaffoldでさくっと作ったインタフェースって、HTTP-POSTからSQLに保存したり取り出したりもできて色々プロトタイプを作るのに便利なのでまとめておく。
ためたデータの管理もできるし。
■Rails側の準備
まずrailsを入れる。
Macの人は既に入っているはず。Windowsなら、ActiveScriptRubyを入れてパス通すと、gemコマンドが入るのでgem install railsすればrailsコマンドが使えるようになる。DBはSQLiteのdll版をc:\windows\system32に入れればできる様になるはず。
railsでtestbbsというプロジェクトを作って、そこにscaffoldでentry(投稿)というmodelを作る。entryには、name(投稿者)とmessage(本文)が入る。
rails testbbs
cd testbbs
ruby script/generate scaffold entry name:string message:text
rake db:migrate
(単数形に注意)
webサーバーを立ち上げる
ruby script/server
http://localhost:3000/entriesから見れるようになっている。はず。(複数形に注意)
こんなページができている。ここからentryを増やしたり消したりもできる。
ここまでで、http://localhost:3000/entries/newから投稿できるのと、http://localhost:3000/entries.xmlから一覧を取得できるようになった。
→Source Code (Ruby on Rails 2.0.2)
■Flashから投稿する
HTTP POSTで行う。
今回作ったもの(動きます)
Source Code (AS3 / Flash CS3 + Flashdevelop)
今回もFlashDevelop上でAS3書いて、FlashCS3オーサリング/コンパイルした。
こいつでPOSTすると、http://localhost:3000/entriesに結果が出るようになる。
どうやってるかというとまず
http://localhost:3000/entries/newを見ると
Name
Message
という風にPOSTしているので、entry[name]とentry[message]をパラメータで渡せばいいとわかる。
Net::Flickrをインストールしたら、flickr.photos.getInfoメソッドが実装されてなかったので良い機会なので実装してみた。
flickr apiをrubyで使う – replore的日記がとても参考になった。
FlickrAPIは普通にRESTなので、REXMLで取得してparseする。
今回自分で実装したのはgeotagまわりのため。FlickrのAPIの仕様でtagは小数点やハイフンが消されるので、その元の値を取るのにgetInfoメソッドが必要になる。Tagオブジェクトのrawからアクセスできるようにした。
使い方はphoto_idをコンストラクタに渡す。
info = PhotoInfo.new(photo_id)
info.tags.each{ |tag|
puts tag.raw
}
flickr-photos-getInfo.rb
require’open-uri’
require’rexml/document’
require’cgi’FLICKR_API_KEY=’your-api-key’
defflickr_call(method_name,arg_map={}.freeze)
args=arg_map.collect{|k,v|CGI.escape(k)<<'='<
url=”http://www.flickr.com/services/rest/?api_key=%s&method=%s&%s”%
[FLICKR_API_KEY,method_name,args]
doc=REXML::Document.new(open(url).read)
endclassPhotoInfo
@xml_doc
definitialize(photo_id)
@xml_doc=flickr_call(‘flickr.photos.getInfo’,’photo_id’=>photo_id)
end
deftags
tag_list=Array.new
REXML::XPath.each(@xml_doc,’//tag’){|tag|
tag_list<
‘id’=>REXML::XPath.first(tag,’attribute::id’),
‘author’=>REXML::XPath.first(tag,’attribute::author’),
‘raw’=>REXML::XPath.first(tag,’attribute::raw’),
‘tag’=>tag.text
)
}
returntag_list
end
endclassTag
definitialize(args)
@id=args[‘id’]
@author=args[‘author’]
@raw=args[‘raw’]
@tag=args[‘tag’]
end
defid
@id
end
defauthor
@author.to_s
end
defraw
@raw.to_s
end
deftag
@tag.to_s
end
defis_machine
if@tag=~/.+:.+=.+/
returntrue
else
returnfalse
end
end
defis_geo
if@tag=~/geo:.+=.+/
returntrue
else
returnfalse
end
end
end