Fawkes API  Fawkes Development Version
refbox_state_sender.cpp
1 
2 /***************************************************************************
3  * refbox_state_sender.cpp - Fawkes RefBox state sender
4  *
5  * Created: Wed Apr 09 10:19:27 2008
6  * Copyright 2008 Tim Niemueller [www.niemueller.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 "refbox_state_sender.h"
24 
25 #include <netcomm/worldinfo/transceiver.h>
26 #include <core/macros.h>
27 
28 #include <cstdio>
29 #include <unistd.h>
30 
31 using namespace fawkes;
32 
33 /** @class RefBoxStateSender "refbox_state_sender.h"
34  * RefBox repeater state sender.
35  * Adapter to the WorldInfoTransceiver, provides easy optional debugging output
36  * to stdout.
37  * @author Tim Niemueller
38  */
39 
40 /** Constructor.
41  * @param addr multicast address to send information to and receive from
42  * @param port UDP port to send information to and receive from
43  * @param key encryption key
44  * @param iv encryption initialisation vector
45  * @param debug true to enable debug output
46  */
47 RefBoxStateSender::RefBoxStateSender(const char *addr, unsigned short port,
48  const char *key, const char *iv,
49  bool debug)
50 {
51  __debug = debug;
52 
53  __transceiver = new WorldInfoTransceiver(WorldInfoTransceiver::MULTICAST, addr, port, key, iv);
54  __transceiver->set_loop( true );
55 
56  __game_state = GS_FROZEN;
57  __state_team = TEAM_BOTH;
58  __score_cyan = 0;
59  __score_magenta = 0;
60  __our_team = TEAM_CYAN;
61  __our_goal_color = GOAL_BLUE;
62  __half = HALF_FIRST;
63  __timeout_thread = NULL;
64 }
65 
66 /** Constructor.
67  * Only to be used by derivatives. These must implement the send() method!
68  */
70 {
71  __debug = false;
72  __transceiver = NULL;
73  __game_state = GS_FROZEN;
74  __state_team = TEAM_BOTH;
75  __score_cyan = 0;
76  __score_magenta = 0;
77  __our_team = TEAM_CYAN;
78  __our_goal_color = GOAL_BLUE;
79  __half = HALF_FIRST;
80  __timeout_thread = NULL;
81 }
82 
83 
84 /** Destructor. */
86 {
87  if ( __timeout_thread ) {
88  __timeout_thread->cancel();
89  __timeout_thread->join();
90  delete __timeout_thread;
91  }
92  delete __transceiver;
93 }
94 
95 
96 /** Set current game state.
97  * @param game_state current game state
98  * @param state_team team referenced by the game state
99  */
100 void
102  worldinfo_gamestate_team_t state_team)
103 {
104  if ( __debug ) {
105  printf("Setting gamestate to '%d' for team '%s'\n",
106  game_state, worldinfo_gamestate_team_tostring(state_team));
107  }
108 
109  __game_state = game_state;
110  __state_team = state_team;
111 }
112 
113 
114 /** Set score.
115  * @param score_cyan current score of team cyan
116  * @param score_magenta current score of team magenta
117  */
118 void
119 RefBoxStateSender::set_score(unsigned int score_cyan, unsigned int score_magenta)
120 {
121  if ( __debug ) {
122  printf("Setting score to %u:%u (cyan:magenta)\n", score_cyan, score_magenta);
123  }
124  __score_cyan = score_cyan;
125  __score_magenta = score_magenta;
126 }
127 
128 
129 /** Set team and goal info.
130  * @param our_team our team color
131  * @param goal_color our goal color
132  */
133 void
136 {
137  if ( __debug ) {
138  printf("Setting team color to '%s' and goal color to '%s'\n",
141  }
142  __our_team = our_team;
143  __our_goal_color = goal_color;
144 }
145 
146 
147 /** Set current half of the game time.
148  * @param half current half
149  */
150 void
152 {
153  if ( __debug ) {
154  printf("Setting half to '%s'\n",
156  }
157  __half = half;
158 }
159 
160 
161 /** Add penalty.
162  * @param player number of the player to add the penalty for
163  * @param penalty penalty code
164  * @param seconds_remaining estimated time when the penalty will be lifted
165  */
166 void
167 RefBoxStateSender::add_penalty(unsigned int player, unsigned int penalty,
168  unsigned int seconds_remaining)
169 {
170  rss_penalty_t p;
171  p.player = player;
172  p.penalty = penalty;
173  p.seconds_remaining = seconds_remaining;
174  __penalties[player] = p;
175 }
176 
177 
178 /** Send worldinfo. */
179 void
181 {
182  if ( __debug ) {
183  printf("Sending worldinfo\n");
184  }
185 
186  if ( __timeout_thread ) {
187  __timeout_thread->cancel();
188  __timeout_thread->join();
189  delete __timeout_thread;
190  }
191  __timeout_thread = new RefBoxStateSender::TimeoutThread(this);
192  __timeout_thread->start();
193 }
194 
195 
196 /** Execute send operation.
197  * Called by internal timeout thread.
198  */
199 void
200 RefBoxStateSender::execute_send()
201 {
202  if (unlikely(! __transceiver)) {
203  return;
204  } else {
205  __transceiver->set_gamestate(__game_state, __state_team);
206  __transceiver->set_score(__score_cyan, __score_magenta);
207  __transceiver->set_team_goal(__our_team, __our_goal_color);
208  __transceiver->set_half(__half);
209  for (__pit = __penalties.begin(); __pit != __penalties.end(); ++__pit) {
210  __transceiver->add_penalty(__pit->second.player, __pit->second.penalty,
211  __pit->second.seconds_remaining);
212  }
213  __penalties.clear();
214  __transceiver->send();
215  }
216 }
217 
218 /** @class RefBoxStateSender::TimeoutThread <tools/refboxrep/refbox_state_sender.h>
219  * Timeout thread.
220  * This thread sends out a burst of world info packages if new information has been set
221  * for sending and will then slow down until only one packet per second is sent.
222  * @author Tim Niemueller
223  */
224 
225 /** Constructor.
226  * @param rss parent refbox state sender
227  */
229  : Thread("RefBoxStateSender::TimeoutThread", Thread::OPMODE_CONTINUOUS)
230 {
231  __timeout_usec = 0;
232  __rss = rss;
233 }
234 
235 
236 /** Destructor. */
238 {
239 }
240 
241 
242 void
244 {
245  __rss->execute_send();
246 
247  switch (__timeout_usec) {
248  case 0: __timeout_usec = 1; break;
249  case 1: __timeout_usec = 2; break;
250  case 2: __timeout_usec = 50000; break;
251  //case 50000: __timeout_usec = 250000; break;
252  //case 250000: __timeout_usec = 500000; break;
253  //case 500000: __timeout_usec = 1000000; break;
254  }
255 
256  usleep(__timeout_usec);
257 }
Blue goal.
Definition: enums.h:64
Class to send and receive world information.
Definition: transceiver.h:52
RefBox repeater state sender.
Fawkes library namespace.
RefBoxStateSender()
Constructor.
virtual ~RefBoxStateSender()
Destructor.
Thread class encapsulation of pthreads.
Definition: thread.h:42
virtual void set_gamestate(int game_state, fawkes::worldinfo_gamestate_team_t state_team)
Set current game state.
TimeoutThread(RefBoxStateSender *rss)
Constructor.
First half.
Definition: enums.h:71
worldinfo_gamestate_half_t
Game time half.
Definition: enums.h:70
const char * worldinfo_gamestate_team_tostring(worldinfo_gamestate_team_t team)
Convert gamestate team to a string.
Definition: enums.cpp:75
virtual void add_penalty(unsigned int player, unsigned int penalty, unsigned int seconds_remaining)
Add penalty.
Use multicast socket for communication.
Definition: transceiver.h:57
Both teams.
Definition: enums.h:58
Frozen, nothing moves.
Definition: enums.h:31
virtual void loop()
Code to execute in the thread.
virtual void set_team_goal(fawkes::worldinfo_gamestate_team_t our_team, fawkes::worldinfo_gamestate_goalcolor_t goal_color)
Set team and goal info.
const char * worldinfo_gamestate_goalcolor_tostring(worldinfo_gamestate_goalcolor_t goal_color)
Convert goal color to a string.
Definition: enums.cpp:92
Cyan team.
Definition: enums.h:56
worldinfo_gamestate_team_t
Team.
Definition: enums.h:54
virtual void send()
Send worldinfo.
virtual void set_half(fawkes::worldinfo_gamestate_half_t half)
Set current half of the game time.
const char * worldinfo_gamestate_half_tostring(worldinfo_gamestate_half_t half)
Convert half time to a string.
Definition: enums.cpp:108
virtual void set_score(unsigned int score_cyan, unsigned int score_magenta)
Set score.
worldinfo_gamestate_goalcolor_t
Goal color.
Definition: enums.h:63