Wiselib
|
00001 #ifndef _DFSCLUSTERING_H 00002 #define _DFSCLUSTERING_H 00003 00004 #include "util/delegates/delegate.hpp" 00005 #include "util/pstl/vector_static.h" 00006 #include "algorithms/cluster/clustering_types.h" 00007 #include <stack> 00008 00009 #undef DEBUG 00010 #define DEBUG 00011 00012 00013 namespace wiselib { 00014 00022 template<typename OsModel_P, 00023 typename Radio_P, 00024 typename Timer_P, 00025 typename Debug_P> 00026 00027 class DfsClustering { 00028 public: 00029 00030 //TYPEDEFS 00031 typedef OsModel_P OsModel; 00032 typedef Radio_P Radio; 00033 typedef Timer_P Timer; 00034 typedef Debug_P Debug; 00035 typedef DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P> self_t; 00036 00037 //data types 00038 typedef int cluster_id_t; 00039 typedef int cluster_level_t; //quite useless within current scheme, supported for compatibility issues 00040 typedef typename Radio::node_id_t node_id_t; 00041 typedef typename Radio::size_t size_t; 00042 typedef typename Radio::block_data_t block_data_t; 00043 typedef wiselib::vector_static<OsModel, node_id_t, 200 > vector_t; 00044 00045 //delegates 00046 typedef delegate1<void, int> cluster_delegate_t; 00047 00048 00049 /* SET functions */ 00050 00051 //set the clustering parameter 00052 00053 void set_theta(int theta) { 00054 theta_ = theta; 00055 } 00056 00057 /* GET functions */ 00058 00059 //get the cluster level 00060 00061 cluster_level_t cluster_level() { 00062 return 0; 00063 } 00064 00065 //get the cluster id 00066 00067 cluster_id_t cluster_id() { 00068 return SID_; 00069 } 00070 00071 //get if cluster head 00072 00073 bool cluster_head() { 00074 return cluster_head_; 00075 } 00076 00077 //get the parent 00078 00079 node_id_t parent() { 00080 return parent_; 00081 } 00082 00083 //get hops from cluster head 00084 00085 size_t hops() { 00086 return hops_; 00087 } 00088 00089 /* CALLBACKS */ 00090 00091 template<class T, void (T::*TMethod)(int) > 00092 inline int reg_changed_callback(T *obj_pnt) { 00093 state_changed_callback_ = cluster_delegate_t::from_method<T, TMethod > (obj_pnt); 00094 return state_changed_callback_; 00095 } 00096 00097 void unreg_changed_callback(int idx) { 00098 state_changed_callback_ = cluster_delegate_t(); 00099 } 00100 00101 /* SHOW all the known nodes */ 00102 #ifdef DEBUG 00103 00104 void present_neighbors() { 00105 #ifndef ISENSE_APP 00106 debug().debug("Present Node %d Neighbors:\n", radio().id()); 00107 debug().debug("Cluster: "); 00108 for (size_t i = 0; i < cluster_neighbors_.size(); i++) { 00109 debug().debug("%d ", cluster_neighbors_.at(i)); 00110 } 00111 debug().debug("\nNon-Cluster: "); 00112 for (size_t i = 0; i < non_cluster_neighbors_.size(); i++) { 00113 debug().debug("%d ", non_cluster_neighbors_.at(i)); 00114 } 00115 debug().debug("\n"); 00116 #else 00117 debug().debug("Present Node %x Neighbors:", radio().id()); 00118 debug().debug("Cluster: "); 00119 for (size_t i = 0; i < cluster_neighbors_.size(); i++) { 00120 debug().debug("%x ", cluster_neighbors_.at(i)); 00121 } 00122 debug().debug("Non-Cluster: "); 00123 for (size_t i = 0; i < non_cluster_neighbors_.size(); i++) { 00124 debug().debug("%x ", non_cluster_neighbors_.at(i)); 00125 } 00126 00127 #endif 00128 00129 } 00130 #endif 00131 00132 #ifdef DEBUG 00133 int mess_join_req() { 00134 return mess_join_req_; 00135 }; 00136 00137 int mess_join_deny() { 00138 return mess_join_deny_; 00139 }; 00140 00141 int mess_resume() { 00142 return mess_resume_; 00143 }; 00144 00145 int mess_neighbor_discovery() { 00146 return mess_neighbor_discovery_; 00147 }; 00148 00149 int mess_neighbor_reply() { 00150 return mess_neighbor_reply_; 00151 }; 00152 #endif 00153 /* 00154 * Enable 00155 * enables the dfsclustering module 00156 * initializes values 00157 * registers callbacks 00158 * and starts the 00159 * clustering procedure 00160 * */ 00161 void enable(void); 00162 /* 00163 * Disable 00164 * disables the bfsclustering module 00165 * unregisters callbacks 00166 * */ 00167 void disable(void); 00168 00169 /* 00170 * Constructor 00171 * */ 00172 DfsClustering() : 00173 cluster_head_(false), 00174 SID_(-1), 00175 parent_(-1), 00176 theta_(30), 00177 hops_(0) 00178 { 00179 cluster_neighbors_.clear(); 00180 non_cluster_neighbors_.clear(); 00181 00182 } 00183 00184 /* 00185 * Destructor 00186 * */ 00187 ~DfsClustering() { 00188 } 00190 00191 /* 00192 * INIT 00193 * initializes the values of radio timer and debug 00194 */ 00195 void init(Radio& radio, Timer& timer, Debug& debug) { 00196 radio_ = &radio; 00197 timer_ = &timer; 00198 debug_ = &debug; 00199 }; 00200 00201 protected: 00202 /* 00203 * DISCOVER_NEIGHBORS 00204 * sends a message to 00205 * start neighbor discovery 00206 * and sets timer to send a neighbor request message 00207 * */ 00208 void discover_neighbors(); 00209 /* 00210 * TIMER_EXPIRED 00211 * if any nodes responded to neighbor discovery 00212 * sends a new neighbor request message 00213 * */ 00214 void timer_expired(void*); 00215 /* 00216 * RECEIVE 00217 * respond to the new messages received 00218 * callback from the radio 00219 * */ 00220 void receive(node_id_t receiver, size_t len, block_data_t *data); 00221 00222 private: 00223 bool cluster_head_; // if a cluster head 00224 cluster_id_t SID_; // the node's cluster id 00225 int callback_id_; // received messages callback 00226 cluster_delegate_t state_changed_callback_; // callback to the processor 00227 vector_t neighbors_; // contains the neighbors 00228 vector_t cluster_neighbors_, non_cluster_neighbors_; 00229 node_id_t parent_; //parent of the node 00230 static const int time_slice_ = 2000; // timeout to receive neighbor replies 00231 int theta_; // clustering parameter 00232 size_t hops_; // hops from head 00233 00234 00235 #ifdef DEBUG 00236 int mess_neighbor_discovery_; 00237 int mess_neighbor_reply_; 00238 int mess_join_req_; 00239 int mess_join_deny_; 00240 int mess_resume_; 00241 00242 void reset_mess_counters() { 00243 mess_neighbor_discovery_ = 0; 00244 mess_neighbor_reply_ = 0; 00245 mess_join_req_ = 0; 00246 mess_join_deny_ = 0; 00247 mess_resume_ = 0; 00248 } 00249 #endif 00250 00251 Radio * radio_; //radio module 00252 Timer * timer_; //timer module 00253 Debug * debug_; //debug module 00254 00255 Radio& radio() { 00256 return *radio_; 00257 } 00258 00259 Timer& timer() { 00260 return *timer_; 00261 } 00262 00263 Debug& debug() { 00264 return *debug_; 00265 } 00266 00267 }; 00268 00269 template<typename OsModel_P, 00270 typename Radio_P, 00271 typename Timer_P, 00272 typename Debug_P> 00273 void 00274 DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>:: 00275 enable(void) { 00276 #ifdef DEBUG 00277 #ifndef ISENSE_APP 00278 debug().debug("DFSClustering ENABLED %d\n", radio().id()); 00279 #else 00280 debug().debug("DFSClustering ENABLED %x", radio().id()); 00281 #endif 00282 #endif 00283 //initilize the variables 00284 SID_ = -1; 00285 cluster_head_ = false; 00286 hops_ = 0; 00287 parent_ = -1; 00288 00289 00290 00291 #ifdef DEBUG 00292 reset_mess_counters(); 00293 #endif 00294 //enable the radio 00295 radio().enable_radio(); 00296 00297 //register receive to radio 00298 callback_id_ = radio().template reg_recv_callback<self_t, 00299 &self_t::receive > (this); 00300 00301 //-> Cluster Head Decision 00302 if (radio().id() % theta_ == 0) { 00303 cluster_head_ = true; 00304 } else { 00305 cluster_head_ = false; 00306 } 00307 00308 // if a cluster head 00309 if (cluster_head_) { 00310 //I am cluster_head, set SID_ to id and discover_neighbors 00311 SID_ = radio().id(); 00312 parent_ = radio().id(); 00313 hops_ = 0; 00314 if (state_changed_callback_) state_changed_callback_(CLUSTER_HEAD_CHANGED); 00315 00316 discover_neighbors(); 00317 } 00318 00319 } 00320 00321 template<typename OsModel_P, 00322 typename Radio_P, 00323 typename Timer_P, 00324 typename Debug_P> 00325 void 00326 DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>:: 00327 disable(void) { 00328 00329 #ifdef DEBUG 00330 #ifndef ISENSE_APP 00331 debug().debug("DFSClustering Disabled! Node %d\n", radio().id()); 00332 #else 00333 debug().debug("DFSClustering Disabled! Node %x", radio().id()); 00334 #endif 00335 #endif 00336 radio().unreg_recv_callback(callback_id_); 00337 00338 } 00339 00340 template<typename OsModel_P, 00341 typename Radio_P, 00342 typename Timer_P, 00343 typename Debug_P> 00344 void 00345 DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>:: 00346 discover_neighbors(void) { 00347 #ifdef DEBUG 00348 #ifndef ISENSE_APP 00349 debug().debug("DFSClustering called discover neighbors! Node %d,cluster_head_=%d\n", radio().id(), cluster_head_); 00350 #else 00351 debug().debug("DFSClustering called discover neighbors! Node %x,cluster_head_=%d", radio().id(), cluster_head_); 00352 #endif 00353 #endif 00354 //NEIGHBOR_DISCOVERY MESSAGE 00355 #ifdef ISENSE_APP 00356 debug().debug("START 2"); 00357 #endif 00358 block_data_t msg = NEIGHBOR_DISCOVERY; 00359 radio().send(Radio::BROADCAST_ADDRESS, 1, &msg); 00360 #ifdef ISENSE_APP 00361 debug().debug("STOP 2"); 00362 #endif 00363 00364 neighbors_.clear(); 00365 #ifdef DEBUG 00366 #ifndef ISENSE_APP 00367 debug().debug("SEND NEIGHBOR_DISCOVERY Node %d\n", radio().id()); 00368 #else 00369 debug().debug("SEND NEIGHBOR_DISCOVERY Node %x", radio().id()); 00370 #endif 00371 //increase the message counter 00372 mess_neighbor_discovery_++; 00373 #endif 00374 //set timer to wait for responds to neighbor discovery 00375 timer().template set_timer<self_t, 00376 &self_t::timer_expired > (time_slice_, this, (void*) 0); 00377 } 00378 00379 template<typename OsModel_P, 00380 typename Radio_P, 00381 typename Timer_P, 00382 typename Debug_P> 00383 00384 void 00385 DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>:: 00386 timer_expired(void* data) { 00387 #ifdef DEBUG 00388 #ifndef ISENSE_APP 00389 debug().debug("DFSClustering timer Expired! Node %d,%d\n", radio().id(), cluster_head_); 00390 #else 00391 debug().debug("DFSClustering timer Expired! Node %x,%d", radio().id(), cluster_head_); 00392 #endif 00393 #endif 00394 00395 // if no more neighbors exist 00396 if (neighbors_.empty()) { 00397 // if not a head 00398 if (!cluster_head_) { 00399 //send a RESUME message 00400 block_data_t msg = RESUME; 00401 //do send the message 00402 radio().send(parent_, 1, &msg); 00403 #ifdef DEBUG 00404 #ifndef ISENSE_APP 00405 debug().debug("SEND RESUME %d -> %d\n", radio().id(), parent_); 00406 #else 00407 debug().debug("SEND RESUME %x -> %x", radio().id(), parent_); 00408 #endif 00409 //increase the message counter 00410 mess_resume_++; 00411 #endif 00412 } else { 00413 if (state_changed_callback_) state_changed_callback_(CLUSTER_FORMED); 00414 00415 #ifdef DEBUG 00416 #ifndef ISENSE_APP 00417 debug().debug("CLUSTER FORMED %d \n", radio().id()); 00418 #else 00419 debug().debug("CLUSTER FORMED %x", radio().id()); 00420 #endif 00421 #endif 00422 00423 } 00424 }//if more neighbors 00425 else { 00426 //get a neighbor 00427 node_id_t dest = neighbors_.back(); 00428 00429 // remove from neighbors 00430 neighbors_.pop_back(); 00431 //send a JOIN_REQUEST message 00432 block_data_t msg[4] = {JOIN_REQUEST, SID_ / 256, SID_ % 256, hops_}; 00433 //do send the message 00434 radio().send(dest, 4, msg); 00435 00436 #ifdef DEBUG 00437 #ifndef ISENSE_APP 00438 debug().debug("SEND JOIN_REQUEST %d -> %d cluster= %d \n", radio().id(), dest, SID_); 00439 #else 00440 debug().debug("SEND JOIN_REQUEST %x -> %x cluster= %x ", radio().id(), dest, SID_); 00441 #endif 00442 //increase the message counter 00443 mess_join_req_++; 00444 #endif 00445 } 00446 } 00447 00448 template<typename OsModel_P, 00449 typename Radio_P, 00450 typename Timer_P, 00451 typename Debug_P> 00452 void 00453 DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>:: 00454 receive(node_id_t from, size_t len, block_data_t* data) { 00455 00456 // if own message ignore it 00457 if (from == radio().id()) return; 00458 00459 //if a NEIGHBOR_DISCOVERY message 00460 if (*data == NEIGHBOR_DISCOVERY) { 00461 #ifdef DEBUG 00462 #ifndef ISENSE_APP 00463 debug().debug("RECEIVED NEIGHBOR_DISCOVERY %d <- %d\n", radio().id(), from); 00464 #else 00465 debug().debug("RECEIVED NEIGHBOR_DISCOVERY %x <- %x", radio().id(), from); 00466 #endif 00467 #endif 00468 00469 // if not clustered yet 00470 if (SID_ == -1) { 00471 //create a reply 00472 block_data_t m_hd = NEIGHBOR_REPLY; 00473 //do send the reply 00474 radio().send(from, 1, &m_hd); 00475 00476 #ifdef DEBUG 00477 #ifndef ISENSE_APP 00478 debug().debug("SEND NEIGHBOR_REPLY %d -> %d\n", radio().id(), from); 00479 #else 00480 debug().debug("SEND NEIGHBOR_REPLY %x -> %x", radio().id(), from); 00481 #endif 00482 //increase the message counter 00483 mess_neighbor_reply_++; 00484 #endif 00485 } 00486 } else if (*data == NEIGHBOR_REPLY) { 00487 #ifdef DEBUG 00488 #ifndef ISENSE_APP 00489 debug().debug("RECEIVED NEIGHBOR_REPLY %d <- %d \n", radio().id(), from); 00490 #else 00491 debug().debug("RECEIVED NEIGHBOR_REPLY %x <- %x", radio().id(), from); 00492 #endif 00493 #endif 00494 //add sender to neighbors 00495 neighbors_.push_back(from); 00496 } else if (*data == JOIN_REQUEST) { 00497 #ifdef DEBUG 00498 #ifndef ISENSE_APP 00499 debug().debug("RECEIVED JOIN_REQUEST %d <- %d \n", radio().id(), from); 00500 #else 00501 debug().debug("RECEIVED JOIN_REQUEST %x <- %x", radio().id(), from); 00502 #endif 00503 #endif 00504 //if not clustered yet 00505 if (SID_ == -1) { 00506 //JOIN the cluster 00507 parent_ = from; 00508 SID_ = data[1]*256 + data[2]; 00509 hops_ = data[3] + 1; 00510 //inform the processor 00511 if (state_changed_callback_) state_changed_callback_(NODE_JOINED); 00512 00513 //discover own neighbors 00514 discover_neighbors(); 00515 } else { 00516 //create a deny message 00517 block_data_t msg = JOIN_DENY; 00518 //do send the message 00519 radio().send(from, 1, &msg); 00520 #ifdef DEBUG 00521 #ifndef ISENSE_APP 00522 debug().debug("SEND JOIN_DENY %d -> %d \n", radio().id(), from); 00523 #else 00524 debug().debug("SEND JOIN_DENY %x -> %x", radio().id(), from); 00525 #endif 00526 //increase the message counter 00527 mess_join_deny_++; 00528 #endif 00529 } 00530 } else if (*data == JOIN_DENY) { 00531 #ifdef DEBUG 00532 #ifndef ISENSE_APP 00533 debug().debug("RECEIVED JOIN_DENY %d <- %d \n", radio().id(), from); 00534 #else 00535 debug().debug("RECEIVED JOIN_DENY %x <- %x", radio().id(), from); 00536 #endif 00537 #endif 00538 //check neighbors 00539 discover_neighbors(); 00540 } else if (*data == RESUME) { 00541 #ifdef DEBUG 00542 #ifndef ISENSE_APP 00543 debug().debug("RECEIVED RESUME %d <- %d \n", radio().id(), from); 00544 #else 00545 debug().debug("RECEIVED RESUME %x <- %x", radio().id(), from); 00546 #endif 00547 #endif 00548 // check neighbors 00549 discover_neighbors(); 00550 } 00551 } 00552 } 00553 #endif 00554