目次

2009年2月22日日曜日

スイッチ 〜モーメンタリーとオルタネイト〜

Mulius デバイスのスイッチを作っていました。


スイッチを押すと電源が入ります。

ぴか!

ここまで来るのに、結構時間が掛かってしまいました(苦笑)なぜかというと、部品を購入するために秋葉原に出なくちゃいけなくて、しかも一回目は違った種類のスイッチを買って来てしまったから。

押しボタン式のスイッチには、「モーメンタリー」と「オルタネイト」という方式のものがあり、「モーメンタリー」を一回目は大量購入してしまったからです。。。。「モーメンタリー」は押している間だけしかonになりません。
それに気づいて本日、またしても秋葉原に言って来たわけです。二日連続秋葉原(笑)

かなりどうでもいいんですけど、最近、マルツにいっても「♪マルツ〜マルツ〜」って曲流れてないですよね?なんかちょっと寂しいです。

2009年2月21日土曜日

Mulius ver3.0

ついにMulius Web Appの全ての機能が完成しました〜!
・曲を変える

プレイリストから、その時すれ違った人の聴いていた曲名をクリック。

するとTopの自分が今、聴いている曲が先ほどクリックしたものに変わります。
となりの♪をクリックすると、、、

こんな感じで、音楽ファイルの再生場所へ飛びます。

そんなこんなでアプリは完成!!!
あとはハードを完成させれば、シンポジウムを待つだけだ〜☆

WiPortは繊細?

日新システムズさん、ごめんなさい。この場であやまっても仕方ないのですが、WiPortの問題は解決しました。

今日、DNPでWiPortを使おうとした所、まったく接続出来なくなってしまい、あわてて日新システムズに問い合わせのメールを送りました。
(問い合わせは二回目。しかも回答をもらう前に、こちらで解決してしまいました。)そして今回もまた、WiPortのせいではなく、DNPのネット環境で使えなくなっていただけだと判明しました。今日はDNPのネットワークはちょっと不安定だったようです。数時間後、問題なく使えていました。
そういえばXportを使っていたときも、なんで接続できないんだ!と数日間悩んだあげく、ネットワーク環境のせいだったと分かって拍子抜けしたことがあったな〜。。。。


でも、WiPort使うのは結構シビアになってまいりました。ネットがかなり安定してないとダメなのに、本番は未知のネットワークですからねー。ドキドキだ

2009年2月20日金曜日

一番簡単なストリーミングサーバーって?

Muliusのお披露目の場所となる、代官山ヒルサイドテラスではネットワークの外部接続が出来ないということが判明し、設計変更を余儀なくされました。
OrbAPIを使おうと思っていたのですが、Orbは、Orbを提供している会社のサーバーにする必要があるのです。う〜ん。。。
Darwinをインストールしようかとも思ったのですが、もっとカンタンな方法がありました。

macに元からApacheが入っているのだから、そこに音楽ファイルを置いて、ipod touchで再生すればいいじゃない!

1、ライブラリ>WebServer>Documents の中に音楽ファイルやらhtmlやらを置く。
2、システム環境設定で「共有」>「Web共有」を有効にする。
これだけ。

1、に関して。
ipod touchで再生できる音楽ファイル/動画ファイルの形式は決まっている。形式は調べると分かるので割愛。ここは変換しておく必要がある。私はiTuneで変換。
さらに便利なのがembedタグ。これを使えばipodtouchで再生出来ます。

<embed src="test.m4a" />

これを足すだけ。

ipod touchから
http://ipアドレス/ルートとかフォルダ名
を入力すると、

こんな感じで、再生ボタンがあるだけのシンプルなもの。
再生を押してみると、

ちゃんと再生されます。

余談ですが、railsでembedタグを使うと、PCから見たときはちゃんと再生出来るのですが、ipod touchからだとリンク切れになっていました。なんでだろう。。。?
これがちゃんと出来たら、かなりイイ感じなのになぁ。。。。。

2009年2月16日月曜日

Mulius WebApp ver2.1

Webアプリもちょこっとずつ改正中。といってもレイアウトの変更がほとんど。

こちらは「すれちがった人リスト」



こちらは「お気に入りリスト」


Webアプリに付け足す機能は、
・画像のアップロード
・「聴いている曲」の変更

あと作らなくちゃいけないのは
・Orb曲ファイルに接続するためのhtmlファイル
railsとJavascriptの連携が、時間のない現状ではきついので、力技でファイル20個作戦で行こうと思います。

あとコレだけ、になる日が来るなんて、ほんと感無量。

リチウムイオン充電池 LI-355SP を使ってみた



このリチウムイオン充電池 LI-355SP かなり小さくていい感じ!

3.7vということで、このまま使ってしまってもWiPortは大丈夫なんじゃないかと思いつつも、三端子レギュレーターを通して置きました。LEDも鮮やかに光り、大変満足です。

しかし、昨日はこれが出来なかった。。。専用充電器というのが、隣に並べて千石で売られていたので購入した所、とてもファジーな代物でした。
充電が完了したら、LEDの色が赤から緑にかわる、と書いてあり、そのLEDの色に従うとまず充電は完了していません。
LEDの色は無視して、だいたい、1時間〜2時間くらい充電してあげるといいと思います。

値段は1つ3000円と高価ではありますが、乾電池よりも全然小さくて軽いので、電子工作にはうってつけだと思います。

2009年2月13日金曜日

rails ちょっとしたテク。~プロジェクトをフォルダごとコピペして、新しいプロジェクトを作る~

Railsの開発をしている時、「この状態を一度とっておいて、続きを別のプロジェクトとして作りたい」ってときがあると思います。例えば、test001を開発している時、test001をコピペしてtest002という名前に変えて開発を続けたい、って時とかです。

ただコピペするだけだと、DB/test001_developmentがtest002で上書きされちゃう。どうするかとおうと、database.ymlを編集するだけでいいんです。

development:
adapter: mysql
encoding: utf8
database: test001_development//ここを編集
pool: 5
username: root
password:
socket: /tmp/mysql.sock


test002に置き換えるだけです。これでtest001に上書きされません。migrateする前に、mysqlでDBを作るのを忘れないようにしましょう。(rakeファイルがあるなら、rake db:initializeをしてもいいかもしれません。)

2009年2月12日木曜日

Mulius WebApp ver2.0

以前、railsでのMulius WebAppの詳細を書くといっておきながら、手を付けていなかったので、Muliusの機能説明も合わせて、ここで書く事にします。
ユーザーが使える機能はざっと3つ
[1]作っているリストを見る
[2]これまでに作ったリストを見る
[3]お気に入りに登録したリストを見る

それぞれをどのように実装したか、詳しく書いて行きます。

[1]作っているリストを見る

マイコン・moxaとWiPortがセットになったMuliusデバイスを持つユーザー同士がすれ違った瞬間、、、、
1,moxa同士がradio通信を行って、信号を送り合う。
2,moxaはradio通信によって得た信号に応じて、serialSendでWiPortにHTTP POSTの文章を送る。(※c192.168.0.111:3000 ~ \r\n\r\n という文字列)
3,WiPortはmoxaから受け取った文字列をもとに、Railsで作ったMulius WebAppへHTTP POSTを行う。
4,Rails/Mulius WebAppでは、WiPortから送られて来たPOST要求を元に、DBへのレコードの更新を行う。
このとき、すれ違ったユーザーがその時聞いていた曲と、書いていたメッセージをレコードにストックする必要がある。
ユーザーIDだけをレコードにためては、ユーザーの情報が変化してしまったとき、
その時聞いていた曲
がころころ変わってしまうことになる。どうやったかというと、まず「すれ違い」のテーブルをmysqlに作った。フィールドは、id|user_id(すれちがったユーザーのID)|song_id(すれ違ったユーザーがその時聞いていた曲のID)|message(すれちがったユーザーのその時のメッセージ)|playlist_id(主体ユーザーが現在作っているプレイリスト)の5つ。
「すれ違い」DBを管理するencounter_controller.rbで以下のようなコードを書いて行った。
#aとbがすれ違った時
def ab
@encounter = Encounter.new(params[:encounter])#新しいencounterを作ります

@user1 = User.find(1)#ユーザー1のID
@user2 = User.find(2)#ユーザー2のID

conditions = ["user_id=?", 1 ]
@playlist = Playlist.find(:first, :conditions => conditions, :order => "updated_at DESC" )
@playlistid = @playlist.id #いま作っているプレイリストを探し出し、関連づける

@encounter.user_id = @user2.id
@encounter.song_id = @user2.song_id#ユーザーbのその時の曲をそのままencounterのsong_idとする。
@encounter.message = @user2.message#ユーザーbのその時のメッセージをそのままencounterのmessageとする。

@encounter.playlist_id = @playlistid

#最終的に、いろいろな所から引っ張って来たデータを、encounterの中に入れる。

if @encounter.save
flash[:notice] = '新規登録完了'
redirect_to :action => 'index'
else
render :action => 'new'
end
end

同様にac、ad、ba、bc、、、、とメソッドを用意しておく。railsのRESTFULLな特製を活かし、POST /encounter/ab とHTTPリクエストを送るだけで、ボディーにメッセージを入れなくともカンタンにDBにレコードを追加して行く事が出来る。

またJavaScriptで、このページのみ5秒間隔でリロードするようにしてあるので、あたかもすれ違った瞬間、リアルタイムで更新されているように見せている。

[2]これまでに作ったリストを見る

playlistテーブルから、いまログインしているユーザー=@current_userのIDを用いてfindする。
def index
@search = params[:id]
conditions = ["user_id=?",@search]
@playlists = Playlist.find(:all, :conditions=> conditions )
end


[3]お気に入りに登録したリストを見る
favoriteという結合テーブルを作って、userテーブルとplaylistテーブルを結合させた。フィールドはシンプル。
|id|user_id|playlist_id|
こちらも「作ったリスト」と同様、user_idからfindする。

というわけで、encounterの部分に手こずりましたが、他はいたってシンプルな構造になっています。レコードの管理になれたら、コレくらいのWebAppはさくっと作れるrailsの凄さ。でも動作がちょっと遅いのと、仕様が「?」な時があるのがタマにきずってところですかね?

でも、メディアデザインを専攻しているような学生、つまり私なんかにはこの開発スピードは何よりも美味しい。
まだまだ流行って欲しいところです。

ipod touch/iphone CSS ~URL欄を消す~

ちょこちょことCSSでレイアウトを整えております。

ipod touchやiphoneでのインターフェイスで、URLが非常に気になっておりました。完全に消し去ることは出来ないのですが、隠すようには出来るので、自分もまねしてみました。

application.rhtmlを編集します。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
<title><% if @page_title%><%= h(@page_title)%> -- <% end -%>Mulius</title>
<%= stylesheet_link_tag 'base' %>

<script type="text/javascript">
<!--
window.onload = function() {
// for hide URL bar
setTimeout(scrollTo, 100, 0, 1);
}
// -->
</script>

</head>
<body>

<div>

<%= yield :layout %>
</div>

</body>
</html>


ようは、JavaScriptを使って、URL欄が隠れる位置まで自動スクロールするという仕組みです。なので<%= yield :layout %>の中身はipod touch/iphoneの画面の長さ(420pxくらい)より長くなければなりません。heightで高さを指定してあげるといいと思いますよ。

Rails + フィジカルコンピューティング ~WiPortやXportを使って、マイコンとrailsを連携~

前回のblogでも長々とMuliusの制作の上でたどった手順を書きましたが、もうちょっと簡潔にまとめて置いて、他のrailsプロジェクトと連携させるときや、Arduinoやその他自作のマイコンと連携させるときの為に役立てようと思います。

手順:
[1]Xport/WiPortの設定
[2]XPort/WiPortをシリアル接続で、TeraTerm等から操作する。
[3]Proce55ingから、シリアル経由でHTTPリクエストを行う。
[4]マイコンにリクエスト用のコードを書き込む。

こんな手順でいけば大丈夫かと思われます。

[1]Xport/WiPortの設定
このblogでもこちらこちらでちょこっと書いてあり、もっと詳しく解説しているサイトもあるので、詳しくは書きませんが注意すべき点があります。ActiveConnectionの設定を、Manual Connectionにしておく事です。

「TeraTermでリクエスト文を打っても、一行にCが出てこない」という場合は、ここの設定が原因の場合が多いようです。
[2]XPort/WiPortをシリアル接続で、TeraTerm等から操作する。
railsプロジェクトの場合、以下のようなリクエスト文になると思われます。
C192.168.0.111:3000
GET /main HTTP/1.1<^M^J>
HOST: 192.168.0.111<^M^J><^M^J>

Winでは\を¥に変える場合もあるようです。確かめてください。
TeraTermの設定で変えられるらしいのですが、Cでサーバーに接続した後はCtrl+M/Ctrl+Jが改行/復帰(復帰=キャリッジリターン:CR/改行=ラインフィード:LF)になります。

キャリッジリターン:CR/ラインフィード:LFは、とっても重要です!


どこに使ったか、何回使ったかを必ず確認しましょう。CRのみの場合や、LFのみの場合、CRLF両方の場合があります。1つのリクエストの中で、CRのみを使う箇所と、CRLFを使う箇所がある場合もあります。1つでも違うと、リクエストは通りません。きちんと把握しましょう。
[3]Proce55ingから、シリアル経由でHTTPリクエストを行う。
お世話になりっぱなしのMakingThingsTalkのサイトに載っているプログラム(Lantronix serial-to-ethernet HTTP request tester)を使いましょう。
CRとLFに注意して、
myPort.write("C192.168.0.111:3000\n");//ここはCRのみ

myPort.write("GET /main HTTP/1.1\r\n");//こちらはCRLFを一回
myPort.write("HOST: 192.168.0.111\r\n\r\n");//CRLFを二回

Railsの場合、接続は復帰=CR一回になります。改行=LFを足すと失敗します。接続した後は、CRLFにしないとまた失敗します。
注意しましょう。
ここで上手くいかなければ、TeraTermからやり直して、もう一度確認です。
このときCR/LFだけでなく、記号(:や/)にも注意してください。:を/に変えたり、\を¥にしたりなど。
成功したら、いよいよマイコンからHTTPリクエスト文をXPort/WiPortに送ります。
[4]マイコンにリクエスト用のコードを書き込む。

Proce55ingで書いたものに忠実に、リクエスト文を出力するようにする。

これを守りましょう。どこから失敗するようになったか分からなくなってしまいますよ。以前のblogにも書いたので、かんたんに説明します。
serialSend("c192.168.0.111:3000" + "\n");
serialSend("GET /main HTTP/1.1\r\n" + "\r\n");
serialSend("HOST: 192.168.0.111"+ "\r\n\r\n");

ほとんどproce55ingで使ったリクエスト文のまんまです。プリント用のメソッド名がそれぞれのマイコンによって違うので合わせてください。未確認ですが、Arduinoだったらこんな感じ?
Serial.print("c192.168.0.111:3000" + "\n");
Serial.print("GET /main HTTP/1.1\r\n" + "\r\n");
Serial.print("HOST: 192.168.0.111"+ "\r\n\r\n");

マイコンによっては、アスキー表のコード番号からCRとLFを引っ張ってくる必要があったりもします。とりあえずは、Proce55ingで上手くいったコードをそのまま流用してからです。

こちらも参考にしながら、Rails + Xport/Wiport + マイコン によるフィジカルコンピューティングライフを楽しんでみてください。

moxaに書き込むコード 09' その[2]

最終的にmoxaに書き込んだコードの全文です。
//for A

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 2);

var checkb= 1;
var checkc= 1;
var checkd= 1;
var CR = String.fromCharCode(13);
var CRLF = String.fromCharCode(13, 10);
var c = "C192.168.0.111:3000";
var h = "HOST: 192.168.0.111";
var con = "Content-Type: application/x-wwwform-urlencoded";
var p1 = "POST /encounter/ab HTTP/1.1";
var p2 = "POST /encounter/ac HTTP/1.1";
var p3 = "POST /encounter/ad HTTP/1.1";



while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'b' && checkb == 1){
serialSend(c + CR);
serialSend(p1 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checkb = 0;
checkc = 1;
checkd = 1;
}else if(data == 'c' && checkc == 1){
serialSend(c + CRLF);
serialSend(p2 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checkb = 1;
checkc = 0;
checkd = 1;

}else if(data == 'd' && checkd == 1){
serialSend(c + CRLF);
serialSend(p3 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 1;
checkb = 1;
checkd = 0;

}else{
}

}
radioSend(0xFFFF, 'a');
}


//for B

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 2);

var checka= 1;
var checkc= 1;
var checkd= 1;
var CR = String.fromCharCode(13);
var CRLF = String.fromCharCode(13, 10);
var c = "C192.168.0.111:3000";
var h = "HOST: 192.168.0.111";
var con = "Content-Type: application/x-wwwform-urlencoded";
var p1 = "POST /encounter/ba HTTP/1.1";
var p2 = "POST /encounter/bc HTTP/1.1";
var p3 = "POST /encounter/bd HTTP/1.1";

while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'a' && checka == 1){
serialSend(c + CR);
serialSend(p1 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 0;
checkc = 1;
checkd = 1;
}else if(data == 'c' && checkc == 1){
serialSend(c + CR);
serialSend(p2 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 1;
checkc = 0;
checkd = 1;

}else if(data == 'd' && checkd == 1){
serialSend(c + CR);
serialSend(p3 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 1;
checkc = 1;
checkd = 0;

}else{
}

}
radioSend(0xFFFF, 'b');
}


//for C

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 2);

var checka= 1;
var checkb= 1;
var checkd= 1;
var CR = String.fromCharCode(13);
var CRLF = String.fromCharCode(13, 10);
var c = "C192.168.0.111:3000";
var h = "HOST: 192.168.0.111";
var con = "Content-Type: application/x-wwwform-urlencoded";
var p1 = "POST /encounter/ca HTTP/1.1";
var p2 = "POST /encounter/cb HTTP/1.1";
var p3 = "POST /encounter/cd HTTP/1.1";

while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'a' && checka == 1){
serialSend(c + CR);
serialSend(p1 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 0;
checkb = 1;
checkd = 1;
}else if(data == 'b' && checkb == 1){
serialSend(c + CR);
serialSend(p2 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 1;
checkb = 0;
checkd = 1;

}else if(data == 'd' && checkd == 1){
serialSend(c + CR);
serialSend(p3 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 1;
checkb = 1;
checkd = 0;

}else{
}

}
radioSend(0xFFFF, 'c');
}


//for D

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 2);

var checka= 1;
var checkb= 1;
var checkc= 1;
var CRLF = String.fromCharCode(13, 10);
var c = "C192.168.0.111:3000";
var h = "HOST: 192.168.0.111";
var con = "Content-Type: application/x-wwwform-urlencoded";
var p1 = "POST /encounter/da HTTP/1.1";
var p2 = "POST /encounter/db HTTP/1.1";
var p3 = "POST /encounter/dc HTTP/1.1";

while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'a' && checka == 1){
serialSend(c + CR);
serialSend(p1 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 0;
checkb = 1;
checkc = 1;
}else if(data == 'b' && checkb == 1){
serialSend(c + CR);
serialSend(p2 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 1;
checkb = 0;
checkc = 1;

}else if(data == 'c' && checkd == 1){
serialSend(c + CR);
serialSend(p3 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);
checka = 1;
checkb = 1;
checkc = 0;

}else{
}

}
radioSend(0xFFFF, 'd');
}

Mulius ver1.0 完成

今朝、ようやくハードも完成し、Mulius ver 1.0が完成しました!!!!!
長かった。。。でも、予定よりも早い完成で、嬉しい限りです。

苦労したのは、WiPort + Rails + マイコン(moxa)が、うまく連携してくれなかったこと。

WiPort + マイコンが上手くいっていないのか、Rails + WiPortが上手くいっていないのか、WiPort + Rails + マイコンを連携させる時に、不具合が起こるのか、どこで失敗するのかもうぐちゃぐちゃに。

そんなとき、Iさんに相談した所、以下のようなアドバイスを頂きました。

>足場を固めながら、論理的に問題を切り分けて行かないと、
>決してゴールにはたどり着けませんよ。

いい言葉です。。。自分の大雑把さを反省しました。コードはたった一文字で動かなかったりするんですよね。

そんなわけで、手順に関してもアドバイスを頂いたので、それをたどる事にしました。

>1 googleサーバから正しい反応が貰えるようなリクエスト文字列をTeratermで確認
>2 Processingでgoogleサーバに「全く同じ」リクエスト文字列を作り、確認
>3 moxaから「全く同じ」リクエスト文字列を送って確認
>4 Railsサーバから正しい反応が貰えるようなリクエスト文字列をTeratermで確認
>5 ProcessingでRailsサーバに「全く同じ」リクエスト文字列を作り、確認
>6 moxaから「全く同じ」リクエスト文字列を送って確認

それでは、手順をひとつずつ見て行きましょう。
[1]SFCサーバから正しい反応が貰えるようなリクエスト文字列をTeratermで確認
googleにリクエストを出すと、上手くいかない時があったので、大学のwebサイトのindexにGET要求を出す事にしました。
まずはSFCのIPアドレスを調べます。
$ dig www.sfc.keio.ac.jp
digでIPアドレスを調べることが出来ますよ。調べたら、TeraTermで、HTTPリクエストを出してみます。

C133.27.4.221:80
GET /index.html HTTP/1.1<^M^J>
HOST: www.sfc.keio.ac.jp<^M^J><^M^J>


MakingThingsTalkという本を参考に、やってみました。
ポート指定の前は、MakingThingsTalkでは/を使っていました。/ではなく:ではないだろうか?という意見を頂いたのですが、/を使っても、:を使っても同じくサーバーと接続できました。なので、ひとまず:で統一することにしました。
少し気になっているのは、サーバーに接続した後は、Enterではなく^M^J(Ctrl-M,Ctrl-J)でCRLFを行っている事。MakingThingsTalkには書かれていたのですが、なぜ^M^Jでなくてはダメなのかは設定の問題と書いてありました。ちょっと気になる所でしたが、ともあれ、上記のリクエスト文で間違いなくGETできていました(200 OKも出ているので)

[2]ProcessingでSFCサーバに「全く同じ」リクエスト文字列を作り、確認

MakingThingTalkではTeraTermからではなく、Proce55ingから、シリアル接続でWiPortにリクエストを出せるプログラムが載っています。Processingのコードの中に大学のサイトのIPアドレスを入れます。
ちなみにこれは、何でもいいので、ボタンを押すと、イベントシーケンスを1つずつ実行してくれるプロジェクトです。
import processing.serial.*;
Serial myPort; // Serial object
int step = 0; // which step in the process you're on
char linefeed = 10; // ASCII linefeed character
void setup()
{
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil(linefeed);
}
void draw()
{
}
void serialEvent(Serial myPort) {
print(myPort.readString());
}
void keyReleased() {
switch (step) {
case 0:
myPort.write("C133.27.4.221:80\n");
step++;
break;
case 1:
myPort.write("GET /index.html HTTP/1.1\r\n");
myPort.write("HOST: www.sfc.keio.ac.jp\r\n\r\n");
step++;
break;
}
}

200 OKと出て、処理が行われました。改行は\nで良さそうです。MakingThingsTalkでは、Cの後は\rになっていたのでちょっと気になっていましたが、\nに変えても結果は変わらなかったので、\nで統一することにしました。(TeraTermで入力した文字列に忠実であるため)また、GET以降はTeraTermと合わせるため、\r\nとしましたが、\nでも問題なく動いていました。
myPort.write("GET /index.html HTTP/1.1\n");
myPort.write("HOST: www.sfc.keio.ac.jp\n\n");
ひとまずは\r\nで行く事にします。
[3]moxaから「全く同じ」リクエスト文字列を送って確認
確認の方法が少し面倒だったので、(MakingThingsTalk > Processingでサーバーを作る方法)
後回しにして、railsの方を進めてみました。
[4]Railsサーバから正しい反応が貰えるようなリクエスト文字列をTeratermで確認
mainページだと、かえってくるhtmlが長過ぎるので、loginページにリクエストを出して分かりやすくしました。
C192.168.0.111:3000
GET /login HTTP/1.1<^M^J>
HOST: 192.168.0.111<^M^J><^M^J>

200 OKが出て、きちんとかえってきました。
[5]ProcessingでRailsサーバに「全く同じ」リクエスト文字列を作り、確認
Processingのコード・以下の三カ所を変更。
myPort.write("C192.168.0.111:3000\n");

myPort.write("GET /encounter HTTP/1.1\r\n");
myPort.write("HOST: 192.168.0.111\r\n\r\n");


なんと今度は成功!ずっと失敗してたのに、、、、。
200 OKとでて、きちんと返してくれました。こちらはSFCの場合と異なり、\r\nとしなければ失敗するようです。(試しに\nでリクエストを出したところ、同じようなエラーが出ました。)
ひとつずつ確認していった事が功を奏したようです。POSTも同様に確かめてみました。

myPort.write("C192.168.0.111:3000\n");

myPort.write("GET /encounter HTTP/1.1\r\n");
myPort.write("HOST: 192.168.0.111\r\n\r\n");

こちらも成功していました。これは期待できるかも、、、、?!
[6] moxaから「全く同じ」リクエスト文字列を送って確認
長いので、全文は後ほど掲載します。
前回からの変更点のみ抜粋。
var CR = String.fromCharCode(13);
var CRLF = String.fromCharCode(13, 10);
var c = "C192.168.0.111:3000";
var h = "HOST: 192.168.0.111";
var con = "Content-Type: application/x-wwwform-urlencoded";
var p1 = "POST /encounter/ab HTTP/1.1";
var p2 = "POST /encounter/ac HTTP/1.1";
var p3 = "POST /encounter/ad HTTP/1.1";

変数の宣言で、文字列指定しちゃいます。ポイントはString.fromCharCode。アスキーコードからCR(改行)とLF(復帰)を引っ張ってきます。
あとは、なんらかの信号を受け取った時(Muliusの場合、他のmoxa基盤からZigBeeで値を受け取った時)にserialSendでWiPortに上記の文字列を送るようにします。
serialSend(c + CR);
serialSend(p1 + CRLF);
serialSend(h + CRLF);
serialSend(con + CRLF + CRLF);


いざ、、、moxaに書き込み、WiPortの電源を入れて、通信させてみます。
すると、railsサーバー側では以下の結果が!

ブラウザから見てみると、

出来てた〜!!!!!

ここまで丸三日間、、、本当にがんばりました。あとはガワやサイトのCSSを整えたりって感じです。もうちょっとだけがんばりますが、今日はblogを書いたりしてのんびり過ごします(笑)

2009年2月9日月曜日

moxaに書き込むコード 09' その[1]

お久しぶりです。
なんだかんだで、Muliusのソフトウェアは完成しました。あとはハードウェアの作成です!(ソフトウェアが最終的にどんなものになったかは後日)

しばらくぶりに、moxaと格闘中。まずは、すれ違った人から、何度も値を受け取らないようにするため、checkというbooleanに使える変数を用意したコード。

これはA用コード
//for A

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 3);

var checkb= 1;
var checkc= 1;
var checkd= 1;

while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'b' && checka == 1){
serialSend("a"+"\r\n");
checkb = 0;
checkc = 1;
checkd = 1;
}else if(data == 'c' && checkb == 1){
serialSend("c"+"\r\n");
checkb = 1;
checkc = 0;
checkd = 1;

}else if(data == 'd' && checkd == 1){
serialSend("d"+"\r\n");
checka = 1;
checkb = 1;
checkd = 0;

}else{
}

}
radioSend(0xFFFF, 'a');
}


これはB用
//for B

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 3);

var checka= 1;
var checkc= 1;
var checkd= 1;

while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'a' && checka == 1){
serialSend("a"+"\r\n");
checka = 0;
checkc = 1;
checkd = 1;
}else if(data == 'c' && checkb == 1){
serialSend("c"+"\r\n");
checka = 1;
checkc = 0;
checkd = 1;

}else if(data == 'd' && checkd == 1){
serialSend("d"+"\r\n");
checka = 1;
checkc = 1;
checkd = 0;

}else{
}

}
radioSend(0xFFFF, 'b');
}



これはC用
//for C

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 3);

var checka= 1;
var checkb= 1;
var checkd= 1;

while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'a' && checka == 1){
serialSend("a"+"\r\n");
checka = 0;
checkb = 1;
checkd = 1;
}else if(data == 'b' && checkb == 1){
serialSend("b"+"\r\n");
checka = 1;
checkb = 0;
checkd = 1;

}else if(data == 'd' && checkd == 1){
serialSend("d"+"\r\n");
checka = 1;
checkb = 1;
checkd = 0;

}else{
}

}
radioSend(0xFFFF, 'c');
}


これはD用
//for D

serialInit(9600);
pinMode(0, true);
digitalWrite(0,true);
ain1 = analogRead(1);
radioInit(0xDDDD, 0, 11, 3);

var checka= 1;
var checkb= 1;
var checkc= 1;

while(true) {

function onRadioReceive(seq,src,pan,data,rss) {
if (data == 'a' && checka == 1){
serialSend("a"+"\r\n");
checka = 0;
checkb = 1;
checkc = 1;
}else if(data == 'b' && checkb == 1){
serialSend("b"+"\r\n");
checka = 1;
checkb = 0;
checkc = 1;

}else if(data == 'c' && checkd == 1){
serialSend("c"+"\r\n");
checka = 1;
checkb = 1;
checkc = 0;

}else{
}

}
radioSend(0xFFFF, 'd');
}


いまはmoxaが2台しかないので、aとbしか受け取っていないのですが、ターミナルから見てみるとこんな感じ。

2009年2月3日火曜日

Wi-portからHTTP POST

Wi-portからHTTP POSTすることを、ずいぶん試しているのですが出来ません。
作ったプロジェクトはこんなもの。


rails -d mysql posttest
プロジェクトを作った後は、modelを作ってstring型のnameとtext型のmessageというカラムを追加しました。
ruby script/generate model user
migrationファイル:XXXXXXXXX_create_users.rb
t.column :name, :string
t.column :message, :text


userというコントローラーを作り、index、new、destroy、createを追加。フォームも作って投稿出来るようにしました。

ruby script/generate controller user index new show create


user_controller
def index
@users = User.find(:all)
end

def create
@user = User.new(params[:user])#上のnewでの値を受け取っています。
if@user.save
redirect_to :action => 'index'
else
render :action => 'new'
end
end

def new
end

def destroy
@user = User.find(params[:id])
@user.destroy
flash[:notice] = '削除しました'
redirect_t


index.rhtml
<h1>Users#index</h1>

<div class ="notice"><%= h(flash[:notice])%></div>
<p><%= link_to('新規ユーザー作成', :action => 'new')%></p>


<% @users.each do |user| -%>
<li>
<%= link_to(h(user.name), :action => 'show', :id => user.id)%>
<%= link_to('削除', {:action => 'destroy', :id => user.id},
{:method => :post, :confirm => '本当に削除しますか?'})%>

</li>
<% end -%>

new.rhtml
<h1>Users#new#新しいユーザーを作る</h1>

<% form_for :user, @user,
:url=>{:action => 'create'} do |form| %>

<p>名前: <%=form.text_field :name, :size => 16 %> </p>
<p>メッセージ:<br /><%=form.text_area :message, :colse =>40, :rows => 3%> </p>

<p>
<%= form.submit 'Create' %>
</p>
<% end %>
<p><%= link_to('一覧へ戻る', :action => 'index') %></p>




ソースをのぞいてみると、

<h1>Users#new#新しいユーザーを作る</h1>

<form action="/user/create" method="post"><div style="margin:0;padding:
0"><input name="authenticity_token" type="hidden"
value="3459c27ed8923e8483d23bd0b4a8a870f248bc56" /></div>

<p>名前: <input id="user_name" name="user[name]" size="16"
type="text" /> </p>
<p>メッセージ:<br /><textarea cols="40" colse="40"
id="user_message" name="user[message]" rows="3"></textarea> </p>

<p>
<input id="user_submit" name="commit" type="submit" value="Create" />
</p>
</form>

<p><a href="/user">一覧へ戻る</a></p>

ここと
id="user_name" name="user[name]"
ここが
id="user_message" name="user[message]"
キモのようです。これを返せばいいんですよね、きっと。

wi-portでhttp postしてみましょう。
シリアル変換をしてtera termで
C192.168.0.111:3000
POST /user/create HTTP/1.1 ^M^J
HOST: 192.168.0.111:3000 ^M^J
user[name]=hoge&user[message]=hoge ^M^J

※Enterの代わりにCntrl + M, CntrlJ を打ちます。= [^M^J]
※Making Things Talk参照
しかし途中でdisconnectになってしまいます。
試しにコマンドプロンプトから

telnet 192.168.0.111 3000
POST /user/create HTTP/1.1
HOST: 192.168.0.111 3000
user[name]=hoge&user[message]=hoge

成功しません。サーバー側のステータスコードを見てみると、
Processing UserController#index (for 192.168.0.111 at 2009-02-03 20:38:01) [GET]
SQL (0.1ms) SET NAMES 'utf8'
SQL (0.1ms) SET SQL_AUTO_IS_NULL=0
User Load (0.7ms) SELECT * FROM `users`
Rendering user/index
User Columns (3.0ms) SHOW FIELDS FROM `users`
Completed in 69ms (View: 63, DB: 1) | 200 OK [http://192.168.0.111/user]

なぜか[GET]メソッドになっている。。。もうこればっかりやっていて、気が狂いそうになっていた所で、キョンちゃんがやってくれました。

POST /user/create HTTP/1.1 ^M^J
HOST: 192.168.0.111 ^M^J
Content-Type: application/x-wwwform-urlencoded


最後のContent-Typeを指定する文章を書き足すと、POSTが成功するようです。
しかし、
user[name]=hoge&user[message]=hoge

ここは送れないようです。[ ]を変換する必要があるのかな?