本文へジャンプ

ソフトウェア Lotus Lotus Developer Domain 製品別技術情報 Lotus Sametime  > 
   
 

バーチャルオフィス: IBM Lotus SametimeチャットとSecond Life: 第3回 Lotus Sametime と Second Life の連携

Sametimeボットを使用してSecond LifeとLotus Sametimeを橋渡しする

   
 
コンテンツ
IBM Lotus SametimeとSecond Lifeの連携
  この動作メカニズム
  サーブレットの作成
  ボットの開始
  Lotus Sametimeに話しかける -- ボット
  Lotus Sametimeに話しかける -- サーブレット
  Lotus Sametimeをリスニングする -- ボット
  Lotus Sametimeをリスニングする -- サーブレット
  Second Lifeに話しかける
  Second Lifeをリスニングする
  完成した製品
  今後の考慮事項
まとめ
ダウンロード
リソース
筆者について(原文のまま)
ご意見ご要望をお寄せ下さい
Nicholas Chase, Writer, Freelance

レベル:中級
原文の掲載:2007年5月11日
原文はこちら (US)

第2回は、基本的なボットと Second Lifeスクリプトの作成について説明しました。第3回は、Lotus Sametime と Second Life の連携方法をご説明します。


[編集者のメモ: この記事で取り上げたIBM Lotus SametimeとSecond Lifeの結合は、US環境以外での検証を行っていません。この記事は、US環境以外で動作を保障するものではありません。また、この記事は2007年5月時点の情報に基づき執筆しています。Second Lifeの最新情報は、Second Life Home Pageで、ご確認ください。]
Second Life Home Page(US)


IBM Lotus SametimeとSecond Lifeの連携

これまでに、双方の環境で話す方法と聞く方法を理解しました。それでは、相互に話しかけ、聞き取ることができるようにしましょう。

この動作メカニズム

Second LifeとIBM Lotus Sametimeはかなり異なる環境であるため、相互に会話をするには少し工夫した方法を使用する必要があります。基本的に、システムは図18のように構成されています。


図18. テキストの双方向への流れ

ユーザーがLotus Sametimeにテキストを入力すると、ボットはそれを受け取り、キューに保管します。Second Lifeは、15秒(または、設定した任意の間隔)ごとにサーブレット呼び出します。サーブレットはキュー内のテキストを返し、それをSecond Lifeウィンドウに表示します。

ユーザーがSecond Lifeでテキストを入力すると、スクリプトはサーブレットを呼び出し、メッセージをパラメーターとして送ります。サーブレットはこれをボットに送り、ボットはこのメッセージをSametimeウィンドウに表示します。

(これらはすべて、Second Life内から直接サーブレットを呼び出せることを前提としています。直接呼び出せない場合は、サーブレットをローカル・ホストで実行している場合でも動作を可能にするプロキシーがこのチュートリアルのサンプル・コードに含まれています。)

上に戻る

サーブレットの作成

サーブレットの作成から始めます。Rational Application Developerで、プロジェクトを右クリックし、「新規作成」->「サーブレット」を選択します。サーブレットの名前(例: BotServlet)を選択し、「終了」をクリックします。これで、基本的なサーブレットが作成されます(リスト9)。


リスト9. 基本的なサーブレット
                    
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

 public class BotServlet extends javax.servlet.http.HttpServlet 
                               implements javax.servlet.Servlet {

   public BotServlet() {
      super();
   }      
   
   protected void doGet(HttpServletRequest request, 
                      HttpServletResponse response) 
                          throws ServletException, IOException {

   }     
   
   protected void doPost(HttpServletRequest request, 
                       HttpServletResponse response) 
                          throws ServletException, IOException {

   }               
}
      

上に戻る

ボットの開始

ユーザーがボットと通信するには、ボットがログインしていなければなりません。これは、サーブレットがボットに話しかけるには、ボットのインスタンスがすでに存在している必要があることを意味します。このようにするには、サーブレットのインスタンス変数としてボットを作成します(リスト10参照)。


リスト10. ボットの開始
                    
...
 public class BotServlet extends javax.servlet.http.HttpServlet 
                               implements javax.servlet.Servlet {

   static SLBot theBot = null; 
       
   public BotServlet() {
      super();
      this.createBot();
    } 

   private void createBot(){
      theBot = new SLBot("stdemo3.dfw.ibm.com", 
                         "Chase Marellan", "abc123");
   }
   
   protected void doGet(HttpServletRequest request, 
...
      

サーブレットは、初めて実行されるときに、ボットの静的インスタンスを作成します。このインスタンスは、サーブレットに送られるすべての要求によって共有されます。これが、望んでいる動作です。

サーブレットを右クリックし、「サーバーで実行」を選択して実行すると、ブラウザー・ウィンドウには何も出力されませんが、アバターがLotus Sametimeにログインしている状態が表示されます(図19参照)。


図19. サーブレットを通じたLotus Sametimeへのログイン

オブジェクトが終了するまで、ボットはLotus Sametimeへのログイン状態を保ちます。サーバー・インスタンスを終了すると、ボットはログアウトします(図20参照)。


図20. サーバーの停止によるログアウト

それでは、ボットへ話しかけるところを見てみましょう。

上に戻る

Lotus Sametimeに話しかける -- ボット

最初にしなければならないことは、ボットがサーブレットからテキストを受信し、それをSametimeウィンドウに表示することです(リスト11参照)。


リスト11. テキストを受信する準備
                    
...
   Thread botThread;
     
   Im currentIM;
   
   public SLBot (String serverName, 
               String stUserId, String password) {

...

   public void imReceived(ImEvent e){

/*      e.getIm().addImListener(this); */

       currentIM = e.getIm();
       currentIM.addImListener(this);
       currentIM.sendText(true, "Standing by...");

   }
   
   public void textReceived(ImEvent e) {
      String theText = e.getText();
      e.getIm().sendText(true, 
                         "I heard you.  You said: '"+theText+"'.");
   }
   
   public void tellSametime(String message){
      currentIM.sendText(true, message);
   }
   
   public void imOpened(ImEvent e) {}
   ...
            

前の説明では、ボットは受信したメッセージに応答していました。これは、たいへん単純なものでした。しかし、特定のイベントへの応答ではない形で何かを話すには、現在のメッセージへの参照を保管し、何かを話すための「フック」を保持する必要があります。これを行うには、ウィンドウが最初に開くときに使用されるImオブジェクトに参照を保管します。

次に、ストリングを受け取り、そのオブジェクトを使用してストリングをウィンドウに送信する新しいメソッドtellSametime()を作成します。そして、この関数をサーブレットから呼び出します。

上に戻る

Lotus Sametimeに話しかける -- サーブレット

ボットがテキストを受信する準備ができたら、サーブレットのdoGet()メソッドからそれを呼び出すことができます(リスト12参照)。


リスト12. ボットへのテキストの送信
                    
...
   protected void doGet(HttpServletRequest request, 
                      HttpServletResponse response) 
                          throws ServletException, IOException {

      if (request.getParameter("message") != null){
         theBot.tellSametime(request.getParameter("message"));
      }
      
   }     
...
            

要求にメッセージ・パラメーターが含まれる場合、サーブレットはテキストを抽出し、それをtellSametime()メソッドに渡します。このメソッドはテキストをSametimeウィンドウに出力します。これは簡単にテストできます。まず、パラメーターなしでサーブレットを実行し、ボットを開始します。ボットのログイン後、新しいチャット・ウィンドウを開き、ブラウザーで
URL「http://localhost:8080/SLBotProject/BotServlet?message=Can+you+hear+me?」にアクセスします。

ウィンドウ内にテキストが表示されます(図21参照)。


図21. サーブレットからのテキスト

次に、もう一方の側を見てみましょう。

上に戻る

Lotus Sametimeをリスニングする -- ボット

Lotus Sametimeからテキストを外部に戻すには、テキストをキューに保管し、そのキューを取得する手段を提供する必要があります(リスト13参照)。


リスト13. キューのセットアップ
                    
...   
   Im currentIM;
    
   String chatQueue = "";
   
   public SLBot (String serverName, 
               String stUserId, String password) {

...
   public void textReceived(ImEvent e) {
      String theText = e.getText();
      if (!chatQueue.equals("")){
         chatQueue = chatQueue + "\n------\n";
      }
      chatQueue = chatQueue + theText;
   }
   
   public String getMessages(){
      String holdQueue = chatQueue;
      chatQueue = "";
      return holdQueue;
   }
   
   public void tellSametime(String message){
      currentIM.sendText(true, message);
   }
...
            

リストからわかるように、プロセスはあまり複雑ではありません。簡単に説明すると、ボットがテキストを受け取るたびに、それをストリング変数chatQueueに追加します。必要な場合は、区切り記号を追加します。サーブレットはgetMessages()メソッドを使用して、その変数を取得できます。

上に戻る

Lotus Sametimeをリスニングする -- サーブレット

ここでは、メッセージを取得するようサーブレットに指示します(リスト14参照)。


リスト14. メッセージの取得
                    
...
   protected void doGet(HttpServletRequest request, 
                      HttpServletResponse response) 
                          throws ServletException, IOException {

      if (request.getParameter("message") != null){
         theBot.tellSametime(request.getParameter("message"));
      }
      
        if (request.getParameter("getMessages") != null){
           response.getWriter().print(theBot.getMessages());
        }
      
   }     
...
            

要求にgetMessagesパラメーターが含まれている場合、サーブレットは単にgetMessages()メソッドの結果を出力します。これをテストするには、サーブレットを実行してログインし、チャット・ウィンドウを開き、テキストを追加します(図22参照)。


図22. テキストの追加

次に、ブラウザーでURL「http://localhost:8080/SLBotProject/BotServlet?getMessages」を開きます。

ブラウザー・ウィンドウにテキストが表示されます(図23参照)。


図23. Lotus Sametimeからのテキスト

ブラウザーを再ロードすると、テキストがまったく表示されなくなります。これは、キューが消去されるためです。複数のステートメントで自由にテストしてみてください。

上に戻る

Second Lifeに話しかける

Lotus Sametimeに話しかけ、その結果をサーブレットに保管できるようになったので、今度はSecond Lifeからサーブレットを呼び出して、テキストを取得できます(リスト15参照)。


リスト15. テキストの取得
                    
key http_request_id;
key listen_request_id;

default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
        llListen( 0, "", "", "");
        llSetTimerEvent(15);
    }

...

   timer(){
        
        listen_request_id = llHTTPRequest(
              "http://myserver/SLBotProject/BotServlet?getMessages", 
               [], "");

   }

    
    http_response(key request_id, integer status, 
                  list metadata, string body)
    {
        if (request_id == listen_request_id)
        {
            if (body != ""){
              llWhisper(0, body);
            }
        }

        if (request_id == http_request_id)
        {
              llSay(0, body);
        }
    }

}
            

スクリプト内のllSetTimerEvent()関数は、一定の間隔でtimer()関数を実行します。このケースでは、関数は単にサーブレットを呼び出し、それに固有の要求IDを割り当てます。次に、http_response()関数は、送られてきたすべての応答に対し要求IDをチェックし、一致した場合はそのテキストをささやき(whisper)ます。(ささやくことは話すことと同じですが、全体に伝えずによりプライバシーを保つ点が異なります。)このスクリプトをオブジェクトに追加すると、保管されたすべてのテキストが数秒以内にウィンドウに表示されます(図24参照)。


図24. キューからのメッセージ

これで、Sametimeウィンドウに追加したすべてのテキストが、Second Lifeの世界に約15以内に表示されます。もちろんこれは、私たちが慣れている瞬時の応答ではありませんが、何もないよりは良いでしょう。これよりも早くすると、プロセス内のいずれかのサーバーのパフォーマンスが著しく低下するおそれがあります。

上に戻る

Second Lifeをリスニングする

最後に、締めくくりとして、Second Lifeで入力されたすべてのテキストを自動的にサーブレットに送る必要があります(リスト16参照)。


リスト16. Lotus Sametimeへのテキストの送信
                    
key say_request_id;
key listen_request_id;

default
{
...
    listen( integer channel, string name, key id, string message ) 
    {
   
        say_request_id = llHTTPRequest(
         "http://myserver/SLBotProject/BotServlet?message="
                    + llEscapeURL(message), [], "");
   
    }
    
...
    http_response(key request_id, integer status, 
                  list metadata, string body)
    {
...

        if (request_id == say_request_id)
        {
              //llSay(0, body);
        }
    }

}
            

このケースでは、オブジェクトが何かを聞いたときにテスト呼び出しをセットアップするのではなく、テキストをサーブレットに送信することにします。この執筆時点では、Linden ScriptのllEscapeURL()関数はあまりうまく機能しませんでした。テキスト内のすべてのスペースを削除してしまい、1度に安全に処理できるのは14文字まででした。(次に記載されるプロキシー・ソリューションは、対策としてBase64エンコードを使用し、この問題を回避しています。動作については、ソース・コードで確認してください。)

このケースでは、応答が何であるかを気にする必要はありません。重要なのは要求だけなので、要求が返されたときに、出力を削除することができます。

Second Lifeからサーブレットにアクセスできる場合は、プロジェクトはこれで完了です。そうでない読者のために、2つのバージョンのサンプル・コードを用意しました。一方は、ここで説明したものとまったく同じスクリプトです。もう一方には、ボットをローカルで実行できるPHPプロキシー・スクリプトが含まれています。

上に戻る

完成した製品

これで、すべての作業が完了しました。テキストが双方向に流れるようすを見ることができます(図25参照)。


図25. 完成した製品


上に戻る

今後の考慮事項

これは、非常に「強引」な方法でものごとを実行しています。この方法では、誰が話しているか識別していませんし、複数の人がアバターと会話することも考慮していません。また、話しかけられるのを待つよりも、アバターの存在をチェックすると、より洗練された方法になります。このようにすると、誰かがオブジェクトのところに来たこと(お店に入るなど)を認識できます。これを行うには、Second Lifeスクリプトに関するJesse Dailyのチュートリアルを確認するとよいでしょう。センサーについてのディスカッションが含まれています(リンクは「リソース」を参照してください)。

また、単純な幾何学的形状以外の外観に見えるようオブジェクトをカスタマイズできます。さらに、オブジェクトの名前をLotus Sametimeに変更すると、少しわかりやすくなります。Second Lifeではほとんどの場合、制限があるとすれば、それは想像力の限界によるものです。

上に戻る

まとめ

このチュートリアルでは、リスニングおよびテキストの中継により会話を行うSametimeボットを作成することにより、IBM Lotus SametimeとSecond Lifeの会話を接続する方法を理解しました。そして、メッセージを受信し、出力するサーブレットを、この機能に結び付けました。最後に、Second Lifeに、オブジェクト)を作成し、チャットをlistenし、サーブレットを通じてボットに中継することを可能にしました。(このオブジェクトは、キューに残されたすべてのメッセージを定期的にチェックします。)

上に戻る

ダウンロード

説明 名前 サイズ ダウンロード方法
チュートリアルのソース・コード sourcecode.zip 6KB HTTP(US)
ダウンロード方法について (US)

上に戻る

リソース

学ぶ

製品およびテクノロジーの入手

議論する

上に戻る

筆者について(原文のまま)

Nicholas Chase has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of Site Dynamics Interactive Communications in Clearwater, Florida, and is the author of three books on Web development, including Java and XML From Scratch (Que) and the upcoming Primer Plus XML Programming (Sams).


上に戻る


上に戻る