Up:[[Tutorial]] Previous:[[サービスプロバイダの作成]] Next:[[画像、距離センサデータ取得]]
----
#contents
*メッセージ送受信 [#zc25bba0]
※このチュートリアルはSIGVerse v2.1.0以降対応です。
前回のメッセージ送信(sendMsg)はサーバを介してコントローラにメッセージを送信しました。
サービスプロバイダはサーバを介さず直接コントローラへメッセージを送信することもできます。
//ここではコントローラとサービスプロバイダがサーバを介さずにメッセージを送受信するサンプルを紹介します。
**コントローラサンプル [#z5f5cfa5]
まずサーバ側でコントローラを作成します。
ServiceTest.cpp
#highlight(cpp){{
#include <string>
#include "Controller.h"
#include "Logger.h"
#include "ControllerEvent.h"
#define PI 3.141592
#define DEG2RAD(DEG) ( (PI) * (DEG) / 180.0 )
using namespace std;
class AgentController : public Controller
{
public:
double onAction(ActionEvent &evt);
void onRecvMsg(RecvMsgEvent &evt);
void onInit(InitEvent &evt);
private:
BaseService *m_srv;
};
void AgentController::onInit(InitEvent &evt)
{
m_srv = NULL;
SimObj *my = getObj(myname());
}
double AgentController::onAction(ActionEvent &evt)
{
if(m_srv == NULL){
// サービスが使用可能かチェックする
bool available = checkService("MyService");
if(available){
// サービスプロバイダに接続
m_srv = connectToService("MyService");
}
}
else{
// サービスプロバイダにメッセージを送信します
m_srv->sendMsgToSrv("Hello");
}
return 1.0;
}
void AgentController::onRecvMsg(RecvMsgEvent &evt)
{
// メッセージ送信元とメッセージを取得します
std::string sender = evt.getSender();
std::string msg = evt.getMsg();
LOG_MSG(("[%s] %s", sender.c_str(), msg.c_str()));
}
extern "C" Controller * createController ()
{
return new AgentController;
}
}}
関数connectToServiceでサービスプロバイダ"MyService"に接続します。
これによりSIGVerseサーバを介さずにコントローラとサービスプロバイダで直接データの送受信を行うことができるようになります。
サービスプロバイダとの接続が完了すると関数sendMsgToSrvでサービスプロバイダ"MyService"にメッセージを送信します。
コントローラはコンパイルしておきます。
$ ./sigmake.sh ServiceTest.cpp
**世界ファイル [#e544b184]
ロボットだけが登場する世界ファイルを作成します。
ServiceTest.xml
#highlight(xml){{
<?xml version="1.0" encoding="utf8"?>
<world name="myworld">
<gravity x="0.0" y="-9.8" z="0.0"/>
<instanciate class="Robot-nii.xml">
<set-attr-value name="name" value="robot_000"/>
<set-attr-value name="implementation"
value="./ServiceTest.so"/>
<set-attr-value name="language" value="c++"/>
<set-attr-value name="dynamics" value="false"/>
<set-attr-value name="x" value="0.0"/>
<set-attr-value name="y" value="65.0"/>
<set-attr-value name="z" value="0.0"/>
</instanciate>
</world>
}}
**サービスサンプル [#d1d0956b]
次にサービスプロバイダのサンプルです。
クライアント側で前回([[サービスプロバイダの作成]])と同じようにVC++2008で新しくプロジェクトを作成し、コードを以下のようにします。
MyService.cpp
#highlight(cpp){{
//#include "stdafx.h"
#include "SIGService.h"
#include <tchar.h>
#include <string>
// SIGServiceを継承したクラスを作成します
class MyService : public sigverse::SIGService
{
public:
MyService(std::string name) : SIGService(name){};
~MyService();
// メッセージ受信時に呼び出される関数
void onRecvMsg(sigverse::RecvMsgEvent &evt);
// 定期的に呼び出される関数
double onAction();
};
MyService::~MyService()
{
// 切断します
this->disconnect();
}
double MyService::onAction()
{
return 1.0;
}
void MyService::onRecvMsg(sigverse::RecvMsgEvent &evt)
{
// メッセージ送信元とメッセージを取得します
std::string sender = evt.getSender();
std::string msg = evt.getMsg();
// メッセージが"Hello"だった場合コントローラにメッセージを返します
if(msg == "Hello") {
this->sendMsgToCtr(sender, "Hello! this is MyService");
}
}
int main(int argc, char** argv)
{
// クラスMyServiceのインスタンスを作成します
MyService srv("MyService");
// unsigned short port = (unsigned short)(atoi(argv[2]));
// srv.connect(argv[1], port);
// サーバに接続します
srv.connect("hostname", <portnum>);
// メインループをスタートさせます
srv.startLoop();
return 0;
}
}}
サーバ接続時の"hostname"と<portnum>は自分の環境に合わせて置き換えてください。
このサービスプロバイダは常にコントローラからのメッセージを受け付けます。
そしてコントローラから"Hello"というメッセージが届くと"Hello! this is MyService"というメッセージをコントローラに返します。
sendMsgToCtrという関数を使うことによりSIGVerseサーバを介さずに直接コントローラにメッセージを送信することができます。
**実行 [#q3f9c3c1]
まずSIGVerseサーバを起動します。
$ sigserver.sh -p 9001 -w ./ServiceTest.xml
次にビューワーでシグバースサーバに接続します。シミュレーションを開始し、MyServiceを起動します。
サーバ側で
[SYS] Service: "MyService" is available
と表示されればサービスプロバイダ立ち上げ成功です。
次に"START"ボタンを押してシミュレーションを開始します。
サーバ側で一秒に一回
[MSG] robot_000(0.0.0.0) [MyService] Hello! this is MyService
と表示されれば成功です。
#highlight(end)
*Old Version [#o6a325a7]
- [[メッセージ送受信(v2.0系)]]
-----
Up:[[Tutorial]] Previous:[[サービスプロバイダの作成]] Next:[[画像、距離センサデータ取得]]
#counter