Wiselib
wiselib.testing/algorithms/topology/adjust_power/sequential_try.h
Go to the documentation of this file.
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_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines