Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * skillet.cpp - Skiller console tool 00004 * 00005 * Created: Sat Mar 15 13:57:22 2008 00006 * Copyright 2006-2008 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include <netcomm/fawkes/client.h> 00024 #include <blackboard/remote.h> 00025 #include <utils/system/argparser.h> 00026 #include <utils/system/signal.h> 00027 #include <core/threading/thread.h> 00028 #include <netcomm/fawkes/client_handler.h> 00029 00030 #include <cstring> 00031 #include <cstdlib> 00032 #include <cstdio> 00033 #include <unistd.h> 00034 #include <csignal> 00035 #include <string> 00036 00037 #include <readline/readline.h> 00038 #include <readline/history.h> 00039 00040 #include <interfaces/SkillerInterface.h> 00041 00042 using namespace fawkes; 00043 00044 void 00045 print_usage(const char *program_name) 00046 { 00047 printf("Usage: %s [-h] [-r host[:port]]\n" 00048 " -h This help message\n" 00049 " -r host[:port] Remote host (and optionally port) to connect to\n", 00050 program_name); 00051 } 00052 00053 static int 00054 event_hook() 00055 { 00056 return 0; 00057 } 00058 00059 00060 /** Skill shell thread. 00061 * This thread opens a network connection to a host and uses a RemoteBlackBoard 00062 * connection to send skill strings for execution. It also shows Skiller log messages 00063 * and uses the skiller network protocol. 00064 * @author Tim Niemueller 00065 */ 00066 class SkillShellThread : public Thread, public FawkesNetworkClientHandler 00067 { 00068 public: 00069 /** Constructor. 00070 * @param argp argument parser 00071 */ 00072 SkillShellThread(ArgumentParser *argp) 00073 : Thread("SkillShellThread", Thread::OPMODE_CONTINUOUS) 00074 { 00075 this->argp = argp; 00076 prompt = "-# "; 00077 just_connected = true; 00078 connection_died_recently = false; 00079 00080 sif = NULL; 00081 using_history(); 00082 // this is needed to get rl_done working 00083 rl_event_hook = event_hook; 00084 00085 continuous = false; 00086 00087 char *host = (char *)"localhost"; 00088 unsigned short int port = 1910; 00089 bool free_host = argp->parse_hostport("r", &host, &port); 00090 00091 c = new FawkesNetworkClient(host, port); 00092 00093 if ( free_host ) free(host); 00094 00095 c->register_handler(this, FAWKES_CID_SKILLER_PLUGIN); 00096 c->connect(); 00097 } 00098 00099 /** Destructor. */ 00100 ~SkillShellThread() 00101 { 00102 printf("Finalizing\n"); 00103 00104 SkillerInterface::ReleaseControlMessage *rcm = new SkillerInterface::ReleaseControlMessage(); 00105 sif->msgq_enqueue(rcm); 00106 00107 usleep(500000); 00108 00109 rbb->close(sif); 00110 delete rbb; 00111 rbb = NULL; 00112 00113 c->deregister_handler(FAWKES_CID_SKILLER_PLUGIN); 00114 c->disconnect(); 00115 delete c; 00116 } 00117 00118 00119 virtual void loop() 00120 { 00121 if ( c->connected() ) { 00122 if ( just_connected ) { 00123 just_connected = false; 00124 try { 00125 rbb = new RemoteBlackBoard(c); 00126 sif = rbb->open_for_reading<SkillerInterface>("Skiller"); 00127 SkillerInterface::AcquireControlMessage *aqm = new SkillerInterface::AcquireControlMessage(); 00128 sif->msgq_enqueue(aqm); 00129 usleep(100000); 00130 } catch (Exception &e) { 00131 e.print_trace(); 00132 return; 00133 } 00134 } 00135 00136 if ( argp->num_items() > 0 ) { 00137 std::string sks = ""; 00138 const std::vector< const char * > & items = argp->items(); 00139 00140 std::vector< const char * >::const_iterator i = items.begin(); 00141 sks = *i; 00142 ++i; 00143 for (; i != items.end(); ++i) { 00144 sks += " "; 00145 sks += *i; 00146 } 00147 00148 SkillerInterface::ExecSkillMessage *esm = new SkillerInterface::ExecSkillMessage(sks.c_str()); 00149 sif->msgq_enqueue(esm); 00150 00151 usleep(100000); 00152 exit(); 00153 } else { 00154 char *line = NULL; 00155 00156 line = readline(prompt); 00157 if ( line ) { 00158 if (strcmp(line, "") != 0) { 00159 00160 if ( strcmp(line, "cont") == 0 ) { 00161 printf("Switching to continuous skill execution mode\n"); 00162 continuous = true; 00163 } else if (strcmp(line, "oneshot") == 0 ) { 00164 printf("Switching to one-shot skill execution mode\n"); 00165 continuous = false; 00166 } else if (strcmp(line, "stop") == 0 ) { 00167 printf("Stopping continuous skill execution\n"); 00168 SkillerInterface::StopExecMessage *sm = new SkillerInterface::StopExecMessage(); 00169 sif->msgq_enqueue(sm); 00170 } else { 00171 printf("Executing: %s\n", line); 00172 if ( continuous ) { 00173 SkillerInterface::ExecSkillContinuousMessage *escm = new SkillerInterface::ExecSkillContinuousMessage(line); 00174 sif->msgq_enqueue(escm); 00175 } else { 00176 SkillerInterface::ExecSkillMessage *esm = new SkillerInterface::ExecSkillMessage(line); 00177 sif->msgq_enqueue(esm); 00178 } 00179 } 00180 00181 add_history(line); 00182 } 00183 } else { 00184 if ( ! connection_died_recently ) { 00185 exit(); 00186 } 00187 } 00188 } 00189 } else { 00190 if ( connection_died_recently ) { 00191 connection_died_recently = false; 00192 printf("Connection died\n"); 00193 c->disconnect(); 00194 } 00195 try { 00196 c->connect(); 00197 } catch (Exception &e) { 00198 printf("."); 00199 fflush(stdout); 00200 sleep(1); 00201 } 00202 } 00203 } 00204 00205 00206 virtual void deregistered(unsigned int id) throw() 00207 { 00208 } 00209 00210 00211 virtual void inbound_received(FawkesNetworkMessage *m, 00212 unsigned int id) throw() 00213 { 00214 } 00215 00216 00217 virtual void connection_died(unsigned int id) throw() 00218 { 00219 prompt = "-# "; 00220 00221 rbb->close(sif); 00222 delete rbb; 00223 rbb = NULL; 00224 sif = NULL; 00225 00226 connection_died_recently = true; 00227 00228 //fprintf(stdin, "\n"); 00229 //kill(SIGINT); 00230 rl_done = 1; 00231 } 00232 00233 00234 virtual void connection_established(unsigned int id) throw() 00235 { 00236 printf("Connection established\n"); 00237 just_connected = true; 00238 prompt = "+# "; 00239 } 00240 00241 00242 private: 00243 ArgumentParser *argp; 00244 FawkesNetworkClient *c; 00245 BlackBoard *rbb; 00246 SkillerInterface *sif; 00247 const char *prompt; 00248 bool just_connected; 00249 bool connection_died_recently; 00250 00251 bool continuous; 00252 }; 00253 00254 00255 /** Config tool main. 00256 * @param argc argument count 00257 * @param argv arguments 00258 */ 00259 int 00260 main(int argc, char **argv) 00261 { 00262 ArgumentParser argp(argc, argv, "hr:"); 00263 00264 if ( argp.has_arg("h") ) { 00265 print_usage(argv[0]); 00266 exit(0); 00267 } 00268 00269 SkillShellThread sst(&argp); 00270 sst.start(); 00271 sst.join(); 00272 00273 return 0; 00274 }