msl2010.cpp

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 }

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1