The lgrControl example demonstrates how to use the Logger Remote Control API to control one or more Loggers from a remote application.
In this case, it provides a console interface to send commands to the remote Loggers.
The Logger control example provides a console based interface to send commands to one or more loggers using the remote control interface. It provides commands for most of the common logger features such as load/play/pause/stop/change speed/close a tape and similar commands for record as well as others. A list of the commands along with the parameters and a description can be printed to the console using the command "help."
The console will accept partial strings for the command tokens, so "h" is acceptable for "help" (first match is chosen). Alternatively, the command ID can be used instead of the token. The "<" and ">" keys will cycle through the command history and restore the commands to the prompt. The command "restoreCmd <int>" will restore a specific command to the prompt.
Required parameters are designated with angle brackets containing the data type and an indication of its purpose or unit (e.g. <seconds(float)> or <overwrite(1/0)>. Optional parameters are designated with square brackets. Curly brackets indicate an enumerated list of values where one of the numeric values must be selected (e.g., {RECORD=2, STOP=3, EMPTY=4}). The term "N/A" indicates that the command requires no parameters. Here is an example of the list of commands (subject to change and differs by protocol).
Enter command token (or ID) with arguments then press Enter key.
#include <vl/exerciseConnInitializer.h>
#include <vlutil/vlPrint.h>
#include <vlutil/vlInetUdpSocket.h>
#include <vlutil/vlRtiMismatchException.h>
#include <vlutil/vlMiniDumper.h>
#include <mtl/mtlEnvironment.h>
using namespace MAKLogger;
char* getToken( char** nextp, const char* sep );
void printHelp();
int tokenToCommandId(
DtString commandString ) ;
DtEntityIdentifier parseEntityIdentifier(const char* buffer);
enum DtRemoteControlId
{
DtRcInvalid = -1,
DtRcQuit = 0,
DtRcLoadPlayback = 1,
DtRcLoadRecord = 2,
DtRcUnload = 3,
DtRcPlay = 4,
DtRcPause = 5,
DtRcStop = 6,
DtRcRewind = 7,
DtRcUnwind = 8,
DtRcRecord = 9,
DtRcSetscale = 10,
DtRcJumpTime = 11,
DtRcSkipTime = 12,
DtRcSetplayAction = 13,
DtRcSetRecordAction = 14,
DtRcSetEofAction = 15,
DtRcDeleteFile = 16,
DtRcToggleFlag = 17,
DtRcSetHeartBeat = 18,
DtRcSetTimeout = 19,
DtRcShutdown = 20,
DtRcSetDestination = 21,
DtRcSetOrigination = 22,
DtRcLoadSubFile = 23,
DtRcRequestFileList = 24,
DtRcInfo = 96,
DtRcConfig = 97,
DtRcPrintHistory = 98,
DtRcRestoreCmd = 99,
DtRcHelp = 100
};
struct DtRcToken
{
DtRemoteControlId id;
const char* token;
const char* paramStr;
const char* helpStr;
};
DtRcToken theCommandTokens[] =
{
{DtRcQuit, "Quit","N/A", "Quit this application (Capital Q will force shutdown of loggers)"},
{DtRcLoadPlayback, "LoadPlayback", "<fileNameString> [constructFileName(1/0)] [checkForMediaFile(1/0)]",
"Load the specified file for playback with option to\n"
"\tconstruct name using logger ID (enabled)"},
{DtRcLoadRecord, "LoadRecord", "<fileNameString> [<overwrite(1/0)> [constructFileName(1/0) [recordMediaFile(1/0)]]]",
"Load the specified file for recording with option to\n"
"\toverwrite (enabled) and construct name using logger ID (enabled)"},
{DtRcUnload, "Unload", "N/A", "Unload the current tape"},
{DtRcPlay, "Play", "N/A", "Play the current tape"},
{DtRcPause, "Pause", "N/A", "Pause playback/recording"},
{DtRcStop, "Stop", "N/A", "Stop playback/recording"},
{DtRcRewind, "Rewind", "N/A", "Rewind to beginning of tape"},
{DtRcUnwind, "Unwind", "N/A", "Unwind to end of tape"},
{DtRcRecord, "Record", "[multipleFiles(0/1)]", "Record tape with option to use multiple files (disabled)"},
{DtRcSetscale, "SetScale", "<float> [skipping(0/1)]", "Set tape speed with the option to skip between checkpoints (disabled)"},
{DtRcJumpTime, "JumpTime", "<absTimeString(h:m:s)>",
"Jump to specified time in tape, hours and/or minutes can be omitted"},
{DtRcSkipTime, "SkipTime", "<relTimeString(h:m:s)>",
"Skip forwards or backwards from the current time;\n"
"\tnegative if used must be used in each part e.g., -5:-30"},
{DtRcSetplayAction, "SetplayAction", "{PLAY=0, PAUSE=1, STOP=3, EMPTY=4, LOOP=5}", "Set various actions for a tape loaded for playback"},
{DtRcSetRecordAction, "SetRecordAction", "{RECORD=2, STOP=3, EMPTY=4}", "Set various actions for a tape loaded for playback"},
{DtRcSetEofAction, "SetEofAction", "{PLAY=0, PAUSE=1, STOP=3, EMPTY=4, LOOP=5}", "Set various actions when reaching EOF"},
{DtRcDeleteFile, "DeleteFile", "<fileNameString>", "Delete the specified file from disk"},
#if DtHLA
{DtRcToggleFlag, "ToggleFlag", "<int>",
"Toggle various system flags\n"
" {STATE_REQUEST=1\n"
" TIME_CONSTR_ON=2, TIME_CONSTR_OFF=3,\n"
" TIME_REGLTD_ON=4, TIME_REGLTD_OFF=5,\n"
" OWN_FED_AMB_ON=6, OWN_FED_AMB_OFF=7}\n"},
#else
{DtRcToggleFlag, "ToggleFlag", "<int>", "Toggle various system flags: {STATE_REQUEST=1}"},
{DtRcSetHeartBeat, "SetHeartBeat", "<float>", "Set the entity heartbeat interval."},
{DtRcSetTimeout, "SetTimeout", "<float>", "Set the entity timeout interval."},
#endif
{DtRcShutdown, "Shutdown", "N/A", "Shutdown the connected loggers."},
{DtRcSetDestination, "SetDestination", "<IdString>",
"Change the destination ID e.g., 9:8:7 or 1:1:* - all loggers at 1:1"},
{DtRcSetOrigination, "SetOrigination", "<IdString>", "Change the origination ID e.g., 3:4:5"},
{DtRcLoadSubFile, "LoadSubFile", "<fileNameString> [idString]",
"Load the specified subscription file, with optional destination e.g., 9:8:7"},
{DtRcInfo, "Info", "N/A", "Display information on connected loggers"},
{DtRcConfig, "Config", "N/A", "Display configuration information"},
{DtRcRequestFileList, "RequestFileList", "[listDirs(1/0)]", "Request a file list from Loggers' default directory (normal files by default)"},
{DtRcPrintHistory, "PrintHistory", "[<int(start)> [<int(end)>]]", "Display command history from start to end (all by default)"},
{DtRcRestoreCmd, "RestoreCmd", "<int>", "Restore command with the given index."},
{DtRcHelp, "Help", "N/A", "Display this list of commands and pause for input\n"},
{DtRcInvalid, 0, "", ""}
};
class DtLgrControlInitializer : public DtVrlApplicationInitializer
{
public:
DtLgrControlInitializer(
int argc,
char* argv[],
const DtString& appName)
: DtVrlApplicationInitializer(argc, argv, appName)
, myNumberOfLoggers(mySettings, "numberOfLoggers", -1, "Number of Logger Connections")
, myRemoteControlId(mySettings, "remoteControlId", 0, "Remote Control ID")
, myConnectionTimeout(mySettings, "connectionTimeout", 120.0, "Connection Timeout")
, myAcknowledgeTimeout(mySettings, "acknowledgeTimeout", 5.0, "Acknowledge Timeout")
, myUseBackChannel(mySettings, "useBackChannel", 1, "Use back channel connection?")
, myBackChannelAddress(mySettings, "backChannelAddress", "229.7.7.53", "Back Channel Address")
, myBackChannelInterface(mySettings, "backChannelInterface", "0.0.0.0", "Back Channel Interface")
, myBackChannelPort(mySettings, "backChannelPort", 4053, "Back Channel Port")
{
#if DtHLA
setExecName("MAK-RPR-2.0");
setFederateType("MAK Logger Control");
setRprFomVersion(2.0);
#if DtHLA_1516_EVOLVED
std::vector<DtString> fomModules;
fomModules.push_back("MAK-VRFExt-4_evolved.xml");
fomModules.push_back("MAK-DIGuy-5_evolved.xml");
fomModules.push_back("MAK-LgrControl-2_evolved.xml");
fomModules.push_back("MAK-VRFAggregate-3_evolved.xml");
fomModules.push_back("MAK-DynamicTerrain-2_evolved.xml");
setFedFileName("RPR_FOM_v2.0_1516-2010.xml");
setFomModules(fomModules);
#elif DtHLA_1516
setFedFileName(DtDefaultRpr2Fom);
#else
setFedFileName(DtDefaultRpr2Fom);
#endif
#endif
}
~DtLgrControlInitializer()
{
}
virtual void initializeMtlParams()
{
DtVrlApplicationInitializer::initializeMtlParams();
myMtlEnv->registerConfigVar(myNumberOfLoggers);
myMtlEnv->registerConfigVar(myRemoteControlId);
myMtlEnv->registerConfigVar(myConnectionTimeout);
myMtlEnv->registerConfigVar(myAcknowledgeTimeout);
myMtlEnv->registerConfigVar(myUseBackChannel);
myMtlEnv->registerConfigVar(myBackChannelAddress);
myMtlEnv->registerConfigVar(myBackChannelPort);
}
virtual void setNumberOfLoggers(int val)
{
myNumberOfLoggers.setValue(val);
}
virtual int numberOfLoggers() const
{
return myNumberOfLoggers.value();
}
virtual void setRemoteControlId(int val)
{
myRemoteControlId.setValue(val);
}
virtual int remoteControlId() const
{
return myRemoteControlId.value();
}
virtual void setConnectionTimeout(double val)
{
myConnectionTimeout.setValue(val);
}
virtual double connectionTimeout() const
{
return myConnectionTimeout.value();
}
virtual void setAcknowledgeTimeout(double val)
{
myAcknowledgeTimeout.setValue(val);
}
virtual double acknowledgeTimeout() const
{
return myAcknowledgeTimeout.value();
}
virtual void setUseBackChannel(bool val)
{
myUseBackChannel.setValue(val);
}
virtual bool useBackChannel() const
{
return myUseBackChannel.value();
}
virtual void setBackChannelPort(int val)
{
myBackChannelPort.setValue(val);
}
virtual int backChannelPort() const
{
return myBackChannelPort.value();
}
virtual void setBackChannelAddress(
const DtString& val)
{
myBackChannelAddress.setValue(val);
}
virtual DtString backChannelAddress()
const
{
return myBackChannelAddress.value();
}
virtual void setBackChannelInterface(
const DtString& val)
{
myBackChannelInterface.setValue(val);
}
virtual DtString backChannelInterface()
const
{
return myBackChannelInterface.value();
}
protected:
DtConfigVariable<int> myNumberOfLoggers;
DtConfigVariable<int> myRemoteControlId;
DtConfigVariable<double> myConnectionTimeout;
DtConfigVariable<double> myAcknowledgeTimeout;
DtConfigVariable<int> myUseBackChannel;
DtConfigVariable<DtString> myBackChannelAddress;
DtConfigVariable<DtString> myBackChannelInterface;
DtConfigVariable<int> myBackChannelPort;
};
int main( int argc, char* argv[] )
{
DtINIT_MINIDUMPER( "Logger Control" );
DtLgrControlInitializer appInit(argc, argv, "lgrControl");
#if DtDIS
appInit.setUseAsynchIO(true);
#endif
appInit.parseCmdLine();
DtEntityIdentifier selfEntityID(DtSimulationAddress(53,53), appInit.remoteControlId());
DtInetUdpSocket* backChannelConnection = 0;
DtEntityIdentifier lgrEntityID("65535:65535:65535");
if (appInit.useBackChannel())
{
DtInetDevice hostIf(DtInetAddr(appInit.backChannelInterface()));
backChannelConnection = new DtInetUdpSocket(
DtInetEndpoint(DtInetAddr(appInit.backChannelAddress()), appInit.backChannelPort()),
0,
((!hostIf.addr() || hostIf.addr()->isAnyAddr()) ? 0 : &hostIf),
DtDefaultSockOpts | DtSockOptNonBlocking);
remoteControl->
setConnection(selfEntityID, backChannelConnection);
}
else
{
try
{
}
catch( DtVlRtiMismatchException )
{
DtFatal << "Mismatching RTI compiler Version. Please reconfigure your environment" << std::endl;
return -1;
}
selfEntityID.setSimulationAddress(conn->applicationId());
}
bool skipTick = false;
char cmdLine[2048];
bool timeToQuit = false;
while( !timeToQuit )
{
if (conn)
{
conn->clock()->setSimTime( conn->clock()->elapsedRealTime() );
}
if (!skipTick)
{
if (conn)
{
conn->drainInput();
}
}
skipTick = false;
{
char* token = cmdLine;
char* cmdToken = getToken( &token, " \t\n\r" );
char* optionalArg = getToken( &token, " \t\n\r" );
int ln = strlen( cmdToken );
if ( ln == 0 )
{
continue;
}
int cmd = 0;
if (isdigit(*cmdToken))
{
cmd = atoi( cmdToken );
}
else
{
cmd = tokenToCommandId(cmdToken);
}
switch( cmd )
{
case DtRcQuit:
{
timeToQuit = true;
if (*cmdToken == 'Q')
{
}
break;
}
case DtRcLoadPlayback:
{
{
bool constructFileName = false;
bool playMedia = false;
char* cmdArg = getToken( &token, " \t\n\r" );
if (cmdArg && *cmdArg != '\0')
{
constructFileName = atoi(cmdArg) == 1;
cmdArg = getToken(&token, " \t\n\r");
if (cmdArg && *cmdArg != '\0')
{
playMedia = atoi(cmdArg) == 1;
}
}
playbackInterface->openFile(optionalArg, constructFileName, playMedia, lgrEntityID);
}
break;
}
case DtRcLoadRecord:
{
if (!playbackInterface->isPlaying())
{
bool overwrite = false;
bool constructFileName = false;
bool recordMedia = false;
char* overwriteArg = getToken( &token, " \t\n\r" );
char* cmdArg = getToken(&token, " \t\n\r");
if (cmdArg && *cmdArg != '\0')
{
overwrite = atoi(cmdArg) != 0;
cmdArg = getToken(&token, " \t\n\r");
if (cmdArg && *cmdArg != '\0')
{
constructFileName = atoi(cmdArg) == 1;
cmdArg = getToken(&token, " \t\n\r");
if (cmdArg && *cmdArg != '\0')
{
recordMedia = atoi(cmdArg) == 1;
}
}
}
if (playbackInterface->isFileOpened() && !playbackInterface->isFileChanged() )
{
playbackInterface->closeFile(lgrEntityID);
}
else if(playbackInterface->isFileOpened() && playbackInterface->isFileChanged() && !overwrite)
{
DtInfo << "The current Logger tape has been modified since the last save. Please save or unload the open Logger file before continuing." << std::endl;
break;
}
recordInterface->
newFile(optionalArg, description, overwrite, constructFileName, recordMedia, lgrEntityID);
}
break;
}
case DtRcUnload:
{
playbackInterface->closeFile(lgrEntityID);
break;
}
case DtRcPlay:
{
playbackInterface->play(lgrEntityID);
break;
}
case DtRcPause:
{
playbackInterface->pause(lgrEntityID);
recordInterface->
pause(lgrEntityID);
break;
}
case DtRcStop:
{
playbackInterface->stop(lgrEntityID);
recordInterface->
stop(
false, lgrEntityID);
break;
}
case DtRcRewind:
{
playbackInterface->jumpToStart(lgrEntityID);
break;
}
case DtRcUnwind:
{
playbackInterface->jumpToStop(lgrEntityID);
break;
}
case DtRcRecord:
{
bool multipleFiles = false;
if ( optionalArg && *optionalArg == '\0' )
{
multipleFiles = atoi(optionalArg) != 0;
}
recordInterface->
record(multipleFiles, lgrEntityID);
break;
}
case DtRcSetscale:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid time-scale.\n" );
}
else
{
bool skipping = false;
char* skippingArg = getToken( &token, " \t\n\r" );
if ( skippingArg && *skippingArg != '\0' )
{
skipping = atoi(skippingArg) != 0;
}
playbackInterface->setPlaybackSpeed(atof(optionalArg), skipping, lgrEntityID);
}
break;
}
case DtRcJumpTime:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid time value.\n" );
}
else
{
try
{
playbackInterface->jumpToTime(time, lgrEntityID);
}
catch (DtInvalidInput*)
{
DtWarn( "Unable to parse time.\n" );
}
catch (...)
{
DtWarn( "Unable to parse time.\n" );
}
}
break;
}
case DtRcSkipTime:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid time value.\n" );
}
else
{
try
{
if (skipTime.seconds() < 0)
{
playbackInterface->skipTimeBackward(-skipTime.seconds(), lgrEntityID);
}
else
{
playbackInterface->skipTimeForward(skipTime, lgrEntityID);
}
}
catch (DtInvalidInput*)
{
DtWarn( "Unable to parse time.\n" );
}
catch (...)
{
DtWarn( "Unable to parse time.\n" );
}
}
break;
}
case DtRcSetplayAction:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid PlayAction mode.\n" );
}
else
{
int ix = atoi(optionalArg);
switch (ix)
{
case 0:
{
playbackInterface->setPlayOnLoad(true, lgrEntityID);
break;
}
case 3:
{
playbackInterface->setPlayOnLoad(false, lgrEntityID);
break;
}
case 1:
case 4:
{
playbackInterface->closeFile(lgrEntityID);
break;
}
case 5:
{
break;
}
case 2:
default:
{
DtWarn( "%d is not a valid PlayAction mode.\n", ix );
break;
}
}
}
break;
}
case DtRcSetRecordAction:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid RecordAction mode.\n" );
}
else
{
int ix = atoi(optionalArg);
switch (ix)
{
case 2:
{
break;
}
case 3:
{
break;
}
case 4:
{
break;
}
case 0:
case 1:
case 5:
default:
{
DtWarn( "%d is not a valid RecordAction mode.\n", ix );
break;
}
}
}
break;
}
case DtRcSetEofAction:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid EofAction mode.\n" );
}
else
{
int ix = atoi(optionalArg);
switch (ix)
{
case 3:
{
playbackInterface->setLoopAtEnd(false, lgrEntityID);
break;
}
case 5:
{
playbackInterface->setLoopAtEnd(true, lgrEntityID);
break;
}
case 0:
case 1:
case 4:
{
break;
}
case 2:
default:
{
DtWarn( "%d is not a valid EofAction mode.\n", ix );
break;
}
}
}
break;
}
case DtRcDeleteFile:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid file name.\n" );
}
else
{
systemInterface->
deleteFile(optionalArg, lgrEntityID);
}
break;
}
case DtRcToggleFlag:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid StateFlag index.\n" );
}
else
{
int ix = atoi(optionalArg);
if ( ix <= 0 || ix > 7 )
{
DtWarn( "%d is not a valid StateFlag index.\n", ix );
}
else
{
{
}
else
{
}
}
}
break;
}
#if DtDIS
case DtRcSetHeartBeat:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid heartbeat.\n" );
}
else
{
DtLgrDisCommandFactory::createSetHeartbeatRateCommand(atof(optionalArg)),
lgrEntityID);
}
break;
}
case DtRcSetTimeout:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a valid timeout.\n" );
}
else
{
DtLgrDisCommandFactory::createSetTimeoutRateCommand(atof(optionalArg)),
lgrEntityID);
}
break;
}
#endif
case DtRcShutdown:
{
break;
}
case DtRcSetDestination:
{
DtEntityIdentifier tempId = parseEntityIdentifier(optionalArg);
if (lgrEntityID == tempId)
{
DtInfo << "Logger ID unchanged: " << lgrEntityID.string() << std::endl;
}
else
{
lgrEntityID = tempId;
DtInfo << "New logger ID: " << lgrEntityID.string() << std::endl;
}
break;
}
case DtRcSetOrigination:
{
DtEntityIdentifier tempId(optionalArg);
if (selfEntityID == tempId)
{
DtInfo << "Self ID unchanged: " << selfEntityID.string() << std::endl;
}
else
{
selfEntityID = tempId;
DtInfo <<"New Self ID; " << selfEntityID.string() << std::endl;
}
break;
}
#if DtHLA
case DtRcLoadSubFile:
{
if ( !optionalArg || *optionalArg == '\0' )
{
DtWarn( "The empty string is not a subscription file name.\n" );
}
else
{
char* entityIdArg = getToken( &token, " \t\n\r" );
if ( entityIdArg && *entityIdArg != '\0' )
{
destination = parseEntityIdentifier(entityIdArg);
}
else
{
destination = lgrEntityID;
}
}
break;
}
#endif
case DtRcInfo:
{
if (connectedLoggers.size() == 0)
{
DtInfo << "No Loggers Connected.\n";
}
else
{
DtInfo << "Connected Loggers\n";
DtEntityIdSet::const_iterator idIter = connectedLoggers.begin();
DtEntityIdSet::const_iterator lgrEnd = connectedLoggers.end();
for ( ; idIter != lgrEnd; ++idIter)
{
if (connection)
{
}
}
DtInfo << std::endl;
}
break;
}
case DtRcConfig:
{
DtInfo << "Destination: " << lgrEntityID.string() << std::endl;
DtInfo << "Origination: " << selfEntityID.string() << std::endl;
DtInfo << "Number Loggers: " << appInit.numberOfLoggers() << std::endl;
DtInfo << "Remote Control ID: " << appInit.remoteControlId() << std::endl;
DtInfo << "Connection timeout: " << appInit.connectionTimeout() << std::endl;
#if DtHLA
DtInfo << "Execution name: " << appInit.execName() << std::endl;
#if DtHLA_1516_EVOLVED
DtInfo << "Federate name: " << appInit.federateName() << std::endl;
#endif
DtInfo << "Federate type: " << appInit.federateType() << std::endl;
DtInfo << "FOM filename: " << appInit.fedFileName() << std::endl;
#if DtHLA_1516_EVOLVED
DtInfo << "MIM filename: " << appInit.mimModule() << std::endl;
std::vector<DtString> modules;
appInit.fomModules(modules);
DtInfo << "FOM Module count : " << modules.size() << std::endl;
for (std::vector<DtString>::const_iterator iter = modules.begin(); iter != modules.end(); ++iter)
DtInfo << "\t" << *iter << std::endl;
#endif
DtInfo << "FOM Mapper lib. name: " << appInit.fomMapperLibName() << std::endl;
DtInfo << "RPR version: " << appInit.rprFomVersion() << std::endl;
DtInfo << "Use Advisories: " << appInit.useAdvisories() << std::endl;
DtInfo << "TimeStamp type: " << appInit.timeStampType() << std::endl;
DtInfo << "Destroy Execution: " << appInit.destroyFedExec() << std::endl;
DtInfo << "Send Fed Time: " << appInit.sendFedTime() << std::endl;
DtInfo << "RPR revision: " << appInit.rprFomRevision() << std::endl;
DtInfo << "Reflecting: " << appInit.reflecting() << std::endl;
DtInfo << "Reflect Remote Updates Into Pub: " << appInit.reflectRemoteUpdatesIntoPub() << std::endl;
DtInfo << "Reflect Through Rti: " << appInit.reflectThroughRti() << std::endl;
DtInfo << "Reply To Sync Points: " << appInit.replyToSynchPoints() << std::endl;
DtInfo << "Auto Subscribe: " << appInit.autoSubscribe() << std::endl;
#else
DtInfo << "Port: " << appInit.port() << std::endl;
DtInfo << "Exercise ID: " << appInit.exerciseId() << std::endl;
DtInfo << "Application Number: " << appInit.applicationNumber() << std::endl;
DtInfo << "Site ID: " << appInit.siteId() << std::endl;
DtInfo << "Destination Address: " << appInit.destinationAddress() << std::endl;
DtInfo << "Send Buffer Size: " << appInit.sendBufferSize() << std::endl;
DtInfo << "Receive Buffer Size: " << appInit.receiveBufferSize() << std::endl;
DtInfo << "Use Asynch. IO: " << appInit.useAsynchIO() << std::endl;
DtInfo << "Multicast TTL: " << appInit.multicastTtl() << std::endl;
DtInfo << "Time Stamp Type: " << appInit.timeStampType() << std::endl;
DtInfo << "Use IP v6: " << appInit.useIpv6() << std::endl;
DtInfo << "Suppress Self Reflect: " << appInit.suppressSelfReflect() << std::endl;
DtInfo << "Device Address: " << appInit.deviceAddress() << std::endl;
const std::vector<DtString>& multicastAddrs = appInit.multicastAddresses();
DtInfo << "Multicast Address count: " << multicastAddrs.size() << std::endl;
for (std::vector<DtString>::const_iterator iter = multicastAddrs.begin(); iter != multicastAddrs.end(); ++iter)
DtInfo << "\t" << *iter << std::endl;
#endif
DtInfo << "Use Back Channel: " << appInit.useBackChannel() << std::endl;
DtInfo << "Back Channel Interface: " << appInit.backChannelInterface() << std::endl;
DtInfo << "Back Channel Address: " << appInit.backChannelAddress() << std::endl;
DtInfo << "Back Channel Port: " << appInit.backChannelPort() << std::endl;
break;
}
case DtRcRequestFileList:
{
bool listDirs = false;
if ( optionalArg && *optionalArg!= '\0' )
{
listDirs = atoi(optionalArg) != 0;
}
playbackInterface->requestFileList(listDirs, lgrEntityID);
break;
}
case DtRcPrintHistory:
{
unsigned int start = 0;
unsigned int end = 65535;
if ( optionalArg && *optionalArg != '\0' )
{
start = atoi(optionalArg);
char* endArg = getToken( &token, " \t\n\r" );
if ( endArg && *endArg != '\0' )
{
end = atoi(endArg);
}
}
break;
}
case DtRcRestoreCmd:
{
int cmdIndex = 0;
if ( optionalArg && *optionalArg != '\0' )
{
cmdIndex = atoi(optionalArg);
}
break;
}
case DtRcHelp:
{
printHelp();
skipTick = true;
break;
}
default:
{
DtWarn << "Command not recognized: " << cmdToken << std::endl;
break;
}
}
}
}
DtDELETE(remoteControl);
DtDELETE(conn);
DtDELETE(backChannelConnection);
DtInfo << std::endl << "Bye bye now..." << std::endl << std::endl;
return 0;
}
char* getToken( char** nextp, const char* sep )
{
char* start = *nextp;
if ( !start ) return 0;
while( *start != '\0' && strchr( sep, *start ) ) ++start;
if ( *start == '\0' )
{
*nextp = start;
return start;
}
char* end = start;
for( ; *end != '\0' && !strchr( sep, *end ); ++end );
for( ; *end != '\0' && strchr( sep, *end ); ++end ) *end = '\0';
*nextp = end;
return start;
}
{
DtWarn << "Logger Connection timed out\n";
}
void printHelp()
{
DtInfo << "Command ID / Token Optional-Arguments\n"
<< "\t Description" << std::endl;
for (int i=0; theCommandTokens[i].token != 0; i++)
{
const DtRcToken& cmdRecord = theCommandTokens[i];
DtInfo << std::setw(3) << cmdRecord.id << " / " << cmdRecord.token << " " << cmdRecord.paramStr
<< std::endl << "\t" << cmdRecord.helpStr << std::endl;
}
DtInfo << "Enter command token (or ID) with arguments then press Enter key." << std::endl;
DtInfo << "WARNING: processing halts until Enter key is pressed!";
DtInfo.flush();
}
int tokenToCommandId(
DtString commandString )
{
int cmdId = -1;
commandString.toLower();
for (int i=0; cmdId < 0 && theCommandTokens[i].token != 0; i++)
{
DtString cmdToken(theCommandTokens[i].token);
cmdToken.toLower();
if (cmdToken == commandString || cmdToken.findString(commandString) == 0)
{
cmdId = theCommandTokens[i].id;
}
}
return cmdId;
}
DtEntityIdentifier parseEntityIdentifier(const char* buffer)
{
DtEntityIdentifier id;
if (idString.findChar('*') < 0)
{
id = DtEntityIdentifier(buffer);
}
else
{
int site = 0;
int host = 0;
int entity = 0;
temp1 = idString;
temp1.snipBack(':', true);
site = (temp1 == wildcard) ? 65535: temp1.toInt();
idString.snipFront(':');
temp1 = idString;
temp1.snipBack(':', true);
host = (temp1 == wildcard) ? 65535: temp1.toInt();
idString.snipFront(':');
temp1 = idString;
entity = (temp1 == wildcard) ? 65535: temp1.toInt();
id.init(site, host, entity);
}
return id;
}