1. class ArClienBase
- You need to connect a client to a server using blockingConnect() with the address for the server.
- Then you should add handlers to the client to receive information from the server (with addHandler(), request(), and requestOnce()).
- Then call run() or runAsync() (or loopOnce() if you really know what you're doing). You can also add a callback that will get called every cycle of the client.
- User and password information may be required by the server. For details on that see ArServerBase.
- The most important thing is the modification to blockingConnect(), it can now take a user and password argument and upon failure you'll want to check wasRejected() to determine whether the client couldn't find the server or if the user and password were rejected.
- Another relevant function is setServerKey() to set the key (string of text) we need to connect to the server.
- This class should be thread safe... The only thing you cannot do is call 'addHandler' or 'remHandler' from within a handler for that specific piece of data.
2. class ArClientHandlerConfig
Client handler for receiving and updating ArConfig data via ArNetworking.ArClientHandlerConfig processes the network packets that describe a robot's ArConfig. It also provides a means to save the modified configuration data to the robot server. This class is designed to work inconjunction with the ArServerHandlerConfig. See the server handler documentation for a complete description of the networking interface.
This class should be thread safe, with the exception of unThreadSafeGetConfig. (If you want to use this method, surround it with calls to lock() and unlock().) Note that you can't add callbacks or remove callbacks from within a callback function.
3. class ArConfig : public ArHasFileName
Stores configuration information which may be read to and from files or other sources
The configuration is a set of parameters (or config arguments), organized into sections. Parameters contain a key or name (a short string), a value (which may be one of several types), a priority (important, normal, or trivial to most users), a longer description, and a display hint which suggests what kind of UI control might be most appropriate for the parameter.
After adding a parameter to the configuration, its value may be changed. when the configuration is loaded or reloaded from a file. Various program modules may register callbacks to be notified when a shared global configuration (such as the static ArConfig object kept by the Aria class) is loaded or otherwise changed. Classes dealing with more specialized kinds of config files inherit from this one.
Important methods in this class are: addParam(), addProcessFileCB(), remProcessFileCB(), parseFile(), writeFile().Usually, configuration data are read from and written to a file using parseFile() and writeFile(), or are set by a remote client via ArNetworking. It is also possible to import configuration settings from an ArArgumentParser (which, for example, may contain a program's command line arguments) using useArgumentParser().
例程1:configClient.cpp
#include "Aria.h"
#include "ArNetworking.h"
ArClientBase *client; //define a class type pointer
ArClientHandlerConfig *configHandler;
bool done = false;
void gotConfig(void)
{
ArConfig *newConfig;//Stores configuration information
//which may be read to and from files or other sources
done = true;
configHandler->getConfig()->writeFile("configClient.txt");
newConfig = new ArConfig(*(configHandler->getConfig()));
newConfig->writeFile("configClientNew.txt");
}
int main(int argc, char **argv)
{
Aria::init();
ArGlobalFunctor gotConfigCB(&gotConfig);
std::string hostname;
client = new ArClientBase;// initialize a pointer
configHandler = new ArClientHandlerConfig(client);
configHandler->addGotConfigCB(&gotConfigCB);
ArArgumentParser parser(&argc, argv);
ArClientSimpleConnector clientConnector(&parser);
parser.loadDefaultArguments();
/* Check for -help, and unhandled arguments: */
if (!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
{
Aria::logOptions();
exit(0);
}
/* Connect our client object to the remote server: */
if (!clientConnector.connectClient(client))
{
exit(1);
}
client->setRobotName(client->getHost()); // include server hostname in log messages
configHandler->requestConfigFromServer();
client->runAsync();//Runs the client in its own thread
while (!done)
ArUtil::sleep(100);//Sleep for the given number of milliseconds
if (configHandler->canRequestDefaults())
{
configHandler->requestDefaultConfigFromServer();
while (!configHandler->haveGottenDefaults())
ArUtil::sleep(100);
printf("%d\n", configHandler->haveGottenDefaults());
configHandler->getDefaultConfig()->writeFile("configClientDefaults.txt");
printf("wrote defaults\n");
}
//在此处进行输出语句操作 运行client时并不会输出,这说明client提示语句的输出是另一种机制
Aria::exit(0);
}
例程2:configClientToServer.cpp
注意运行后两个程序输出的不同之处(如第二个无法使用-help命令),找到对应的命令行,通过添加修改相关命令,加深对此程序的理解。
#include "Aria.h"
#include "ArNetworking.h"
/*
Pass this a file to send to the server (should be made by configClient then modified).
Takes a file to send, and can take the host to send to too
*/
ArClientBase *client;
ArClientHandlerConfig *configHandler;
char *file;
void saveConfigSucceeded(void)
{
printf("HERE: Save config succeeded\n");
}
void saveConfigFailed(const char *str)
{
printf("HERE: Save config failed: %s\n", str);
}
void gotConfig(void)
{
char errorBuffer[1024];
ArConfig *newConfig;
if (!configHandler->getConfig()->parseFile(file, false, false, errorBuffer,
sizeof(errorBuffer)))
printf("Error loading file: %s\n", errorBuffer);
configHandler->saveConfigToServer();
client->loopOnce();
ArUtil::sleep(1000);
client->loopOnce();
ArUtil::sleep(1000);
client->disconnect();
Aria::shutdown();
exit(0);
}
int main(int argc, char **argv)
{
Aria::init();
//ArLog::init(ArLog::StdOut, ArLog::Verbose);
/*
This is a class for global functions. This ties a C style function
pointer into the functor class hierarchy as a convience. Code that
has a reference to this class and treat it as an ArFunctor can use
it like any other functor.
*/
ArGlobalFunctor gotConfigCB(&gotConfig);
ArGlobalFunctor saveConfigSucceededCB(&saveConfigSucceeded);
ArGlobalFunctor1<const char *> saveConfigFailedCB(&saveConfigFailed);
std::string hostname;
client = new ArClientBase;
configHandler = new ArClientHandlerConfig(client, true);
configHandler->addGotConfigCB(&gotConfigCB);
configHandler->addSaveConfigSucceededCB(&saveConfigSucceededCB);
configHandler->addSaveConfigFailedCB(&saveConfigFailedCB);
if (argc == 1)
{
printf("Usage: %s <file> <host>\n", argv[0]);
exit(1);
}
file = argv[1];
if (argc == 2)
hostname = "localhost";
else
hostname = argv[2];
if (!client->blockingConnect(hostname.c_str(), 7272))
{
printf("Could not connect server, exiting\n");
exit(1);
}
//client->requestOnce("setConfig");
configHandler->requestConfigFromServer();
//client->requestOnce("setConfig");
client->run();
return 0;
}
例程3:ClientCommandLister.cpp
#include "Aria.h"
#include "ArNetworking.h"
int main(int argc, char **argv)
{
Aria::init();
ArLog::init(ArLog::StdOut, ArLog::Normal);
ArClientBase client;
ArArgumentParser parser(&argc, argv);
/*
simpleconnector中的函数执行后大都返回bool值顺便用来判断是否连接成功
*/
ArClientSimpleConnector clientConnector(&parser);//通过parser中的myHost参数传递ip值用于判断
parser.loadDefaultArguments();
//parseArgs()负责检测输入的-host等参数,检测到返回true
if (!clientConnector.parseArgs() || !parser.checkHelpAndWarnUnparsed())
{
clientConnector.logOptions();
exit(0);
}
if (!clientConnector.connectClient(&client))
{
if (client.wasRejected())
printf("Server '%s' rejected connection, exiting\n", client.getHost());
else
printf("Could not connect to server '%s', exiting\n", client.getHost());
exit(1);
}
client.setRobotName(client.getHost()); // include server hostname in log messages
client.runAsync();
ArUtil::sleep(500);
client.logDataList();// Print out data with descriptions
Aria::shutdown();
return 0;
}