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