Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * msl2010.cpp - Fawkes mid-size refbox 2010 protocol repeater 00004 * 00005 * Created: Wed Apr 01 18:41:00 2010 00006 * Copyright 2010 Stefan Schiffer [stefanschiffer.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/msl2010.h> 00024 #include <netcomm/socket/stream.h> 00025 #include <netcomm/socket/datagram_multicast.h> 00026 00027 #include <cstring> 00028 #include <cstdio> 00029 #include <unistd.h> 00030 #include <iostream> 00031 #include <sstream> 00032 #include <string> 00033 00034 #include <libxml++/libxml++.h> 00035 00036 using namespace fawkes; 00037 using namespace xmlpp; 00038 00039 00040 // REFBOX_CODES ////////////////////////// 00041 00042 //static const char * REFBOX_WELCOME = "Welcome"; 00043 //static const char * REFBOX_RECONNECT = "Reconnect"; 00044 00045 static const std::string REFBOX_EVENT = "RefboxEvent"; 00046 static const std::string REFBOX_GAMEINFO = "GameInfo"; 00047 static const std::string REFBOX_EVENT_REFEREE = "Referee"; 00048 static const std::string REFBOX_EVENT_TEAMSETUP = "TeamSetup"; 00049 00050 static const std::string REFBOX_CANCEL = "Cancel"; 00051 00052 static const std::string REFBOX_GAMESTART = "GameStart"; 00053 static const std::string REFBOX_GAMESTOP = "GameStop"; 00054 00055 static const std::string REFBOX_STAGE_CHANGED = "StageChanged"; 00056 static const std::string REFBOX_STAGETYPE_PREGAME = "preGame"; 00057 static const std::string REFBOX_STAGETYPE_FIRSTHALF = "firstHalf"; 00058 static const std::string REFBOX_STAGETYPE_HALFTIME = "halfTime"; 00059 static const std::string REFBOX_STAGETYPE_SECONDHALF = "secondHalf"; 00060 static const std::string REFBOX_STAGETYPE_SHOOTOUT = "shootOut"; 00061 static const std::string REFBOX_STAGETYPE_ENDGAME = "endGame"; 00062 00063 static const std::string REFBOX_GOAL_AWARDED = "GoalAwarded"; 00064 static const std::string REFBOX_GOAL_REMOVED = "GoalRemoved"; 00065 00066 static const std::string REFBOX_CARD_AWARDED = "CardAwarded"; 00067 static const std::string REFBOX_CARD_REMOVED = "CardRemoved"; 00068 00069 static const std::string REFBOX_SUBSTITUTION = "Substitution"; 00070 static const std::string REFBOX_PLAYER_OUT = "PlayerOut"; 00071 static const std::string REFBOX_PLAYER_IN = "PlayerIn"; 00072 00073 static const std::string REFBOX_DROPPEDBALL = "DroppedBall"; 00074 static const std::string REFBOX_KICKOFF = "KickOff"; 00075 static const std::string REFBOX_FREEKICK = "FreeKick"; 00076 static const std::string REFBOX_GOALKICK = "GoalKick"; 00077 static const std::string REFBOX_THROWIN = "ThrowIn"; 00078 static const std::string REFBOX_CORNER = "Corner"; 00079 static const std::string REFBOX_PENALTY = "Penalty"; 00080 00081 static const std::string REFBOX_TEAMCOLOR_CYAN = "Cyan"; 00082 static const std::string REFBOX_TEAMCOLOR_MAGENTA = "Magenta"; 00083 00084 static const std::string REFBOX_GOALCOLOR_YELLOW = "yellow"; 00085 static const std::string REFBOX_GOALCOLOR_BLUE = "blue"; 00086 00087 static const std::string REFBOX_CARDCOLOR_YELLOW = "yellow"; 00088 static const std::string REFBOX_CARDCOLOR_RED = "red"; 00089 00090 00091 /** @class Msl2010RefBoxRepeater <tools/refboxrep/msl2010.h> 00092 * Mid-size league refbox repeater. 00093 * This class will communicate with the mid-size league refbox and derive matching 00094 * game states from the communiation stream and send this via the world info. 00095 * @author Stefan Schiffer 00096 */ 00097 00098 /** Constructor. 00099 * @param rss refbox state sender 00100 * @param refbox_host refbox host 00101 * @param refbox_port refbox port 00102 * @param use_multicast use multicast connection (true by default) 00103 */ 00104 Msl2010RefBoxRepeater::Msl2010RefBoxRepeater(RefBoxStateSender &rss, 00105 const char *refbox_host, 00106 unsigned short int refbox_port, 00107 const bool use_multicast ) 00108 : __rss(rss) 00109 { 00110 __quit = false; 00111 __s = NULL; 00112 __score_cyan = __score_magenta = 0; 00113 00114 __refbox_host = strdup(refbox_host); 00115 __refbox_port = refbox_port; 00116 00117 __use_multicast = use_multicast; 00118 00119 reconnect(); 00120 } 00121 00122 00123 /** Destructor. */ 00124 Msl2010RefBoxRepeater::~Msl2010RefBoxRepeater() 00125 { 00126 free(__refbox_host); 00127 __s->close(); 00128 delete __s; 00129 } 00130 00131 00132 /** Reconnect to refbox. */ 00133 void 00134 Msl2010RefBoxRepeater::reconnect() 00135 { 00136 if ( __s ) { 00137 __s->close(); 00138 delete __s; 00139 } 00140 printf("Trying to connect to refbox at %s:%u\n", __refbox_host, __refbox_port); 00141 do { 00142 try { 00143 00144 if( __use_multicast ) { 00145 00146 printf("Creating MulticastDatagramSocket\n"); 00147 __s = new MulticastDatagramSocket(__refbox_host, __refbox_port, 2.3); 00148 //printf("set loop\n"); 00149 ((MulticastDatagramSocket *)__s)->set_loop(true); // (re)receive locally sent stuff 00150 //printf("bind\n"); 00151 ((MulticastDatagramSocket *)__s)->bind(); 00152 //printf("bind done\n"); 00153 00154 printf("check for data availability ...\n"); 00155 if ( !__s->available() ) { 00156 printf("... nothing to receive\n"); 00157 } else { 00158 printf("... data is available!\n"); 00159 } 00160 00161 } 00162 else { 00163 00164 __s = new StreamSocket(); 00165 __s->connect(__refbox_host, __refbox_port); 00166 00167 // char welcombuf[strlen(REFBOX_WELCOME) + 1]; 00168 // welcombuf[strlen(REFBOX_WELCOME)] = 0; 00169 // char connectbuf[strlen(REFBOX_RECONNECT) + 1]; 00170 // connectbuf[strlen(REFBOX_RECONNECT)] = 0; 00171 // __s->read(connectbuf, strlen(REFBOX_RECONNECT)); 00172 // printf("Received welcome string: %s\n", connectbuf); 00173 00174 } 00175 00176 } catch (Exception &e) { 00177 delete __s; 00178 __s = NULL; 00179 printf("%s",e.what()); 00180 printf("\n."); 00181 fflush(stdout); 00182 usleep(500000); 00183 } 00184 } while ( ! __s ); 00185 00186 printf("Connected.\n"); 00187 } 00188 00189 00190 /** Process received string. */ 00191 void 00192 Msl2010RefBoxRepeater::process_string(char *buf, size_t len) 00193 { 00194 printf("Received\n *****\n %s \n *****\n", buf); 00195 00196 std::istringstream iss( std::string(buf), std::istringstream::in); 00197 00198 dom = new DomParser(); 00199 //dom->set_validate(); 00200 dom->set_substitute_entities(); 00201 dom->parse_stream(iss); 00202 root = dom->get_document()->get_root_node(); 00203 00204 //printf( " root node:\n%s\n", root->get_name().data() ); 00205 00206 const Element * el = dynamic_cast<const Element *>(root); 00207 00208 if ( el ) { 00209 /// valid element 00210 //printf("Is valid Element\n"); 00211 printf("root-element name is '%s'\n", el->get_name().data() ); 00212 00213 const Node::NodeList nl = el->get_children(); 00214 00215 if( nl.size() == 0 ) { 00216 printf("root has NO children!\n"); 00217 } 00218 else { 00219 //printf("root has %u children!\n", nl.size()); 00220 00221 for (Node::NodeList::const_iterator it = nl.begin(); it != nl.end(); ++it) { 00222 const Node* node = *it; 00223 printf("1st level child name is '%s'\n", node->get_name().data() ); 00224 00225 //if( node->get_name().data() == REFBOX_GAMEINFO ) { 00226 // 00227 //} 00228 //else if( node->get_name().data() == REFBOX_EVENT ) { 00229 // 00230 //} 00231 //else { 00232 // printf(" unhandled RefboxMessage-type '%s'!\n", node->get_name().data() ); 00233 //} 00234 00235 const Node::NodeList cnl = node->get_children(); 00236 00237 if( cnl.size() == 0 ) { 00238 printf("child has NO children!\n"); 00239 } 00240 else { 00241 //printf("child has %u children!\n", nl.size()); 00242 00243 for (Node::NodeList::const_iterator cit = cnl.begin(); cit != cnl.end(); ++cit) { 00244 const Node* cnode = *cit; 00245 const Element* cel = dynamic_cast<const Element *>(cnode); 00246 std::string cnodename(cnode->get_name().data()); 00247 00248 printf("2nd level child name is '%s'\n", cnode->get_name().data() ); 00249 00250 const Attribute* cattr; 00251 std::string cteamcolor; 00252 //std::string cgoalcolor; 00253 //std::string ccardcolor; 00254 std::string cstagetype; 00255 00256 if( cnodename == REFBOX_KICKOFF || cnodename == REFBOX_FREEKICK || 00257 cnodename == REFBOX_GOALKICK || cnodename == REFBOX_THROWIN || 00258 cnodename == REFBOX_CORNER || cnodename == REFBOX_PENALTY || 00259 cnodename == REFBOX_GOAL_AWARDED || cnodename == REFBOX_GOAL_REMOVED || 00260 cnodename == REFBOX_CARD_AWARDED || cnodename == REFBOX_CARD_REMOVED || 00261 cnodename == REFBOX_PLAYER_OUT || cnodename == REFBOX_PLAYER_IN || 00262 cnodename == REFBOX_SUBSTITUTION ) 00263 { 00264 cattr = cel->get_attribute("team"); 00265 cteamcolor = std::string( cattr->get_value().data() ); 00266 } 00267 00268 if( cnodename == REFBOX_CANCEL ) { 00269 // refbox canceled last command 00270 printf("RefBox cancelled last command\n"); 00271 } 00272 else if( cnodename == REFBOX_GAMESTOP ) { 00273 printf("sending command: REFBOX_GAMESTOP\n"); 00274 __rss.set_gamestate(GS_FROZEN, TEAM_BOTH); 00275 } 00276 else if( cnodename == REFBOX_GAMESTART ) { 00277 printf("sending command: REFBOX_GAMESTART\n"); 00278 __rss.set_gamestate(GS_PLAY, TEAM_BOTH); 00279 } 00280 else if( cnodename == REFBOX_DROPPEDBALL ) { 00281 printf("sending command: REFBOX_DROPPEDBALL\n"); 00282 __rss.set_gamestate(GS_DROP_BALL, TEAM_BOTH); 00283 } 00284 else if( cnodename == REFBOX_GOAL_AWARDED ) { 00285 // increment according to color 00286 if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) { 00287 printf("sending command: REFBOX_TEAMCOLOR_CYAN\n"); 00288 __rss.set_score(++__score_cyan, __score_magenta); 00289 } 00290 else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) { 00291 printf("sending command: REFBOX_TEAMCOLOR_MAGENTA\n"); 00292 __rss.set_score(__score_cyan, ++__score_magenta); 00293 } 00294 printf("sending command: GS_FROZEN\n"); 00295 __rss.set_gamestate(GS_FROZEN, TEAM_BOTH); 00296 } 00297 else if( cnodename == REFBOX_KICKOFF ) { 00298 if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) { 00299 printf("sending command: GS_KICK_OFF, TEAM_CYAN\n"); 00300 __rss.set_gamestate(GS_KICK_OFF, TEAM_CYAN); 00301 } 00302 else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) { 00303 printf("sending command: GS_KICK_OFF, TEAM_MAGENTA\n"); 00304 __rss.set_gamestate(GS_KICK_OFF, TEAM_MAGENTA); 00305 } 00306 } 00307 else if( cnodename == REFBOX_PENALTY ) { 00308 if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) { 00309 __rss.set_gamestate(GS_PENALTY, TEAM_CYAN); 00310 } 00311 else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) { 00312 __rss.set_gamestate(GS_PENALTY, TEAM_MAGENTA); 00313 } 00314 } 00315 else if( cnodename == REFBOX_CORNER ) { 00316 if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) { 00317 __rss.set_gamestate(GS_CORNER_KICK, TEAM_CYAN); 00318 } 00319 else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) { 00320 __rss.set_gamestate(GS_CORNER_KICK, TEAM_MAGENTA); 00321 } 00322 } 00323 else if( cnodename == REFBOX_THROWIN ) { 00324 if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) { 00325 __rss.set_gamestate(GS_THROW_IN, TEAM_CYAN); 00326 } 00327 else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) { 00328 __rss.set_gamestate(GS_THROW_IN, TEAM_MAGENTA); 00329 } 00330 } 00331 else if( cnodename == REFBOX_FREEKICK ) { 00332 if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) { 00333 __rss.set_gamestate(GS_FREE_KICK, TEAM_CYAN); 00334 } 00335 else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) { 00336 __rss.set_gamestate(GS_FREE_KICK, TEAM_MAGENTA); 00337 } 00338 } 00339 else if( cnodename == REFBOX_GOALKICK ) { 00340 if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) { 00341 __rss.set_gamestate(GS_GOAL_KICK, TEAM_CYAN); 00342 } 00343 else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) { 00344 __rss.set_gamestate(GS_GOAL_KICK, TEAM_MAGENTA); 00345 } 00346 } 00347 else if( cnodename == REFBOX_STAGE_CHANGED ) { 00348 cattr = cel->get_attribute("newStage"); 00349 cstagetype = std::string( cattr->get_value().data() ); 00350 if( cstagetype == REFBOX_STAGETYPE_PREGAME ) { 00351 // 00352 } else if( cstagetype == REFBOX_STAGETYPE_FIRSTHALF ) { 00353 __rss.set_half(HALF_FIRST); 00354 } else if( cstagetype == REFBOX_STAGETYPE_HALFTIME ) { 00355 __rss.set_gamestate(GS_HALF_TIME, TEAM_BOTH); 00356 } else if( cstagetype == REFBOX_STAGETYPE_SECONDHALF ) { 00357 __rss.set_half(HALF_SECOND); 00358 } else if( cstagetype == REFBOX_STAGETYPE_SHOOTOUT ) { 00359 // 00360 } else if( cstagetype == REFBOX_STAGETYPE_ENDGAME ) { 00361 // 00362 } 00363 00364 } 00365 00366 } // end-for "child-node children list iteration" 00367 } // end-if "child-node has children" 00368 } // end-for "root children list iteration" 00369 } // end-if "root has children" 00370 } 00371 else { 00372 // throw RefBoxParserException("root is not an element"); 00373 printf("root is NOT a valid element\n"); 00374 } 00375 00376 __rss.send(); 00377 } 00378 00379 00380 /** Run. 00381 * Reads messages from the network, processes them and calls the refbox state sender. 00382 */ 00383 void 00384 Msl2010RefBoxRepeater::run() 00385 { 00386 //char tmpbuf[4096]; 00387 char tmpbuf[1024]; 00388 while ( ! __quit ) { 00389 size_t bytes_read = __s->read(tmpbuf, sizeof(tmpbuf), /* read all */ false); 00390 //size_t bytes_read = __s->read(tmpbuf, sizeof(tmpbuf), /* read all */ true ); 00391 if ( bytes_read == 0 ) { 00392 // seems that the remote has died, reconnect 00393 printf("Connection died, reconnecting\n"); 00394 reconnect(); 00395 } else { 00396 printf("Received %zu bytes, processing ...\n", bytes_read); 00397 tmpbuf[bytes_read] = '\0'; 00398 process_string(tmpbuf, bytes_read); 00399 } 00400 } 00401 }