Shuichi Machida's Weblog

« [NetBeans 独り言] sout... | メイン | [Sun SPOT Demo(5)]... »

http://blogs.sun.com/machida/date/20080318 2008年 3月 18日 火曜日

[Sun SPOT Demo(4)] Isolate migration: 演奏中の音楽(Melody) を Sun SPOT間で移動させてみる。

Sun SPOTにスピーカーもつながりましたので、今回はスピーカーとトーンジェネレータ、そしてSun SPOTに(実験的に)実装されているアイソレットマイグレーションという機能を使って簡単なデモを作ってみます。

# アイソレットについてはこちらでも少し触れています

アイソレットマイグレーションを使うと、一つのVM(Sun SPOT)上で実行中のアイソレット(アプリケーション)を別のVMに移動して、実行を継続させることができます。今回は、メロディを演奏するアイソレットと、それをSun SPOT間で移動させるプログラムを作成します。

。。。

プログラム作成中、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

、、、、

。。。

完成 ;-)

。。。

下が、完成したデモの外観です。

# 言うまでもないですが音符と矢印はハメコミです。

 

Sun SPOTの左側のスイッチで演奏の開始・終了、右側のスイッチでアイソレットの移動開始を指定します。メロディーはもちろん、先日草薙さんに伝授して頂いたポルッカです。

演奏の途中で右ボタンをポチッと押すと、、、

。。。

左側のスピーカーで鳴ってたメロディーが中断して、15秒ぐらい後に、右側のスピーカーで中断した所から鳴り始めました ;-)

# アイソレットの転送が微妙に遅っ。通信速度がMAX 250Kbps で、しかも同じチャネルでブロードキャストパケット飛ばしてるので仕方ないのかも。。シリアライズされたアイソレットって意外にサイズ大きいのか。。今度調べてみよう。

今回作ったプログラムは、バックグラウンドで定期的(3秒後)にブロードキャストパケットを飛ばしてお互いの存在を通知しあったり、複数のSun SPOTがある場合にアイソレットの転送先を決定するアルゴリズムを実装したり(今のところ単に、最も近い?(受信電波強度の強い)Sun SPOTに転送するように実装してます)、転送時の事前ネゴシエーションのためのプロトコルを実装したり、、、、と結構コードを書いており複雑になっていますので、以下ではアイソレットAPIを使う部分のソースコードの概略をご紹介します(例外処理などは省略しています)。

アイソレットを開始する部分のソースコードは以下のようになります。第一引数で、アイソレットとして実行したいクラスの名前を指定します。

 ...
// アイソレットとして実行するクラス
String classname = "org.sunspotworld.demo.isolate.MelodyPlayer";

// アイソレットの生成
Isolate isolate = new Isolate(classname,
    new String[0], null, VM.getCurrentIsolate().getParentSuiteSourceURI());
// アイソレットの実行
isolate.start();  
...

アイソレットとして実行するクラスは、main メソッドを持つ必要があります。

 
// アイソレットとして実行するクラス(mainメソッドを持つ)

package org.sunspotworld.demo.isolate;
import com.sun.spot.util.Utils;

public class MelodyPlayer {
    public static void main(String[] args) {
        while (true) {
            // ここにトーンジェネレータを使ってメロディーを演奏する
            // コードを実装
        }
    }
}

アイソレットを送信する際には、コネクション型のRadiostreamプロトコルを使って宛先のSun SPOTに対するコネクションをオープンします。アイソレットは送信前に休眠(hibernate)させます。

 // アイソレットの送信側
....

// 宛先のアドレス、ポート番号、使用するプロトコル
String targetAddr = "<address>";     // 例: "0014:4F01:0000:0002"
int portNumber = 220;
String url = "radiostream://" + targetAddr + ":" + portNumber;

// 宛先Sun SPOTへのコネクションをオープンする
StreamConnection conn = (StreamConnection)Connector.open(url);
DataOutputStream dos = conn.openDataOutputStream();

// アイソレットを休眠させ、宛先に送信する
isolate.hibernate();
isolate.save(dos, VM.getCurrentIsolate().getParentSuiteSourceURI());
...

アイソレットの受信側でも、送信元Sun SPOTのアドレスを指定してコネクションをオープンします。ここではお互いのアドレスを直に指定していますが、事前にお互いを知らない Sun SPOT間で双方向コネクションを張るためには、先にブロードキャストでお互いのアドレスを交換するなどの実装が必要になります。アイソレットを受け取ったら、叩き起こ(unhibernate)せば再び動き出します。

 // アイソレットの受信側
...

// 送信元 のアドレス、ポート番号、使用するプロトコル
String targetAddr = "<address>";      // 例: "0014:4F01:0000:0001"
int portNumber = 220;
String url = "radiostream://" + targetAddr + ":" + portNumber;

// 送信元 Sun SPOT へのコネクションをオープンする
StreamConnection conn = (StreamConnection)Connector.open(url);
DataInputStream dis = conn.openDataInputStream();

// アイソレットを受け取り、叩き起こす
Isolate isolate = Isolate.load(dis, "" );
isolate.unhibernate();
...

アイソレットについては、

などで、サンプルコードを含めた有益な情報が得られます。

投稿されたコメント:

コメント
  • HTML文法 不許可

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.