Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
msl2010.cpp
1 
2 /***************************************************************************
3  * msl2010.cpp - Fawkes mid-size refbox 2010 protocol repeater
4  *
5  * Created: Wed Apr 01 18:41:00 2010
6  * Copyright 2010 Stefan Schiffer [stefanschiffer.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include <tools/refboxrep/msl2010.h>
24 #include <netcomm/socket/stream.h>
25 #include <netcomm/socket/datagram_multicast.h>
26 
27 #include <cstring>
28 #include <cstdio>
29 #include <unistd.h>
30 #include <iostream>
31 #include <sstream>
32 #include <string>
33 
34 #include <libxml++/libxml++.h>
35 
36 using namespace fawkes;
37 using namespace xmlpp;
38 
39 
40 // REFBOX_CODES //////////////////////////
41 
42 //static const char * REFBOX_WELCOME = "Welcome";
43 //static const char * REFBOX_RECONNECT = "Reconnect";
44 
45 static const std::string REFBOX_EVENT = "RefboxEvent";
46 static const std::string REFBOX_GAMEINFO = "GameInfo";
47 static const std::string REFBOX_EVENT_REFEREE = "Referee";
48 static const std::string REFBOX_EVENT_TEAMSETUP = "TeamSetup";
49 
50 static const std::string REFBOX_CANCEL = "Cancel";
51 
52 static const std::string REFBOX_GAMESTART = "GameStart";
53 static const std::string REFBOX_GAMESTOP = "GameStop";
54 
55 static const std::string REFBOX_STAGE_CHANGED = "StageChanged";
56 static const std::string REFBOX_STAGETYPE_PREGAME = "preGame";
57 static const std::string REFBOX_STAGETYPE_FIRSTHALF = "firstHalf";
58 static const std::string REFBOX_STAGETYPE_HALFTIME = "halfTime";
59 static const std::string REFBOX_STAGETYPE_SECONDHALF = "secondHalf";
60 static const std::string REFBOX_STAGETYPE_SHOOTOUT = "shootOut";
61 static const std::string REFBOX_STAGETYPE_ENDGAME = "endGame";
62 
63 static const std::string REFBOX_GOAL_AWARDED = "GoalAwarded";
64 static const std::string REFBOX_GOAL_REMOVED = "GoalRemoved";
65 
66 static const std::string REFBOX_CARD_AWARDED = "CardAwarded";
67 static const std::string REFBOX_CARD_REMOVED = "CardRemoved";
68 
69 static const std::string REFBOX_SUBSTITUTION = "Substitution";
70 static const std::string REFBOX_PLAYER_OUT = "PlayerOut";
71 static const std::string REFBOX_PLAYER_IN = "PlayerIn";
72 
73 static const std::string REFBOX_DROPPEDBALL = "DroppedBall";
74 static const std::string REFBOX_KICKOFF = "KickOff";
75 static const std::string REFBOX_FREEKICK = "FreeKick";
76 static const std::string REFBOX_GOALKICK = "GoalKick";
77 static const std::string REFBOX_THROWIN = "ThrowIn";
78 static const std::string REFBOX_CORNER = "Corner";
79 static const std::string REFBOX_PENALTY = "Penalty";
80 
81 static const std::string REFBOX_TEAMCOLOR_CYAN = "Cyan";
82 static const std::string REFBOX_TEAMCOLOR_MAGENTA = "Magenta";
83 
84 static const std::string REFBOX_GOALCOLOR_YELLOW = "yellow";
85 static const std::string REFBOX_GOALCOLOR_BLUE = "blue";
86 
87 static const std::string REFBOX_CARDCOLOR_YELLOW = "yellow";
88 static const std::string REFBOX_CARDCOLOR_RED = "red";
89 
90 
91 /** @class Msl2010RefBoxRepeater <tools/refboxrep/msl2010.h>
92  * Mid-size league refbox repeater.
93  * This class will communicate with the mid-size league refbox and derive matching
94  * game states from the communiation stream and send this via the world info.
95  * @author Stefan Schiffer
96  */
97 
98 /** Constructor.
99  * @param rss refbox state sender
100  * @param refbox_host refbox host
101  * @param refbox_port refbox port
102  * @param use_multicast use multicast connection (true by default)
103  */
105  const char *refbox_host,
106  unsigned short int refbox_port,
107  const bool use_multicast )
108  : __rss(rss)
109 {
110  __quit = false;
111  __s = NULL;
112  __score_cyan = __score_magenta = 0;
113 
114  __refbox_host = strdup(refbox_host);
115  __refbox_port = refbox_port;
116 
117  __use_multicast = use_multicast;
118 
119  reconnect();
120 }
121 
122 
123 /** Destructor. */
125 {
126  free(__refbox_host);
127  __s->close();
128  delete __s;
129 }
130 
131 
132 /** Reconnect to refbox. */
133 void
134 Msl2010RefBoxRepeater::reconnect()
135 {
136  if ( __s ) {
137  __s->close();
138  delete __s;
139  }
140  printf("Trying to connect to refbox at %s:%u\n", __refbox_host, __refbox_port);
141  do {
142  try {
143 
144  if( __use_multicast ) {
145 
146  printf("Creating MulticastDatagramSocket\n");
147  __s = new MulticastDatagramSocket(__refbox_host, __refbox_port, 2.3);
148  //printf("set loop\n");
149  ((MulticastDatagramSocket *)__s)->set_loop(true); // (re)receive locally sent stuff
150  //printf("bind\n");
151  ((MulticastDatagramSocket *)__s)->bind();
152  //printf("bind done\n");
153 
154  printf("check for data availability ...\n");
155  if ( !__s->available() ) {
156  printf("... nothing to receive\n");
157  } else {
158  printf("... data is available!\n");
159  }
160 
161  }
162  else {
163 
164  __s = new StreamSocket();
165  __s->connect(__refbox_host, __refbox_port);
166 
167 // char welcombuf[strlen(REFBOX_WELCOME) + 1];
168 // welcombuf[strlen(REFBOX_WELCOME)] = 0;
169 // char connectbuf[strlen(REFBOX_RECONNECT) + 1];
170 // connectbuf[strlen(REFBOX_RECONNECT)] = 0;
171 // __s->read(connectbuf, strlen(REFBOX_RECONNECT));
172 // printf("Received welcome string: %s\n", connectbuf);
173 
174  }
175 
176  } catch (Exception &e) {
177  delete __s;
178  __s = NULL;
179  printf("%s",e.what());
180  printf("\n.");
181  fflush(stdout);
182  usleep(500000);
183  }
184  } while ( ! __s );
185 
186  printf("Connected.\n");
187 }
188 
189 
190 /** Process received string. */
191 void
192 Msl2010RefBoxRepeater::process_string(char *buf, size_t len)
193 {
194  printf("Received\n *****\n %s \n *****\n", buf);
195 
196  std::istringstream iss( std::string(buf), std::istringstream::in);
197 
198  dom = new DomParser();
199  //dom->set_validate();
200  dom->set_substitute_entities();
201  dom->parse_stream(iss);
202  root = dom->get_document()->get_root_node();
203 
204  //printf( " root node:\n%s\n", root->get_name().data() );
205 
206  const Element * el = dynamic_cast<const Element *>(root);
207 
208  if ( el ) {
209  /// valid element
210  //printf("Is valid Element\n");
211  printf("root-element name is '%s'\n", el->get_name().data() );
212 
213  const Node::NodeList nl = el->get_children();
214 
215  if( nl.size() == 0 ) {
216  printf("root has NO children!\n");
217  }
218  else {
219  //printf("root has %u children!\n", nl.size());
220 
221  for (Node::NodeList::const_iterator it = nl.begin(); it != nl.end(); ++it) {
222  const Node* node = *it;
223  printf("1st level child name is '%s'\n", node->get_name().data() );
224 
225  //if( node->get_name().data() == REFBOX_GAMEINFO ) {
226  //
227  //}
228  //else if( node->get_name().data() == REFBOX_EVENT ) {
229  //
230  //}
231  //else {
232  // printf(" unhandled RefboxMessage-type '%s'!\n", node->get_name().data() );
233  //}
234 
235  const Node::NodeList cnl = node->get_children();
236 
237  if( cnl.size() == 0 ) {
238  printf("child has NO children!\n");
239  }
240  else {
241  //printf("child has %u children!\n", nl.size());
242 
243  for (Node::NodeList::const_iterator cit = cnl.begin(); cit != cnl.end(); ++cit) {
244  const Node* cnode = *cit;
245  const Element* cel = dynamic_cast<const Element *>(cnode);
246  std::string cnodename(cnode->get_name().data());
247 
248  printf("2nd level child name is '%s'\n", cnode->get_name().data() );
249 
250  const Attribute* cattr;
251  std::string cteamcolor;
252  //std::string cgoalcolor;
253  //std::string ccardcolor;
254  std::string cstagetype;
255 
256  if( cnodename == REFBOX_KICKOFF || cnodename == REFBOX_FREEKICK ||
257  cnodename == REFBOX_GOALKICK || cnodename == REFBOX_THROWIN ||
258  cnodename == REFBOX_CORNER || cnodename == REFBOX_PENALTY ||
259  cnodename == REFBOX_GOAL_AWARDED || cnodename == REFBOX_GOAL_REMOVED ||
260  cnodename == REFBOX_CARD_AWARDED || cnodename == REFBOX_CARD_REMOVED ||
261  cnodename == REFBOX_PLAYER_OUT || cnodename == REFBOX_PLAYER_IN ||
262  cnodename == REFBOX_SUBSTITUTION )
263  {
264  cattr = cel->get_attribute("team");
265  cteamcolor = std::string( cattr->get_value().data() );
266  }
267 
268  if( cnodename == REFBOX_CANCEL ) {
269  // refbox canceled last command
270  printf("RefBox cancelled last command\n");
271  }
272  else if( cnodename == REFBOX_GAMESTOP ) {
273  printf("sending command: REFBOX_GAMESTOP\n");
274  __rss.set_gamestate(GS_FROZEN, TEAM_BOTH);
275  }
276  else if( cnodename == REFBOX_GAMESTART ) {
277  printf("sending command: REFBOX_GAMESTART\n");
278  __rss.set_gamestate(GS_PLAY, TEAM_BOTH);
279  }
280  else if( cnodename == REFBOX_DROPPEDBALL ) {
281  printf("sending command: REFBOX_DROPPEDBALL\n");
282  __rss.set_gamestate(GS_DROP_BALL, TEAM_BOTH);
283  }
284  else if( cnodename == REFBOX_GOAL_AWARDED ) {
285  // increment according to color
286  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
287  printf("sending command: REFBOX_TEAMCOLOR_CYAN\n");
288  __rss.set_score(++__score_cyan, __score_magenta);
289  }
290  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
291  printf("sending command: REFBOX_TEAMCOLOR_MAGENTA\n");
292  __rss.set_score(__score_cyan, ++__score_magenta);
293  }
294  printf("sending command: GS_FROZEN\n");
295  __rss.set_gamestate(GS_FROZEN, TEAM_BOTH);
296  }
297  else if( cnodename == REFBOX_KICKOFF ) {
298  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
299  printf("sending command: GS_KICK_OFF, TEAM_CYAN\n");
300  __rss.set_gamestate(GS_KICK_OFF, TEAM_CYAN);
301  }
302  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
303  printf("sending command: GS_KICK_OFF, TEAM_MAGENTA\n");
304  __rss.set_gamestate(GS_KICK_OFF, TEAM_MAGENTA);
305  }
306  }
307  else if( cnodename == REFBOX_PENALTY ) {
308  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
309  __rss.set_gamestate(GS_PENALTY, TEAM_CYAN);
310  }
311  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
312  __rss.set_gamestate(GS_PENALTY, TEAM_MAGENTA);
313  }
314  }
315  else if( cnodename == REFBOX_CORNER ) {
316  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
317  __rss.set_gamestate(GS_CORNER_KICK, TEAM_CYAN);
318  }
319  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
320  __rss.set_gamestate(GS_CORNER_KICK, TEAM_MAGENTA);
321  }
322  }
323  else if( cnodename == REFBOX_THROWIN ) {
324  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
325  __rss.set_gamestate(GS_THROW_IN, TEAM_CYAN);
326  }
327  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
328  __rss.set_gamestate(GS_THROW_IN, TEAM_MAGENTA);
329  }
330  }
331  else if( cnodename == REFBOX_FREEKICK ) {
332  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
333  __rss.set_gamestate(GS_FREE_KICK, TEAM_CYAN);
334  }
335  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
336  __rss.set_gamestate(GS_FREE_KICK, TEAM_MAGENTA);
337  }
338  }
339  else if( cnodename == REFBOX_GOALKICK ) {
340  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
341  __rss.set_gamestate(GS_GOAL_KICK, TEAM_CYAN);
342  }
343  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
344  __rss.set_gamestate(GS_GOAL_KICK, TEAM_MAGENTA);
345  }
346  }
347  else if( cnodename == REFBOX_STAGE_CHANGED ) {
348  cattr = cel->get_attribute("newStage");
349  cstagetype = std::string( cattr->get_value().data() );
350  if( cstagetype == REFBOX_STAGETYPE_PREGAME ) {
351  //
352  } else if( cstagetype == REFBOX_STAGETYPE_FIRSTHALF ) {
353  __rss.set_half(HALF_FIRST);
354  } else if( cstagetype == REFBOX_STAGETYPE_HALFTIME ) {
355  __rss.set_gamestate(GS_HALF_TIME, TEAM_BOTH);
356  } else if( cstagetype == REFBOX_STAGETYPE_SECONDHALF ) {
357  __rss.set_half(HALF_SECOND);
358  } else if( cstagetype == REFBOX_STAGETYPE_SHOOTOUT ) {
359  //
360  } else if( cstagetype == REFBOX_STAGETYPE_ENDGAME ) {
361  //
362  }
363 
364  }
365 
366  } // end-for "child-node children list iteration"
367  } // end-if "child-node has children"
368  } // end-for "root children list iteration"
369  } // end-if "root has children"
370  }
371  else {
372  // throw RefBoxParserException("root is not an element");
373  printf("root is NOT a valid element\n");
374  }
375 
376  __rss.send();
377 }
378 
379 
380 /** Run.
381  * Reads messages from the network, processes them and calls the refbox state sender.
382  */
383 void
385 {
386  //char tmpbuf[4096];
387  char tmpbuf[1024];
388  while ( ! __quit ) {
389  size_t bytes_read = __s->read(tmpbuf, sizeof(tmpbuf), /* read all */ false);
390  //size_t bytes_read = __s->read(tmpbuf, sizeof(tmpbuf), /* read all */ true );
391  if ( bytes_read == 0 ) {
392  // seems that the remote has died, reconnect
393  printf("Connection died, reconnecting\n");
394  reconnect();
395  } else {
396  printf("Received %zu bytes, processing ...\n", bytes_read);
397  tmpbuf[bytes_read] = '\0';
398  process_string(tmpbuf, bytes_read);
399  }
400  }
401 }