本文へジャンプ

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

バーチャルオフィス: IBM Lotus SametimeチャットとSecond Life: 第2回 基本的なボットと Second Lifeスクリプトの作成

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

   
 
コンテンツ
基本的なボット
基本的なSecond Lifeスクリプト
ダウンロード
リソース
筆者について(原文のまま)
ご意見ご要望をお寄せ下さい
Nicholas Chase, Writer, Freelance

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

第1回は、チュートリアルをはじめるための手順を説明しました。第2回は、基本的なボットと 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とプログラマチックに対話するために、ボットを作成する必要があります。このボットは1つのJavaクラスで、送られてきたチャット・メッセージなどのさまざまなイベントをlistenし、それに合わせて応答します。

ボット・クラスの作成

以下のコードを入力し、SLBotandという新しいクラスを作成します(リスト1参照)。


リスト1. 基本クラス
                    
import com.lotus.sametime.awareness.*;
import com.lotus.sametime.community.*;
import com.lotus.sametime.core.comparch.*;
import com.lotus.sametime.core.constants.*;
import com.lotus.sametime.im.*;

public class SLBot implements Runnable, 
     LoginListener, ImServiceListener, ImListener  {

   public void run() {}
   public void loggedIn(LoginEvent e) {}
   public void imReceived(ImEvent e){}
   public void textReceived(ImEvent e) {}
   public void imOpened(ImEvent e) {}
   public void imClosed(ImEvent e) {}
   public void dataReceived(ImEvent e) {}
   public void openImFailed(ImEvent e) {}
   public void loggedOut(LoginEvent e) {}

   public static void main(String[] args) {
   }

}
      

ボットはいくつかの要件を実行しなければならないので(たとえば、ログ・イベントおよびインスタント・メッセージングのlistenなど)、4つの異なるインターフェースをインプリメントします。これを行うために、完成したプロジェクトは一部のメソッドしか使用しませんが、必要なすべてのメソッドを含める必要があります。

上に戻る

Lotus Sametimeへのボットのログイン

それでは、実際に何かを行うボットを作成しましょう。最初に必要なことは、Lotus Sametimeにログインすることです(リスト2参照)。


リスト2. Lotus Sametimeへのログイン
                    
...
public class SLBot implements Runnable, 
            LoginListener, ImServiceListener, ImListener  {

   STSession sametimeSession;
   CommunityService communityService;
   
   public SLBot (String serverName, 
               String stUserId, String password) {

      try {        
            sametimeSession = new STSession("SLSession");        
      } catch (DuplicateObjectException e) {        
            e.printStackTrace();
            return;        
      }

      sametimeSession.loadSemanticComponents();    
      sametimeSession.start();            
         
      STCompApi sametimeCompApi = 
          sametimeSession.getCompApi(CommunityService.COMP_NAME);
      communityService = (CommunityService)sametimeCompApi;
      
      communityService.addLoginListener(this);
      communityService.loginByPassword(serverName, userId, password);

   }

   public void close(){
      communityService.logout();
      sametimeSession.stop();
   }

   public void run() {}
   ...
   public void loggedOut(LoginEvent e) {}
   
   public static void main(String[] args) {

       SLBot theBot = new SLBot("stdemo3.dfw.ibm.com", 
                              "Chase Marellan", "abc123");
       
       try {
          Thread.sleep(30000);
       } catch (Exception e){
          e.printStackTrace();
       }
       
       theBot.close();   
   
   }

}
      

詳細に入る前に、行われることの概要を知るために、一番下のmain()メソッドから始めましょう。まず、ボットの新しいインスタンスを作成します。このとき、サーバー名、ユーザー名、およびパスワードを提供しますが、簡単にハード・コーディングしたり、パラメーターとして渡したりといった方法でこれを行うことができます。

インスタンスの生成後、ボットはこの情報を使用してサーバーにログインします。この状態から、アプリケーションは30秒間待つだけで、セッションを閉じます。

一番上に戻ります。さまざまなメソッドでCommunityServiceオブジェクト(一般)およびSTSessionオブジェクト(特定)を参照する必要があるので、これらをメンバー変数として作成します。

コンストラクターに移ります。まず、セッション自体を作成し、ストリング識別子を割り当てます。この識別子は完全に任意で、重複を作成しないために用いられます。セッションを得た後は、UI以外の(つまり、セマンティックな)すべてのコンポーネントをロードし、セッションを開始します。

次に、このセッションを使用してCommunityServiceAPIをロードし、前に宣言したcommunityServiceオブジェクトにこれを割り当てます。CommunityServiceを使用して、このクラスがログイン関連のイベントをlistenするよう指定し、ログイン・プロセスを開始します。必要であれば、loggedIn()メソッドを使用して、ボットのログインが成功したときに実行する何らかのアクションを指定できます。しかし、ここではもっと簡単な方法でそれを実行します。

最後に、ボットを閉じる時間になったら、サーバーからログアウトし(CommunityService)、セッションを停止します。

これを実行してみるには、自分自身がLotus Sametimeにログインしていることを確認します。2番目のユーザーは、ログインしていないなのでグレー表示になっています。アプリケーションを実行した数秒後、この表示が突然緑色の太字に変わります(図8参照)。


図8. 他のユーザーのログイン

これは、ユーザーがログインし、チャット可能であることを示します。しかし、30秒後、アプリケーションはこのユーザーをログアウトするので、表示は元の状態に戻ります。

上に戻る

ボットの実行

ここまではうまくいきましたが、もちろん、アプリケーションを30秒よりも長く実行する必要があります。実際には、無期限に実行させなければなりません。ここで、実行用のインプリメンテーションを行います(リスト3参照)。


リスト3. スレッドでのアプリケーションの実行
                    
...
   CommunityService communityService;
    
   Thread botThread;
   
   public SLBot (String serverName, 
               String stUserId, String password) {

      ...
      communityService.loginByPassword(serverName, stUserId, password);

      this.start();
      
   }

   public void start() {
      if (botThread == null) { 
           botThread = new Thread(this, "SLBotThread");
           botThread.start();
      }
   }
   
   public void close(){
      communityService.logout();
      sametimeSession.stop();
   }

   public void run() {
      
      Thread current = Thread.currentThread();
      while (botThread == current){
         try {
            Thread.sleep(1000);
         } catch (InterruptedException e){
            //Do nothing, this is just the program ending.
         }
      }
   }
   
   public void loggedIn(LoginEvent e) {}
...
 
   public static void main(String[] args) {

       SLBot theBot = new SLBot("stdemo3.dfw.ibm.com", 
                              "Chase Marellan", "abc123");
          
   }

}
      

最初に、Threadを宣言し、クラス全体から参照できるようにします。これは、start()メソッドを通じてスレッドを開始させるコンストラクターそのものです。

start()メソッドはThreadが作成されているかどうかをチェックします。作成されていない場合は、新規スレッドを作成し、開始します。もちろん、これは何かを実行しなければならないことを意味します。つまり、run()メソッドをインプリメントすることが必要です。このメソッドは、スレッドがまだ存在しているかチェックします。スレッドが存在する限り、メソッドは単に1秒待ち、もう一度チェックします。

最後に、アプリケーションを永続的に実行するために、一時停止およびclose()の参照をmain()メソッドから削除します。

これで、アプリケーションを実行すると、アバターはもう一度Lotus Sametimeにログインします。今回はアプリケーションを終了するまで、アバターはログイン状態を保ちます。

上に戻る

会話の開始

これでボットがログインしたので、誰かがボットに話しかけたときに、それを認識する必要があります(リスト4参照)。


リスト4. 会話の開始の認識
                    
...
   public void loggedIn(LoginEvent e) {

      STCompApi imServiceApi = SametimeSession
                  .getCompApi(InstantMessagingService.COMP_NAME); 

      InstantMessagingService instantMessagingService;
      instantMessagingService = (InstantMessagingService)imServiceApi;
      instantMessagingService.registerImType(ImTypes.IM_TYPE_CHAT);
      instantMessagingService.addImServiceListener(this);      

   }

   public void imReceived(ImEvent e){
      e.getIm().addImListener(this);
      e.getIm().sendText(true, "Standing by...");
   }
...
      

誰かに話しかけられたことを認識するには、ボットはInstantMessagingServiceに注意を払っている必要があります。これは、CommunityServiceを作成したときと同じ方法でセッションから作成されます。オブジェクトを取得したら、チャット・イベントを探していることを知らせ、アプリケーションをリスナーとしてそれらのイベントに追加します。

これが完了すると、誰かがボットとのチャット・ウィンドウを開くたびにアプリケーションはimReceived()メソッドを実行します。このメソッドはアプリケーションに対し、そのウィンドウからのインスタント・メッセージングをlistenし、そのウィンドウに単純な応答を送信するよう指示します。(sandTags()メソッドの最初のパラメーターは、転送中のメッセージを暗号化するようボットに指示します。)

このアクションは簡単に見ることができます。アプリケーションを実行し、Sametimeウィンドウに注目します。ボットがログインしたら、ボットをダブルクリックしてチャット・ウィンドウを開きます。図9に示すような応答が表示されます。


図9. 新規チャットへの応答

ここまでは、うまくいきました。すべてが順調であることの具体的な兆候が初めて得られました。

上に戻る

メッセージの受信

実際にメッセージを受信したときに何を行うのかも、ボットに指示する必要があります(リスト5参照)。


リスト5. メッセージの受信
                    
...
   public void textReceived(ImEvent e) {
      String theText = e.getText();
      e.getIm().sendText(true, 
                         "I heard you.  You said: '"+theText+"'.");
   }
...
      

テキストの受信は、大変直接的です。ボットはメッセージを受信したことを認識すると、textReceived()メソッドを実行します。この例では、このハンドラー・メソッドによって受信されたイベントの一部であるテキストをエコーし、ユーザーに返します(図10参照)。


図10. テキストのエコー・バック

これで、ボットと対話できるようになったので、等式のもう一方の側の構築を開始しましょう。

上に戻る

基本的なSecond Lifeスクリプト

Second Lifeでは、スクリプトの作成を楽しめます。Second Life内の人々が話することをlistenし、HTTP要求を作成するスクリプトを作ることから始めます。後で、この要求を使用してLotus Sametimeに話しかけます。

このセクションを始める前に、Second Lifeにログインし、オブジェクトを構築できる場所にいることを確認してください。

オブジェクトの作成

Second Lifeでは、すべてのオブジェクトは1つ以上のプリム(プリミティブ)でできています。プリミティブは、円柱や立方体などの単純な幾何学的形状です。実際のアプリケーションでは、複数のプリム、色、捻り、陰影、テクスチャー、およびさまざまな種類の美的要素を含むオブジェクトを作成します。しかし、今回必要となるのはプリムそのものです。外観の変更については、読者の好みにお任せします。

それでは始めましょう。地面を右クリックし、パイ・メニューから「Create」を選択します(図11参照)。


図11. 新しいオブジェクトの作成

ポップアップした情報ウィンドウで、クリックによって形状を選択します。次に、そのオブジェクトを表示する地面をクリックします(図12参照)。


図12. 形状の選択

地面にオブジェクトを配置すると、情報ウィンドウが拡張されます。拡張されない場合は、「More >」ボタンをクリックします。次に、「Content」タブをクリックします。ここに、新しいスクリプトを入力します。「New Script」ボタンをクリックします。Contentsフォルダーに、新しいスクリプトが作成されます(図13参照)。


図13. 新しいスクリプトの作成

このスクリプトをダブルクリックして、エディター・ウィンドウを開きます。どのオブジェクトにも提供される初期スクリプトが表示されます(リスト6参照)。


リスト6. 初期Lindenスクリプト
                    
default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
    }

    touch_start(integer total_number)
    {
        llSay(0, "Touched.");
    }
}
      

このコードは、Second Lifeの言語であるLinden Scriptで書かれています。(実際に、Rational Application Developerおよび他のEclipseベースのIDE用のLinden Scriptエディターを入手できます。この方法のチュートリアルについては、「リソース」セクションを参照してください。)

Linden Scriptは、状態の概念に基づいています。オブジェクトは、使用中、収納、売却、未売却など、さまざまな状態に分類されます。これは、非常に強力なメカニズムですが、ここで本当に必要なのはデフォルトの状態です。

任意の状態に入る前に(この場合は、デフォルトの状態)、オブジェクトはその状態のstate_entry()関数を実行します。このケースでは、関数はオブジェクトに単に「hello」と言うように指示します。ユーザーがオブジェクトにタッチすると、オブジェクトはユーザーがタッチしたと言います。このアクションを見るために、スクリプト・ウィンドウと情報ウィンドウを閉じます。オブジェクトはすでに作成されていて、その最初の「Hello, Avatar!」というメッセージが表示されます。どのようなケースでも、オブジェクトをクリックする、つまりタッチすると、そのやりとりを認識するチャット・メッセージが表示されます(図14参照)。


図14. タッチへの応答

しかし、人々が話すのを聞いて応答するには、どのようにすればよいのでしょうか。

上に戻る

会話の聞き取り

音声による対話は近々Second Lifeに装備される予定ですが、現在Second Lifeの人々は、Sametimeチャットのように、単純なチャット・メカニズムを使用して相互に話しかけます。オブジェクトにlistenさせたいのは、これらの対話です。

No spying!
Although it's not mentioned in the Second Life Terms of Service, Second Life's Community Standards require you to respect resident privacy. In a production application, you'd want to require the user to click the object or take some other definitive action so you're not just spying on random conversations. The code download includes a Linden Script example of how to accomplish this task.

スクリプト・エディターに戻るために、オブジェクトを右クリックし、「Edit」を選択します。情報ウィンドウがポップアップしたら、必要であれば「More>>」をクリックし、「Content」をクリックします。次に、New Scriptファイルをダブルクリックし、エディターを開きます。

チャット・メッセージのリスニングは直接的です(リスト7参照)。


リスト7. チャット・メッセージのリスニング
                    
default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
        llListen(0, "", "", "");
    }

    touch_start(integer total_number)
    {
        llSay(0, "Touched.");
    }
    
    listen(integer channel, string name, key id, string message) 
    {
        llSay(0, "I heard something: " + message);
    }

}
      

llListen()関数は、スクリプトにチャット・メッセージをlistenするよう指示します。パブリック・メッセージ(アバターの会話)はチャネル0で発生するので、このチャネルを listenします。他のパラメーターによって、誰が話しているかに基づいて入力をフィルターできます。たとえば、オブジェクトの所有者だけをlistenすることができます。しかし、ここではすべてをlistenします。

オブジェクトが聞き取れる範囲内でアバターが何かを話すと、listen()関数が起動され、メッセージを反復して返します。このアクションを表示するには、スクリプトを保存し、ウィンドウを閉じます。そして、オブジェクトに向かって何か言います(図15参照)。


図15. リスニングしているオブジェクト


HTTP呼び出しの作成

これで、メッセージの受信方法はわかりましたが、どのような方法でメッセージをLotus Sametimeに送信するのでしょうか。最終的に、サーブレットへのHTTP呼び出しを作成することによってこれを行うので、このプロセスがどのように動作するのかを簡単に見ておきましょう。

まず、テストに使用するWebアクセス可能なテキスト・ファイルを作成します。あるいは、筆者が作成したファイル(http://www.nicholaschase.com/botQueue/testCall.txt)を使用することもできます。ブラウザーでこのファイルを呼び出すと、簡単なテキストが表示されます(図16参照)。
http://www.nicholaschase.com/botQueue/testCall.txt (US)

図16. テスト・ファイル

Linden Scriptを使用してこの情報を取得する方法をリスト8に示します。


リスト8. 呼び出しの作成
                    
key http_request_id;

default
{
    ...
    listen( integer channel, string name, key id, string message ) 
    {
   
        llSay(0, "I heard something: " + message);
        http_request_id = llHTTPRequest(
           "http://www.nicholaschase.com/botQueue/testCall.txt", 
           [], "");
   
    }
    
    http_response(key request_id, integer status, 
                  list metadata, string body)
    {
        if (request_id == http_request_id)
        {
              llSay(0, body);
        }
    }

}
      

Linden Scriptはイベント・ベースであることを思い出してください。この例では、オブジェクトが何かを聞くと、HTTP要求を送り出します。(パラメーターはURL、URL用の任意のパラメーター、および要求の本文を表すため、llHTTPRequest()を使用して、GETrequestsではなく、POSTrequestsを送信することも可能です。しかし、ここではそれを練習として残しておきます。)

この変数にIDを割り当て、グローバル宣言変数http_request_idに保管します。応答が返ってくると、http_response()関数によってそれが処理されます。応答のIDが、待っていた応答IDに一致すると、スクリプトはHTTP応答の本文を出力します。

このケースでは、HTTP応答は「Yes, I can hear you」という単純なテキストです(図16参照)。

このため、フローは次のようになります。アバターは何か言い、オブジェクトはこれを聞き取ります。オブジェクトはこのチャット・メッセージを反復し、URLへの呼び出しを行います。応答が返ってきたら、応答をウィンドウに出力します(図17参照)。


図17. HTTP要求の受信

ここでは、URLのコンテンツはたまたま単純な1行の文でした。しかし、どのようなHTMLが提供されても、それは未加工の(そのままの)形式で表示されます。

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

上に戻る

ダウンロード

説明 名前 サイズ ダウンロード方法
チュートリアルのソース・コード 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).


上に戻る


上に戻る