Wiselib
|
00001 /* 00002 * Author: Juan Farré, UPC 00003 */ 00004 00005 #ifndef ALGORITHMS_TOPOLOGY_ADJUST_POWER_SEQUENTIAL_TRY_H_ 00006 #define ALGORITHMS_TOPOLOGY_ADJUST_POWER_SEQUENTIAL_TRY_H_ 00007 00008 #include <stdint.h> 00009 00010 #include "external_interface/external_interface.h" 00011 #include "util/pstl/vector_static.h" 00012 #include "util/pstl/algorithm.h" 00013 00014 #include "algorithms/topology/adjust_power/sequential_try_types.h" 00015 #include "algorithms/topology/adjust_power/sequential_try_ping_message.h" 00016 #include "algorithms/topology/adjust_power/sequential_try_pong_message.h" 00017 00018 namespace wiselib { 00019 00020 #define MAX_NEIGH_DEF 32 00021 #define SEND_DELAY 500 00022 #define POWER_SET_DELAY 500 00023 #define DELTA_DEF 10000 00024 #define PING_TASK 0 00025 #define PONG_TASK 1 00026 #define RESTORE_POWER_TASK 2 00027 #define CHECK_TASK 3 00028 #define END_PONG_TASK 4 00029 #define SEND_TASK 5 00030 #define END_PING_TASK 6 00031 00032 template<class OsModel_P, class Radio_P = typename OsModel_P::TxRadio, 00033 class Neigh_P = vector_static<OsModel_P, typename Radio_P::node_id_t, 00034 MAX_NEIGH_DEF> , class Timer_P = typename OsModel_P::Timer> 00035 class SequentialTry { 00036 public: 00037 typedef OsModel_P OsModel; 00038 typedef Radio_P Radio; 00039 typedef Neigh_P Neighbors; 00040 typedef Timer_P Timer; 00041 #ifdef DEBUG 00042 typedef typename OsModel_P::Debug Debug; 00043 #endif 00044 00045 typedef SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P> self_type; 00046 00047 typedef typename OsModel::Os Os; 00048 00049 typedef typename Radio::node_id_t node_id_t; 00050 typedef typename Radio::size_t size_t; 00051 typedef typename Radio::block_data_t block_data_t; 00052 typedef typename Radio::TxPower TxPower; 00053 typedef typename Timer::millis_t millis_t; 00054 00055 SequentialTry(); 00056 00057 void enable(); 00058 void disable(); 00059 00060 TxPower power() const; 00061 00062 #ifdef DEBUG 00063 void init(Radio &r, Timer &t, Debug &d) { 00064 radio = &r; 00065 timer = &t; 00066 debug = &d; 00067 } 00068 #else 00069 void init(Radio &r, Timer &t) { 00070 radio = &r; 00071 timer = &t; 00072 } 00073 #endif 00074 00075 void set_neighbors(Neighbors &); 00076 Neighbors &neighbors(); 00077 void set_delta(millis_t); 00078 millis_t delta(); 00079 00080 template<class T, void(T::*TMethod)()> 00081 void reg_listener_callback(T *); 00082 00083 template<void(*TMethod)()> 00084 void reg_listener_callback(); 00085 00086 void unreg_listener_callback(); 00087 00088 static void set_default_delta(millis_t); 00089 static millis_t default_delta(); 00090 00091 private: 00092 typedef delegate0<void> delegate_t; 00093 00094 void notify_listeners(); 00095 00096 void start_ping(); 00097 void send_ping(); 00098 void send_pong(); 00099 void receive(node_id_t from, size_t len, block_data_t *data); 00100 void timer_callback(void *); 00101 00102 SequentialTryPongMessage<OsModel, Radio> pong_msg; 00103 Radio *radio; 00104 Timer *timer; 00105 #ifdef DEBUG 00106 Debug *debug; 00107 #endif 00108 Neighbors replied; 00109 TxPower power_; 00110 delegate_t callback_; 00111 Neighbors *neigh; 00112 millis_t delta_; 00113 bool enabled; 00114 bool initialized; 00115 bool wait; 00116 bool waiting; 00117 00118 static uint8_t const ping_task; 00119 static uint8_t const pong_task; 00120 static uint8_t const send_task; 00121 static uint8_t const restore_power_task; 00122 static uint8_t const check_task; 00123 static uint8_t const end_ping_task; 00124 static uint8_t const end_pong_task; 00125 static millis_t delta_def; 00126 }; 00127 00128 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00129 uint8_t const SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::ping_task( 00130 PING_TASK); 00131 00132 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00133 uint8_t const SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::pong_task( 00134 PONG_TASK); 00135 00136 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00137 uint8_t const SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::send_task( 00138 SEND_TASK); 00139 00140 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00141 uint8_t const 00142 SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::restore_power_task( 00143 RESTORE_POWER_TASK); 00144 00145 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00146 uint8_t const SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::check_task( 00147 CHECK_TASK); 00148 00149 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00150 uint8_t const 00151 SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::end_ping_task( 00152 END_PING_TASK); 00153 00154 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00155 uint8_t const 00156 SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::end_pong_task( 00157 END_PONG_TASK); 00158 00159 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00160 typename SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::millis_t 00161 SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::delta_def( 00162 DELTA_DEF); 00163 00164 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00165 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::set_default_delta( 00166 millis_t millis) { 00167 delta_def = millis; 00168 } 00169 00170 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00171 typename SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::millis_t SequentialTry< 00172 OsModel_P, Radio_P, Neigh_P, Timer_P>::default_delta() { 00173 return delta_def; 00174 } 00175 00176 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00177 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::set_neighbors( 00178 Neighbors &n) { 00179 neigh = &n; 00180 } 00181 00182 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00183 typename SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::Neighbors &SequentialTry< 00184 OsModel_P, Radio_P, Neigh_P, Timer_P>::neighbors() { 00185 return *neigh; 00186 } 00187 00188 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00189 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::set_delta( 00190 millis_t millis) { 00191 delta_ = millis; 00192 } 00193 00194 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00195 typename SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::millis_t SequentialTry< 00196 OsModel_P, Radio_P, Neigh_P, Timer_P>::delta() { 00197 return delta_; 00198 } 00199 00200 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00201 typename SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::TxPower SequentialTry< 00202 OsModel_P, Radio_P, Neigh_P, Timer_P>::power() const { 00203 return power_; 00204 } 00205 00206 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00207 template<class T, void(T::*TMethod)()> 00208 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::reg_listener_callback( 00209 T *obj_pnt) { 00210 callback_ = delegate_t::from_method<T, TMethod>(obj_pnt); 00211 } 00212 00213 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00214 template<void(*TMethod)()> 00215 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::reg_listener_callback() { 00216 callback_ = delegate_t::from_function<TMethod>(); 00217 } 00218 00219 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00220 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::unreg_listener_callback() { 00221 callback_ = delegate_t(); 00222 } 00223 00224 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00225 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::notify_listeners() { 00226 if (callback_) 00227 callback_(); 00228 } 00229 00230 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00231 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::send_ping() { 00232 radio->set_power(power_); 00233 wait = true; 00234 timer->template set_timer<self_type, &self_type::timer_callback> ( 00235 POWER_SET_DELAY, this, const_cast<uint8_t *> (&send_task)); 00236 #ifdef DEBUG 00237 debug->debug("SequentialTry set power to %i\n", power_.to_dB()); 00238 #endif 00239 } 00240 00241 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00242 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::start_ping() { 00243 #ifdef DEBUG 00244 debug->debug("SequentialTry ready to send ping\n"); 00245 #endif 00246 if (wait) 00247 waiting = true; 00248 else 00249 send_ping(); 00250 } 00251 00252 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00253 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::send_pong() { 00254 radio->send(Radio::BROADCAST_ADDRESS, pong_msg.buffer_size(), 00255 pong_msg.buf()); 00256 timer->template set_timer<self_type, &self_type::timer_callback> ( 00257 SEND_DELAY, this, const_cast<uint8_t *> (&end_pong_task)); 00258 wait = true; 00259 #ifdef DEBUG 00260 debug->debug("SequentialTry sending pong\n"); 00261 #endif 00262 pong_msg.set_neighbor_number(0); 00263 } 00264 00265 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00266 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::timer_callback( 00267 void *userdata) { 00268 typedef typename Neighbors::iterator Iter; 00269 if (!enabled) 00270 return; 00271 switch (*static_cast<uint8_t const *> (userdata)) { 00272 case PING_TASK: 00273 start_ping(); 00274 break; 00275 case SEND_TASK: { 00276 SequentialTryPingMessage<OsModel, Radio> msg; 00277 msg.set_msg_id(SequentialTryPingMsgId); 00278 radio->send(Radio::BROADCAST_ADDRESS, msg.buffer_size(), msg.buf()); 00279 timer->template set_timer<self_type, &self_type::timer_callback> ( 00280 SEND_DELAY, this, const_cast<uint8_t *> (&restore_power_task)); 00281 #ifdef DEBUG 00282 debug->debug("SequentialTry sent ping at %i dB\n", power_.to_dB()); 00283 #endif 00284 } 00285 break; 00286 case RESTORE_POWER_TASK: 00287 radio->set_power(TxPower::MAX); 00288 timer->template set_timer<self_type, &self_type::timer_callback> ( 00289 POWER_SET_DELAY, this, const_cast<uint8_t *> (&end_ping_task)); 00290 timer->template set_timer<self_type, &self_type::timer_callback> ( 00291 delta() + 2 * POWER_SET_DELAY + 2 * SEND_DELAY, this, 00292 const_cast<uint8_t *> (&check_task)); 00293 #ifdef DEBUG 00294 debug->debug("SequentialTry restored max power\n"); 00295 #endif 00296 break; 00297 case END_PING_TASK: 00298 #ifdef DEBUG 00299 debug->debug("SequentialTry finished sending ping\n"); 00300 #endif 00301 wait = false; 00302 if (waiting) { 00303 send_pong(); 00304 waiting = false; 00305 } 00306 break; 00307 case CHECK_TASK: 00308 for (Iter i = neigh->begin(); i != neigh->end(); ++i) { 00309 if (find(replied.begin(), replied.end(), *i) == replied.end()) { 00310 ++power_; 00311 if (power_ == TxPower::MAX) 00312 break; 00313 start_ping(); 00314 return; 00315 } 00316 } 00317 #ifdef DEBUG 00318 debug->debug("SequentialTry found final power: %i\n", power_.to_dB()); 00319 #endif 00320 notify_listeners(); 00321 break; 00322 case PONG_TASK: 00323 if (pong_msg.neighbor_number() != 0) { 00324 #ifdef DEBUG 00325 debug->debug("SequentialTry ready to send pong\n"); 00326 #endif 00327 if (wait) 00328 waiting = true; 00329 else 00330 send_pong(); 00331 } 00332 timer->template set_timer<self_type, &self_type::timer_callback> ( 00333 delta(), this, const_cast<uint8_t *> (&pong_task)); 00334 break; 00335 case END_PONG_TASK: 00336 #ifdef DEBUG 00337 debug->debug("SequentialTry finished sending pong\n"); 00338 #endif 00339 wait = false; 00340 if (waiting) { 00341 send_ping(); 00342 waiting = false; 00343 } 00344 break; 00345 } 00346 } 00347 00348 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00349 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::receive( 00350 node_id_t from, size_t len, block_data_t *data) { 00351 if (len == 0) 00352 return; 00353 switch (*data) { 00354 case SequentialTryPingMsgId: 00355 #ifdef DEBUG 00356 debug->debug("SequentialTry receives ping from %i\n", from); 00357 #endif 00358 pong_msg.set_neighbor(pong_msg.neighbor_number(), from); 00359 pong_msg.set_neighbor_number(pong_msg.neighbor_number() + 1); 00360 break; 00361 case SequentialTryPongMsgId: { 00362 SequentialTryPongMessage<OsModel, Radio> 00363 *msg = 00364 reinterpret_cast<SequentialTryPongMessage<OsModel, 00365 Radio> *> (data); 00366 for (size_t i = 0; i < msg->neighbor_number(); ++i) 00367 if (msg->neighbor(i) == radio->id()) { 00368 if (find(replied.begin(), replied.end(), from) == replied.end()) 00369 replied.push_back(from); 00370 #ifdef DEBUG 00371 debug->debug("SequentialTry gets reply from %i\n", from); 00372 #endif 00373 break; 00374 } 00375 } 00376 break; 00377 } 00378 } 00379 00380 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00381 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::enable() { 00382 if (enabled || !radio) 00383 return; 00384 if (!initialized) { 00385 if (TxPower::MIN == TxPower::MAX) { 00386 #ifdef DEBUG 00387 debug->debug("SequentialTry: Only one power lever. Nothing to do.\n"); 00388 #endif 00389 notify_listeners(); 00390 } 00391 radio->template reg_recv_callback<self_type, &self_type::receive> (this); 00392 initialized = true; 00393 #ifdef DEBUG 00394 debug->debug("SequentialTry Boots for %i\n", radio->id()); 00395 #endif 00396 } 00397 if (neigh) { 00398 timer->template set_timer<self_type, &self_type::timer_callback> ( 00399 delta(), this, const_cast<uint8_t *> (&pong_task)); 00400 radio->set_power(TxPower::MAX); 00401 pong_msg.set_neighbor_number(0); 00402 replied.clear(); 00403 power_ = TxPower::MIN; 00404 enabled = true; 00405 wait = false; 00406 waiting = false; 00407 timer->template set_timer<self_type, &self_type::timer_callback> ( 00408 delta(), this, const_cast<uint8_t *> (&ping_task)); 00409 #ifdef DEBUG 00410 debug->debug("Starting SequentialTry\n"); 00411 #endif 00412 } 00413 } 00414 00415 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00416 void SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::disable() { 00417 enabled = false; 00418 #ifdef DEBUG 00419 debug->debug("SequentialTry disabled\n"); 00420 #endif 00421 } 00422 00423 template<class OsModel_P, class Radio_P, class Neigh_P, class Timer_P> 00424 SequentialTry<OsModel_P, Radio_P, Neigh_P, Timer_P>::SequentialTry() : 00425 radio(0), timer(0), neigh(0), delta_(delta_def), enabled(false), 00426 initialized(false), wait(false), waiting(false) { 00427 pong_msg.set_msg_id(SequentialTryPongMsgId); 00428 } 00429 00430 } 00431 00432 #endif /* ALGORITHMS_TOPOLOGY_ADJUST_POWER_SEQUENTIAL_TRY_H_ */