Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * msl2007.cpp - Fawkes mid-size refbox repeater 00004 * 00005 * Created: Wed Apr 09 10:38:16 2008 00006 * Copyright 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 <tools/refboxrep/msl2007.h> 00024 #include <netcomm/socket/stream.h> 00025 00026 #include <cstring> 00027 #include <cstdio> 00028 #include <unistd.h> 00029 00030 using namespace fawkes; 00031 00032 // REFBOX_CODES ////////////////////////// 00033 static const char REFBOX_TEST = '*'; 00034 static const char REFBOX_CANCEL = 'x'; 00035 static const char REFBOX_START = 's'; 00036 static const char REFBOX_HALT = 'H'; 00037 static const char REFBOX_STOP = 'S'; 00038 static const char REFBOX_ENDHALF = 'H'; 00039 static const char REFBOX_DROPPED_BALL = 'N'; 00040 00041 static const char REFBOX_FIRST_HALF = '1'; 00042 static const char REFBOX_SECOND_HALF = '2'; 00043 static const char REFBOX_HALF_TIME = 'h'; 00044 static const char REFBOX_END_GAME = 'e'; 00045 00046 static const char REFBOX_GOAL_CYAN = 'A'; 00047 static const char REFBOX_GOAL_MAGENTA = 'a'; 00048 00049 static const char REFBOX_KICK_OFF_CYAN = 'K'; 00050 static const char REFBOX_KICK_OFF_MAGENTA = 'k'; 00051 static const char REFBOX_FREE_KICK_CYAN = 'F'; 00052 static const char REFBOX_FREE_KICK_MAGENTA = 'f'; 00053 static const char REFBOX_GOAL_KICK_CYAN = 'G'; 00054 static const char REFBOX_GOAL_KICK_MAGENTA = 'g'; 00055 static const char REFBOX_THROW_IN_CYAN = 'T'; 00056 static const char REFBOX_THROW_IN_MAGENTA = 't'; 00057 static const char REFBOX_CORNER_KICK_CYAN = 'C'; 00058 static const char REFBOX_CORNER_KICK_MAGENTA = 'c'; 00059 static const char REFBOX_PENALTY_CYAN = 'P'; 00060 static const char REFBOX_PENALTY_MAGENTA = 'p'; 00061 00062 static const char * REFBOX_WELCOME = "Welcome.."; 00063 //static const char * REFBOX_RECONNECT = "Reconnect"; 00064 00065 /** @class MidsizeRefBoxRepeater <tools/refboxrep/msl2007.h> 00066 * Mid-size league refbox repeater. 00067 * This class will communicate with the mid-size league refbox and derive matching 00068 * game states from the communiation stream and send this via the world info. 00069 * @author Tim Niemueller 00070 */ 00071 00072 /** Constructor. 00073 * @param rss refbox state sender 00074 * @param refbox_host refbox host 00075 * @param refbox_port refbox port 00076 */ 00077 MidsizeRefBoxRepeater::MidsizeRefBoxRepeater(RefBoxStateSender &rss, 00078 const char *refbox_host, 00079 unsigned short int refbox_port) 00080 : __rss(rss) 00081 { 00082 __quit = false; 00083 __s = NULL; 00084 __score_cyan = __score_magenta = 0; 00085 00086 __refbox_host = strdup(refbox_host); 00087 __refbox_port = refbox_port; 00088 00089 reconnect(); 00090 } 00091 00092 00093 /** Destructor. */ 00094 MidsizeRefBoxRepeater::~MidsizeRefBoxRepeater() 00095 { 00096 free(__refbox_host); 00097 __s->close(); 00098 delete __s; 00099 } 00100 00101 00102 /** Reconnect to refbox. */ 00103 void 00104 MidsizeRefBoxRepeater::reconnect() 00105 { 00106 if ( __s ) { 00107 __s->close(); 00108 delete __s; 00109 } 00110 printf("Trying to connect to refbox at %s:%u\n", __refbox_host, __refbox_port); 00111 do { 00112 try { 00113 __s = new StreamSocket(); 00114 __s->connect(__refbox_host, __refbox_port); 00115 00116 char welcomebuf[strlen(REFBOX_WELCOME) + 1]; 00117 welcomebuf[strlen(REFBOX_WELCOME)] = 0; 00118 __s->read(welcomebuf, strlen(REFBOX_WELCOME)); 00119 printf("Connected, received welcome string: %s\n", welcomebuf); 00120 } catch (Exception &e) { 00121 delete __s; 00122 __s = NULL; 00123 printf("."); 00124 fflush(stdout); 00125 usleep(500000); 00126 } 00127 } while ( ! __s ); 00128 } 00129 00130 00131 /** Process received string. */ 00132 void 00133 MidsizeRefBoxRepeater::process_string(char *buf, size_t len) 00134 { 00135 for (size_t b = 0; b < len; ++b) { 00136 switch (buf[b]) { 00137 case REFBOX_TEST: 00138 // immediately reply 00139 printf("Received connection test, replying\n"); 00140 __s->write("*", 1); 00141 break; 00142 00143 case REFBOX_CANCEL: 00144 printf("RefBox cancelled last command\n"); 00145 break; 00146 00147 case REFBOX_START: 00148 __rss.set_gamestate(GS_PLAY, TEAM_BOTH); 00149 break; 00150 00151 case REFBOX_HALT: 00152 case REFBOX_STOP: 00153 __rss.set_gamestate(GS_FROZEN, TEAM_BOTH); 00154 break; 00155 00156 case REFBOX_DROPPED_BALL: 00157 __rss.set_gamestate(GS_DROP_BALL, TEAM_BOTH); 00158 break; 00159 00160 case REFBOX_GOAL_CYAN: 00161 __rss.set_score(++__score_cyan, __score_magenta); 00162 __rss.set_gamestate(GS_FROZEN, TEAM_BOTH); 00163 break; 00164 00165 case REFBOX_GOAL_MAGENTA: 00166 __rss.set_score(__score_cyan, ++__score_magenta); 00167 __rss.set_gamestate(GS_FROZEN, TEAM_BOTH); 00168 break; 00169 00170 case REFBOX_KICK_OFF_CYAN: 00171 __rss.set_gamestate(GS_KICK_OFF, TEAM_CYAN); 00172 break; 00173 00174 case REFBOX_KICK_OFF_MAGENTA: 00175 __rss.set_gamestate(GS_KICK_OFF, TEAM_MAGENTA); 00176 break; 00177 00178 case REFBOX_PENALTY_CYAN: 00179 __rss.set_gamestate(GS_PENALTY, TEAM_CYAN); 00180 break; 00181 00182 case REFBOX_PENALTY_MAGENTA: 00183 __rss.set_gamestate(GS_PENALTY, TEAM_MAGENTA); 00184 break; 00185 00186 case REFBOX_CORNER_KICK_CYAN: 00187 __rss.set_gamestate(GS_CORNER_KICK, TEAM_CYAN); 00188 break; 00189 00190 case REFBOX_CORNER_KICK_MAGENTA: 00191 __rss.set_gamestate(GS_CORNER_KICK, TEAM_MAGENTA); 00192 break; 00193 00194 case REFBOX_THROW_IN_CYAN: 00195 __rss.set_gamestate(GS_THROW_IN, TEAM_CYAN); 00196 break; 00197 00198 case REFBOX_THROW_IN_MAGENTA: 00199 __rss.set_gamestate(GS_THROW_IN, TEAM_MAGENTA); 00200 break; 00201 00202 case REFBOX_FREE_KICK_CYAN: 00203 __rss.set_gamestate(GS_FREE_KICK, TEAM_CYAN); 00204 break; 00205 00206 case REFBOX_FREE_KICK_MAGENTA: 00207 __rss.set_gamestate(GS_FREE_KICK, TEAM_MAGENTA); 00208 break; 00209 00210 case REFBOX_GOAL_KICK_CYAN: 00211 __rss.set_gamestate(GS_GOAL_KICK, TEAM_CYAN); 00212 break; 00213 00214 case REFBOX_GOAL_KICK_MAGENTA: 00215 __rss.set_gamestate(GS_GOAL_KICK, TEAM_MAGENTA); 00216 break; 00217 00218 case REFBOX_FIRST_HALF: 00219 __rss.set_half(HALF_FIRST); 00220 break; 00221 00222 case REFBOX_SECOND_HALF: 00223 __rss.set_half(HALF_SECOND); 00224 break; 00225 00226 case REFBOX_HALF_TIME: 00227 __rss.set_gamestate(GS_HALF_TIME, TEAM_BOTH); 00228 break; 00229 00230 default: 00231 printf("Received unknown command: '%c'\n", buf[b]); 00232 break; 00233 } 00234 } 00235 00236 __rss.send(); 00237 } 00238 00239 00240 /** Run. 00241 * Reads messages from the network, processes them and calls the refbox state sender. 00242 */ 00243 void 00244 MidsizeRefBoxRepeater::run() 00245 { 00246 char tmpbuf[100]; 00247 while ( ! __quit ) { 00248 size_t bytes_read = __s->read(tmpbuf, sizeof(tmpbuf), /* read all */ false); 00249 if ( bytes_read == 0 ) { 00250 // seems that the remote has died, reconnect 00251 printf("Connection died, reconnecting\n"); 00252 reconnect(); 00253 } else { 00254 process_string(tmpbuf, bytes_read); 00255 } 00256 } 00257 }