Fawkes API  Fawkes Development Version
msl2008.cpp
1 
2 /***************************************************************************
3  * msl2008.cpp - Fawkes mid-size refbox 2008 protocol repeater
4  *
5  * Created: Wed Apr 09 10:38:16 2008
6  * Copyright 2008 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/msl2008.h>
24 #include <netcomm/socket/datagram_multicast.h>
25 
26 #include <cstring>
27 #include <cstdio>
28 #include <unistd.h>
29 #include <iostream>
30 #include <sstream>
31 #include <string>
32 
33 #include <libxml++/libxml++.h>
34 
35 using namespace fawkes;
36 using namespace xmlpp;
37 
38 
39 // REFBOX_CODES //////////////////////////
40 
41 static const std::string REFBOX_EVENT = "RefboxEvent";
42 static const std::string REFBOX_GAMEINFO = "GameInfo";
43 static const std::string REFBOX_EVENT_REFEREE = "Referee";
44 static const std::string REFBOX_EVENT_TEAMSETUP = "TeamSetup";
45 
46 static const std::string REFBOX_CANCEL = "Cancel";
47 
48 static const std::string REFBOX_GAMESTART = "GameStart";
49 static const std::string REFBOX_GAMESTOP = "GameStop";
50 
51 static const std::string REFBOX_STAGE_CHANGED = "StageChanged";
52 static const std::string REFBOX_STAGETYPE_PREGAME = "preGame";
53 static const std::string REFBOX_STAGETYPE_FIRSTHALF = "firstHalf";
54 static const std::string REFBOX_STAGETYPE_HALFTIME = "halfTime";
55 static const std::string REFBOX_STAGETYPE_SECONDHALF = "secondHalf";
56 static const std::string REFBOX_STAGETYPE_SHOOTOUT = "shootOut";
57 static const std::string REFBOX_STAGETYPE_ENDGAME = "endGame";
58 
59 static const std::string REFBOX_GOAL_AWARDED = "GoalAwarded";
60 static const std::string REFBOX_GOAL_REMOVED = "GoalRemoved";
61 
62 static const std::string REFBOX_CARD_AWARDED = "CardAwarded";
63 static const std::string REFBOX_CARD_REMOVED = "CardRemoved";
64 
65 static const std::string REFBOX_SUBSTITUTION = "Substitution";
66 static const std::string REFBOX_PLAYER_OUT = "PlayerOut";
67 static const std::string REFBOX_PLAYER_IN = "PlayerIn";
68 
69 static const std::string REFBOX_DROPPEDBALL = "DroppedBall";
70 static const std::string REFBOX_KICKOFF = "KickOff";
71 static const std::string REFBOX_FREEKICK = "FreeKick";
72 static const std::string REFBOX_GOALKICK = "GoalKick";
73 static const std::string REFBOX_THROWIN = "ThrowIn";
74 static const std::string REFBOX_CORNER = "Corner";
75 static const std::string REFBOX_PENALTY = "Penalty";
76 
77 static const std::string REFBOX_TEAMCOLOR_CYAN = "Cyan";
78 static const std::string REFBOX_TEAMCOLOR_MAGENTA = "Magenta";
79 
80 static const std::string REFBOX_GOALCOLOR_YELLOW = "yellow";
81 static const std::string REFBOX_GOALCOLOR_BLUE = "blue";
82 
83 static const std::string REFBOX_CARDCOLOR_YELLOW = "yellow";
84 static const std::string REFBOX_CARDCOLOR_RED = "red";
85 
86 
87 /** @class Msl2008RefBoxRepeater <tools/refboxrep/msl2008.h>
88  * Mid-size league refbox repeater.
89  * This class will communicate with the mid-size league refbox and derive matching
90  * game states from the communiation stream and send this via the world info.
91  * @author Stefan Schiffer
92  */
93 
94 /** Constructor.
95  * @param rss refbox state sender
96  * @param refbox_host refbox host
97  * @param refbox_port refbox port
98  */
100  const char *refbox_host,
101  unsigned short int refbox_port)
102  : __rss(rss)
103 {
104  __quit = false;
105  __s = NULL;
106  __score_cyan = __score_magenta = 0;
107 
108  __refbox_host = strdup(refbox_host);
109  __refbox_port = refbox_port;
110 
111  reconnect();
112 }
113 
114 
115 /** Destructor. */
117 {
118  free(__refbox_host);
119  __s->close();
120  delete __s;
121 }
122 
123 
124 /** Reconnect to refbox. */
125 void
126 Msl2008RefBoxRepeater::reconnect()
127 {
128  if ( __s ) {
129  __s->close();
130  delete __s;
131  }
132  printf("Trying to connect to refbox at %s:%u\n", __refbox_host, __refbox_port);
133  do {
134  try {
135  printf("Creating MulticastDatagramSocket\n");
136  __s = new MulticastDatagramSocket(__refbox_host, __refbox_port, 2.3);
137  //printf("set loop\n");
138  __s->set_loop(true); // (re)receive locally sent stuff
139  //printf("bind\n");
140  __s->bind();
141  //printf("bind done\n");
142 
143  // printf("check for data availability ...\n");
144  // if ( !__s->available() ) {
145  // printf("... nothing to receive\n");
146  // } else {
147  // printf("... data is available!\n");
148  // }
149 
150  } catch (Exception &e) {
151  delete __s;
152  __s = NULL;
153  printf(".");
154  fflush(stdout);
155  usleep(500000);
156  }
157  } while ( ! __s );
158 }
159 
160 
161 /** Process received string. */
162 void
163 Msl2008RefBoxRepeater::process_string(char *buf, size_t len)
164 {
165  printf("Received\n *****\n %s \n *****\n", buf);
166 
167  std::istringstream iss( std::string(buf), std::istringstream::in);
168 
169  dom = new DomParser();
170  //dom->set_validate();
171  dom->set_substitute_entities();
172  dom->parse_stream(iss);
173  root = dom->get_document()->get_root_node();
174 
175  //printf( " root node:\n%s\n", root->get_name().data() );
176 
177  const Element * el = dynamic_cast<const Element *>(root);
178 
179  if ( el ) {
180  /// valid element
181  //printf("Is valid Element\n");
182  printf("root-element name is '%s'\n", el->get_name().data() );
183 
184  const Node::NodeList nl = el->get_children();
185 
186  if( nl.size() == 0 ) {
187  printf("root has NO children!\n");
188  }
189  else {
190  //printf("root has %u children!\n", nl.size());
191 
192  for (Node::NodeList::const_iterator it = nl.begin(); it != nl.end(); ++it) {
193  const Node* node = *it;
194  printf("1st level child name is '%s'\n", node->get_name().data() );
195 
196  //if( node->get_name().data() == REFBOX_GAMEINFO ) {
197  //
198  //}
199  //else if( node->get_name().data() == REFBOX_EVENT ) {
200  //
201  //}
202  //else {
203  // printf(" unhandled RefboxMessage-type '%s'!\n", node->get_name().data() );
204  //}
205 
206  const Node::NodeList cnl = node->get_children();
207 
208  if( cnl.size() == 0 ) {
209  printf("child has NO children!\n");
210  }
211  else {
212  //printf("child has %u children!\n", nl.size());
213 
214  for (Node::NodeList::const_iterator cit = cnl.begin(); cit != cnl.end(); ++cit) {
215  const Node* cnode = *cit;
216  const Element* cel = dynamic_cast<const Element *>(cnode);
217  std::string cnodename(cnode->get_name().data());
218 
219  printf("2nd level child name is '%s'\n", cnode->get_name().data() );
220 
221  const Attribute* cattr;
222  std::string cteamcolor;
223  //std::string cgoalcolor;
224  //std::string ccardcolor;
225  std::string cstagetype;
226 
227  if( cnodename == REFBOX_KICKOFF || cnodename == REFBOX_FREEKICK ||
228  cnodename == REFBOX_GOALKICK || cnodename == REFBOX_THROWIN ||
229  cnodename == REFBOX_CORNER || cnodename == REFBOX_PENALTY ||
230  cnodename == REFBOX_GOAL_AWARDED || cnodename == REFBOX_GOAL_REMOVED ||
231  cnodename == REFBOX_CARD_AWARDED || cnodename == REFBOX_CARD_REMOVED ||
232  cnodename == REFBOX_PLAYER_OUT || cnodename == REFBOX_PLAYER_IN ||
233  cnodename == REFBOX_SUBSTITUTION )
234  {
235  cattr = cel->get_attribute("team");
236  cteamcolor = std::string( cattr->get_value().data() );
237  }
238 
239  if( cnodename == REFBOX_CANCEL ) {
240  // refbox canceled last command
241  printf("RefBox cancelled last command\n");
242  }
243  else if( cnodename == REFBOX_GAMESTOP ) {
244  __rss.set_gamestate(GS_FROZEN, TEAM_BOTH);
245  }
246  else if( cnodename == REFBOX_GAMESTART ) {
247  __rss.set_gamestate(GS_PLAY, TEAM_BOTH);
248  }
249  else if( cnodename == REFBOX_DROPPEDBALL ) {
250  __rss.set_gamestate(GS_DROP_BALL, TEAM_BOTH);
251  }
252  else if( cnodename == REFBOX_GOAL_AWARDED ) {
253  // increment according to color
254  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
255  __rss.set_score(++__score_cyan, __score_magenta);
256  }
257  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
258  __rss.set_score(__score_cyan, ++__score_magenta);
259  }
260  __rss.set_gamestate(GS_FROZEN, TEAM_BOTH);
261  }
262  else if( cnodename == REFBOX_KICKOFF ) {
263  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
264  __rss.set_gamestate(GS_KICK_OFF, TEAM_CYAN);
265  }
266  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
267  __rss.set_gamestate(GS_KICK_OFF, TEAM_MAGENTA);
268  }
269  }
270  else if( cnodename == REFBOX_PENALTY ) {
271  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
272  __rss.set_gamestate(GS_PENALTY, TEAM_CYAN);
273  }
274  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
275  __rss.set_gamestate(GS_PENALTY, TEAM_MAGENTA);
276  }
277  }
278  else if( cnodename == REFBOX_CORNER ) {
279  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
280  __rss.set_gamestate(GS_CORNER_KICK, TEAM_CYAN);
281  }
282  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
283  __rss.set_gamestate(GS_CORNER_KICK, TEAM_MAGENTA);
284  }
285  }
286  else if( cnodename == REFBOX_THROWIN ) {
287  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
288  __rss.set_gamestate(GS_THROW_IN, TEAM_CYAN);
289  }
290  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
291  __rss.set_gamestate(GS_THROW_IN, TEAM_MAGENTA);
292  }
293  }
294  else if( cnodename == REFBOX_FREEKICK ) {
295  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
296  __rss.set_gamestate(GS_FREE_KICK, TEAM_CYAN);
297  }
298  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
299  __rss.set_gamestate(GS_FREE_KICK, TEAM_MAGENTA);
300  }
301  }
302  else if( cnodename == REFBOX_GOALKICK ) {
303  if( cteamcolor == REFBOX_TEAMCOLOR_CYAN ) {
304  __rss.set_gamestate(GS_GOAL_KICK, TEAM_CYAN);
305  }
306  else if ( cteamcolor == REFBOX_TEAMCOLOR_MAGENTA ) {
307  __rss.set_gamestate(GS_GOAL_KICK, TEAM_MAGENTA);
308  }
309  }
310  else if( cnodename == REFBOX_STAGE_CHANGED ) {
311  cattr = cel->get_attribute("newStage");
312  cstagetype = std::string( cattr->get_value().data() );
313  if( cstagetype == REFBOX_STAGETYPE_PREGAME ) {
314  //
315  } else if( cstagetype == REFBOX_STAGETYPE_FIRSTHALF ) {
316  __rss.set_half(HALF_FIRST);
317  } else if( cstagetype == REFBOX_STAGETYPE_HALFTIME ) {
318  __rss.set_gamestate(GS_HALF_TIME, TEAM_BOTH);
319  } else if( cstagetype == REFBOX_STAGETYPE_SECONDHALF ) {
320  __rss.set_half(HALF_SECOND);
321  } else if( cstagetype == REFBOX_STAGETYPE_SHOOTOUT ) {
322  //
323  } else if( cstagetype == REFBOX_STAGETYPE_ENDGAME ) {
324  //
325  }
326 
327  }
328 
329  } // end-for "child-node children list iteration"
330  } // end-if "child-node has children"
331  } // end-for "root children list iteration"
332  } // end-if "root has children"
333  }
334  else {
335  // throw RefBoxParserException("root is not an element");
336  printf("root is NOT a valid element\n");
337  }
338 
339  __rss.send();
340 }
341 
342 
343 /** Run.
344  * Reads messages from the network, processes them and calls the refbox state sender.
345  */
346 void
348 {
349  char tmpbuf[1024];
350  while ( ! __quit ) {
351  size_t bytes_read = __s->read(tmpbuf, sizeof(tmpbuf), /* read all */ false);
352  if ( bytes_read == 0 ) {
353  // seems that the remote has died, reconnect
354  printf("Connection died, reconnecting\n");
355  reconnect();
356  } else {
357  tmpbuf[bytes_read] = '\0';
358  process_string(tmpbuf, bytes_read);
359  }
360  }
361 }
Msl2008RefBoxRepeater(RefBoxStateSender &rss, const char *refbox_host, unsigned short int refbox_port)
Constructor.
Definition: msl2008.cpp:99
virtual void close()
Close socket.
Definition: socket.cpp:219
RefBox repeater state sender.
Fawkes library namespace.
void set_loop(bool loop)
Set loopback of sent packets.
virtual void bind()
Bind socket.
virtual void set_gamestate(int game_state, fawkes::worldinfo_gamestate_team_t state_team)
Set current game state.
Base class for exceptions in Fawkes.
Definition: exception.h:36
Multicast datagram socket.
Definition: parser.h:35
virtual size_t read(void *buf, size_t count, bool read_all=true)
Read from socket.
Definition: socket.cpp:525
virtual void send()
Send worldinfo.
virtual void set_half(fawkes::worldinfo_gamestate_half_t half)
Set current half of the game time.
~Msl2008RefBoxRepeater()
Destructor.
Definition: msl2008.cpp:116
virtual void set_score(unsigned int score_cyan, unsigned int score_magenta)
Set score.