Wiselib
wiselib.testing/algorithms/cluster/fronts/fronts_core.h
Go to the documentation of this file.
00001 /*
00002  * File:   fronts_core.h
00003  * Author: Amaxilatis
00004  *
00005  */
00006 
00007 #ifndef __FRONTS_CORE_H_
00008 #define __FRONTS_CORE_H_
00009 
00010 #include "util/delegates/delegate.hpp"
00011 #include "algorithms/cluster/clustering_types.h"
00012 #include "util/base_classes/clustering_base.h"
00013 #include "algorithms/neighbor_discovery/echo.h"
00014 #include "algorithms/neighbor_discovery/pgb_payloads_ids.h"
00015 
00016 //Enable This to Initiate Fixed Cluster Roles for Nodes
00017 //#define FIXED_ROLES
00018 #ifdef FIXED_ROLES
00019 #define TOTAL_NODES 2
00020 #endif
00021 #define MAINTENANCE
00022 
00023 #undef DEBUG
00024 // Uncomment to enable Debug
00025 //#define DEBUG
00026 #ifdef DEBUG
00027 //#define DEBUG_PAYLOADS
00028 //#define DEBUG_RECEIVED
00029 //#define DEBUG_CLUSTERING
00030 #endif
00031 
00032 
00033 namespace wiselib {
00034 
00042     template<typename OsModel_P, typename Radio_P, typename HeadDecision_P,
00043     typename JoinDecision_P, typename Iterator_P>
00044     class FrontsCore : public ClusteringBase<OsModel_P> {
00045     public:
00046         //TYPEDEFS
00047         typedef OsModel_P OsModel;
00048         // os modules
00049         typedef Radio_P Radio;
00050         typedef typename OsModel::Timer Timer;
00051         typedef typename OsModel::Debug Debug;
00052         typedef typename OsModel::Rand Rand;
00053 
00054         //algorithm modules
00055         typedef HeadDecision_P HeadDecision_t;
00056         typedef JoinDecision_P JoinDecision_t;
00057         typedef Iterator_P Iterator_t;
00058 
00059         // self type
00060         typedef FrontsCore<OsModel_P, Radio_P, HeadDecision_P, JoinDecision_P,
00061         Iterator_P> self_type;
00062         typedef wiselib::Echo<OsModel, Radio, Timer, Debug> nb_t;
00063 
00064         // data types
00065         typedef typename Radio::node_id_t node_id_t;
00066         typedef node_id_t cluster_id_t;
00067         typedef typename Radio::size_t size_t;
00068         typedef typename Radio::block_data_t block_data_t;
00069         typedef uint16_t cluster_level_t; //quite useless within current scheme, supported for compatibility issues
00070 
00071 
00072 #ifdef FIXED_ROLES
00073         typedef wiselib::pair<node_id_t, node_id_t> node_role_t;
00074 #endif
00075 
00076         // delegate
00077         //typedef delegate1<void, uint32_t> cluster_delegate_t;
00078 
00079          typedef delegate3<void, uint8_t, cluster_id_t, node_id_t>   cradio_delegate_t;
00080         
00081 
00082         /*
00083          * Constructor
00084          * */
00085         FrontsCore() :
00086         enabled_(false), status_(0), maxhops_(1), auto_reform_(0), reform_(
00087         false), head_lost_(false) {
00088         }
00089 
00090         /*
00091          * Destructor
00092          * */
00093         ~FrontsCore() {
00094         }
00095 
00096         /*
00097          * INIT
00098          * initializes the values of radio timer and debug
00099          */
00100         void init(Radio& radiot, Timer& timert, Debug& debugt, Rand& randt,
00101                 nb_t& neighbor_discovery) {
00102             radio_ = &radiot;
00103             timer_ = &timert;
00104             debug_ = &debugt;
00105             rand_ = &randt;
00106 
00107 
00108             neighbor_discovery_ = &neighbor_discovery;
00109 
00110             uint8_t flags = nb_t::DROPPED_NB | nb_t::LOST_NB_BIDI
00111                     | nb_t::NEW_PAYLOAD_BIDI ;//| nb_t::NB_READY;
00112 
00113             neighbor_discovery_->template reg_event_callback<self_type,
00114                     &self_type::ND_callback > (CLUSTERING, flags, this);
00115             neighbor_discovery_->register_payload_space((uint8_t) CLUSTERING);
00116 
00117             cradio_delegate_=cradio_delegate_t();
00118 
00119             //initialize the clustering modules
00120             chd().init(radio(), debug());
00121             jd().init(radio(), debug());
00122             it().init(radio(), timer(), debug());
00123 
00124             rand().srand(radio().id());
00125 
00126 
00127         }
00128 
00129         /*
00130          * Set Clustering modules
00131          * it,jd,chd
00132          */
00133         inline void set_iterator(Iterator_t &it) {
00134             it_ = &it;
00135         }
00136         inline void set_join_decision(JoinDecision_t &jd) {
00137             jd_ = &jd;
00138         }
00139         inline void set_cluster_head_decision(HeadDecision_t &chd) {
00140             chd_ = &chd;
00141         }
00142 
00143         /* Set Clustering Parameters
00144          * maxhops
00145          */
00146         inline void set_maxhops(uint8_t maxhops) {
00147             maxhops_ = maxhops;
00148             jd().set_maxhops(maxhops);
00149       if (hops()>maxhops){
00150          node_lost(parent());
00151       }
00152         }
00153 
00154         /* Get Clustering Values
00155          * cluster_id
00156          * parent
00157          * hops (from parent)
00158          * node_type
00159          * childs_count
00160          * childs
00161          * node_count (like childs)
00162          * is_gateway
00163          * is_cluster_head
00164          */
00165         inline cluster_id_t cluster_id(void) {
00166       if (enabled_)
00167             return it().cluster_id();
00168       else return 0;
00169         }
00170         inline node_id_t parent(void) {
00171             return it().parent();
00172         }
00173         inline uint8_t hops(void) {
00174             return it().hops();
00175         }
00176         inline int node_type(void) {
00177             return it().node_type();
00178         }
00179         inline int childs_count() {
00180             return it().childs_count();
00181         }
00182         inline void childs(node_id_t * list) {
00183             it().childs(list);
00184         }
00185         inline size_t node_count(int type){
00186             return  it().node_count(type);
00187         }
00188           inline bool is_gateway(){
00189             return it().is_gateway();
00190         }
00191         inline bool is_cluster_head() {
00192             if (node_type() != UNCLUSTERED) {
00193                 return it().cluster_id() == radio().id();
00194             } else {
00195                 return false;
00196             }
00197         }
00198 
00199         
00200         /*
00201          * Register a callback that prints specific debug information
00202          * upon any generated event
00203          */
00204         void register_debug_callback() {
00205 //            enable_debug_ = true;
00206         }
00207 
00208         /*
00209          * The status Of the Clustering Algorithm
00210          * 1 means a cluster is being formed
00211          * 0 means cluster is formed
00212          */
00213         inline uint8_t status() {
00214             //1 - forming , 0 - formed
00215             if (enabled_) {
00216                 return status_;
00217             } else {
00218                 return 2;
00219             }
00220         }
00221 
00222 
00223 
00224         /*
00225          * Size of the payload to the ND module beacon
00226          */
00227         inline size_t beacon_size() {
00228             JoinClusterMsg<OsModel, Radio> msg;
00229             // send a join payload
00230             return msg.length();
00231         }
00232 
00233                 /*
00234          * Receive a beacon payload
00235          * check for new head if needed
00236          * check if in need to reform
00237          */
00238         void receive_beacon(node_id_t node_from, size_t len, uint8_t * data) {
00239             //receive the beacon data
00240             JoinClusterMsg<OsModel, Radio> *msg;
00241             msg = (JoinClusterMsg<OsModel, Radio> *)data;
00242 //DOWN            memcpy(&msg, data, len);
00243             node_id_t cluster = msg->cluster_id();
00244             int hops = msg->hops();
00245 #ifndef SHAWN
00246             if (cluster == 0 ) return;
00247 #endif
00248 
00249        if (cluster == UNKNOWN_CLUSTER_HEAD) return;
00250 
00251             //if the connection to the cluster head was lost
00252             if (head_lost_) {
00253                 //if the beacon came from a cluster head
00254                 if ((hops < maxhops_) && (cluster < radio().id()) && (neighbor_discovery_->is_neighbor_bidi(node_from))) {
00255                     // join him
00256                     // inform iterator about the new cluster
00257                     it().set_parent(node_from);
00258                     it().set_cluster_id(cluster);
00259                     jd().set_cluster_id(cluster);
00260                     it().set_hops(hops+1);
00261                     jd().set_hops(hops+1);
00262                     it().set_node_type(SIMPLE);
00263                     it().node_joined(node_from);
00264 
00265                     //mark that the head_lost_ situation was resolved
00266                     head_lost_ = false;
00267 
00268                     JoinClusterMsg<OsModel, Radio> join_msg = jd().get_join_request_payload();
00269                     // Forward message from previous node
00270                     radio().send(Radio::BROADCAST_ADDRESS, join_msg.length(), (block_data_t *) & join_msg);
00271 #ifdef DEBUG_CLUSTERING
00272                     debug().debug("Send::%x::%d::%x::%d::", radio().id(),
00273                             join_msg.msg_id(), Radio::BROADCAST_ADDRESS,
00274                             join_msg.hops());
00275 #ifdef SHAWN
00276                     debug().debug("\n");
00277 #endif
00278 #endif
00279 //                    if (enable_debug_){
00280                         debug().debug("CLS;%x;%d;%x", radio().id(),
00281                             join_msg.msg_id(), Radio::BROADCAST_ADDRESS);
00282 //                    }
00283                     //set the timer to check for clustering end
00284                     timer().template set_timer
00285                             <self_type, &self_type::wait2form_cluster >
00286                             (time_slice_, this, (void*) 0);
00287                     }
00288             }
00289             else{
00290       receive(node_from,len,data);
00291             }
00292             //debug().debug("Node %x(%x) from %x(%x)\n",radio().id(),it().cluster_id(),node_from,cluster);
00293             //if Beacon from cluster neighbor
00294             if (cluster == it().cluster_id() ) {
00295                 it().node_joined(node_from);
00296             }//if Beacon from non cluster neighbor
00297             else {
00298                 it().node_not_joined(node_from, cluster);
00299                 notify_cradio(RESUME, cluster, node_from);
00300             }
00301 
00302             //if the sender was my cluster head but is no more a cluster head (possible reform was lost)
00303             if ((node_from == parent()) && (cluster != it().cluster_id())) {
00304                 node_lost(node_from);
00305             }
00306             if ((node_from == parent()) && (it().hops() != hops+1 )) {
00307                 node_lost(node_from);
00308             }
00309         }
00310 
00311         /*
00312          * Get a payload
00313          * to save on a beacon message
00314          */
00315         void get_beacon(uint8_t * mess) {
00316             JoinClusterMsg<OsModel, Radio> msg = jd().get_join_request_payload();
00317             memcpy(mess, &msg, msg.length());
00318         }
00319 
00320         void present_neighbors(void) {
00321             if (status() != 2) {
00322                 it().present_neighbors();
00323             }
00324         }
00325 
00326         /*
00327          * Enable
00328          * enables the clustering module
00329          * enable chd it and jd modules
00330          * calls find head to start clustering
00331          */
00332         inline void enable() {
00333 #ifdef SHAWN
00334             enable(6);
00335 #else
00336             enable(40);
00337 #endif
00338         }
00339 
00340         void enable(int start_in) {
00341             if (enabled_) return;
00342 
00343             //set as enabled
00344             enabled_ = true;
00345             head_lost_ = false;
00346 
00347 #ifdef DEBUG_CLUSTERING
00348             debug().debug("Enable::%x::%d::", radio().id(), maxhops_);
00349 #ifdef SHAWN
00350             debug().debug("\n");
00351 #endif
00352 #endif
00353 
00354 #ifdef FIXED_ROLES
00355             //HERE Define the roles For Each node in the network
00356             debug().debug("SettingRoles");
00357             //Vector Containing The NodeId - ClusterId To set the node to the network
00358             node_role_t roles_vector_[TOTAL_NODES];
00359 
00360             //All node Ids Have to be defined here as .first element of the pair
00361             roles_vector_[0].first = 0x96fc;
00362             roles_vector_[1].first = 0x96f4;
00363 
00364             //For Each Node Id defined Above A ClusterId has to be defined
00365             //If the NodeId is the same as the ClusterId then the node is ClusterHead
00366             //If Different then the Node Joins Cluster with Cluster Id and sets its parent to Cluster-Id (cluster head, simulate 1 hop cluster)
00367             roles_vector_[0].second = 0x96fc;
00368             roles_vector_[1].second = 0x96fc;
00369 
00370             //Run again for all Nodes in vector to set Iterator Lists
00371             for (int i = 0; i < 2; i++) {
00372                 //Run once for all Nodes in vector to set Roles
00373                 for (int i = 0; i < TOTAL_NODES; i++) {
00374                     set_role(roles_vector_[i].first, roles_vector_[i].second);
00375                 }
00376             }
00377 #endif
00378             // receive receive callback
00379             callback_id_ = radio().template reg_recv_callback<self_type,
00380                     &self_type::receive > (this);
00381             // set variables of other modules
00382             chd().set_attribute(radio().id());
00383             jd().set_maxhops(maxhops_);
00384 
00385 #ifndef FIXED_ROLES
00386 #ifdef SHAWN
00387             timer().template set_timer<self_type, &self_type::form_cluster > (
00388                     6000, this, (void *) maxhops_);
00389 #else
00390             timer().template set_timer<self_type, &self_type::form_cluster > (
00391                     start_in * 1000, this, (void *) maxhops_);
00392 #endif
00393 #endif
00394         }
00395 
00396         // Call with a timer to start a reform procedure from the cluster head
00397 
00398         inline void reform_cluster(void * parameter) {
00399             reform_ = true;
00400         }
00401 
00402         // Start the procedure needed to form a cluster
00403 
00404         void form_cluster(void * parameter) {
00405             if (!enabled_)
00406                 return;
00407             status_ = 1;
00408             //enabling
00409             chd().reset();
00410             chd().set_attribute(radio().id());
00411             jd().reset();
00412             it().reset();
00413 
00414             uint8_t buf[beacon_size()];
00415             get_beacon(buf);
00416 
00417             neighbor_discovery_->set_payload((uint8_t) CLUSTERING, buf,
00418                     beacon_size());
00419 
00420             // start the procedure to find new head
00421             timer().template set_timer<self_type, &self_type::find_head > (
00422                     rand()() % 300 + time_slice_, this, (void *) 0);
00423 
00424             // reform is false as cluster is not yet formed
00425             reform_ = false;
00426         }
00427 
00428         /*
00429          * Disable
00430          * disables the bfsclustering module
00431          * unregisters callbacks
00432          */
00433         inline void disable(void) {
00434             // Unregister the callback
00435             radio().unreg_recv_callback(callback_id_);
00436             enabled_ = false;
00437         }
00438         ;
00439 
00440         /*
00441          * wait2form_cluster
00442          * if wait2form_cluster is called and no
00443          * accept messages were received
00444          * there are no nodes under this one and
00445          * node has to respond to head with a resume message
00446          */
00447         void wait2form_cluster(void * timer_value) {
00448             // if none joind under the node
00449             if (!it().any_joined()) {
00450                 // if not a cluster head
00451                 if (it().node_type() != HEAD) {
00452                     // create a resume message
00453                     ResumeClusterMsg<OsModel, Radio> msg =
00454                             it().get_resume_payload();
00455                     //do send the message
00456                     radio().send(it().parent(), msg.length(), (block_data_t *) & msg);
00457 #ifdef DEBUG_CLUSTERING
00458                     debug().debug("CL::Send::from%x::type%d::to%x::", radio().id(), msg.msg_id(),
00459                             it().parent());
00460 #ifdef SHAWN
00461                     debug().debug("\n");
00462 #endif
00463 #else
00464 //                    if (enable_debug_) {
00465                         debug().debug("CLS;%x;%d;%x", radio().id(), msg.msg_id(),
00466                                 it().parent());
00467  //                   }
00468 #endif
00469 
00470 
00471                     // if a cluster head end the clustering under this branch
00472                 } else {
00473                     cluster_state_changed(CLUSTER_FORMED);
00474                     this->state_changed(CLUSTER_FORMED);
00475                     reset_beacon_payload();
00476                 }
00477                 status_ = 0;
00478             } else {
00479 
00480             }
00481         }
00482 
00483         /*
00484          * FIND_HEAD
00485          * starts clustering
00486          * decides a head and then start clustering
00487          * from the head of each cluster
00488          * */
00489         void find_head(void * value) {
00490 
00491             long round = (long) value;
00492 
00493             if (round < maxhops_) {
00494                 //SEND my Attribute to my neighbors (Broadcast the ID)
00495 
00496                 AttributeClusterMsg<OsModel, Radio> msg =
00497                         chd().get_attribute_payload();
00498                 radio().send(Radio::BROADCAST_ADDRESS, msg.length(),
00499                         (block_data_t *) & msg);
00500 #ifdef DEBUG_CLUSTERING
00501                 debug().debug("CL::Send::from%x::type%d::to%x::%d::%x::", radio().id(), ATTRIBUTE,
00502                             Radio::BROADCAST_ADDRESS, round, msg.attribute());
00503 #ifdef SHAWN
00504                 debug().debug("\n");
00505 #endif
00506 #else
00507 //                if (enable_debug_) {
00508                     debug().debug("CLS;%x;%d;%x", radio().id(), ATTRIBUTE,
00509                         Radio::BROADCAST_ADDRESS);
00510 //                }
00511 #endif
00512 
00513 
00514                 round++;
00515 
00516                 //Recall find_head funtion to resend attribute messages if round<maxhops or elect cluster heads
00517                 timer().template set_timer<self_type, &self_type::find_head > (
00518                         time_slice_, this, (void *) round);
00519 
00520             } else {
00521                 // if Cluster Head
00522                 if (chd().calculate_head() == true) {
00523 
00524 
00525                     // set values for iterator and join_decision
00526                     it().set_parent(radio().id());
00527                     it().set_cluster_id(radio().id());
00528                     jd().set_cluster_id(radio().id());
00529                     it().set_hops(0);
00530                     jd().set_hops(0);
00531 
00532 
00533 
00534                     // inform : node is a cluster head
00535                     cluster_state_changed(CLUSTER_HEAD_CHANGED);
00536                     this->state_changed(CLUSTER_HEAD_CHANGED);
00537                     reset_beacon_payload();
00538 
00539                     if (auto_reform_ > 0) {
00540                         timer().template set_timer<self_type,
00541                                 &self_type::reform_cluster > (auto_reform_
00542                                 * time_slice_, this, (void *) maxhops_);
00543                     }
00544 
00545                     status_ = 0;
00546 
00547                     JoinClusterMsg<OsModel, Radio> join_msg =
00548                             jd().get_join_request_payload();
00549                     // send JOIN
00550                     radio().send(Radio::BROADCAST_ADDRESS, join_msg.length(),
00551                             (block_data_t *) & join_msg);
00552 #ifdef DEBUG_CLUSTERING
00553                     debug().debug("CL::Send::from%x::type%d::to%x::", radio().id(),
00554                             join_msg.msg_id(), Radio::BROADCAST_ADDRESS);
00555 #ifdef SHAWN
00556                     debug().debug("\n");
00557 #endif
00558 #else
00559 //                    if (enable_debug_) {
00560                         debug().debug("CLS;%x;%d;%x", radio().id(),
00561                                 join_msg.msg_id(), Radio::BROADCAST_ADDRESS);
00562 //                    }
00563 #endif
00564 
00565                     //Check after some time if any accept messages were received
00566                     //2*time_slice for messages to be sent and received
00567                     timer().template set_timer<self_type, &self_type::wait2form_cluster > (
00568                             4 * maxhops_ * time_slice_, this, 0);
00569                 } else {
00570                     timer().template set_timer<self_type, &self_type::wait_for_joins > (time_slice_ / 2, this, (void *) 1);
00571                 }
00572             }
00573         }
00574 
00575 #ifdef FIXED_ROLES
00576 
00577         void set_role(node_id_t node, node_id_t cluster) {
00578             if (node == radio().id()) {
00579                 debug().debug("Node %x is in %x", node, cluster);
00580                 it().set_parent(cluster);
00581                 it().set_cluster_id(cluster);
00582                 jd().set_cluster_id(cluster);
00583                 if (cluster == radio().id()) {
00584                     it().set_hops(0);
00585                 } else {
00586                     it().set_hops(1);
00587                 }
00588             } else {
00589                 if (cluster == it().cluster_id()) {
00590                     it().node_joined(node);
00591                 } else {
00592                     it().node_not_joined(node);
00593                 }
00594             }
00595         }
00596 #endif
00597 
00598         template<class T, void(T::*TMethod)(uint8_t, node_id_t, node_id_t) >
00599         uint8_t reg_notify_cradio(T * obj_pnt) {
00600             cradio_delegate_ = cradio_delegate_t::template from_method<T, TMethod > (obj_pnt);
00601             return 0;
00602         }
00603 
00604         node_id_t get_next_node_to_child(node_id_t dest) {
00605             return it().get_child(dest);
00606         }
00607 
00608     protected:
00609 
00610         /*
00611          * Called when ND lost contact with a node
00612          * If the node was cluster head
00613          *  - start searching for new head
00614          * else
00615          *  - remove node from known nodes
00616          */
00617         void node_lost(node_id_t node) {
00618 
00619             if (status_ == 0) {
00620                 //If the node was my route to CH
00621                 if (node == parent()) {
00622                     //Reset Iterator
00623                     it().reset();
00624                     //Mark as headless
00625                     head_lost_ = true;
00626                     //Timeout for new CH beacons
00627                     timer().template set_timer <self_type, &self_type::wait_for_joins > (1000, this, (void*) 0);
00628                 } else {
00629                     //if not my CH
00630                     //Remove from Iterator
00631                     it().drop_node(node);
00632                 }
00633             }
00634         }
00635 
00636         void cluster_state_changed(int event) throw () {
00637                     debug().debug("CLP;%x;%d;%x", radio().id(), it().node_type(), it().cluster_id());
00638 /*CDOWN
00639 //            if (enable_debug_) {
00640                 if (event == wiselib::NODE_JOINED) {
00641 //                    debug().debug("Present::%x::%d::%x::%d::%x::", radio().id(), it().node_type(), it().cluster_id(), it().hops(), it().parent());
00642                     debug().debug("Present::%x::%d::%x::", radio().id(), it().node_type(), it().cluster_id());
00643 #ifdef SHAWN
00644                     debug().debug("\n");
00645 #endif
00646                 } else if (event == wiselib::CLUSTER_HEAD_CHANGED) {
00647 //                    debug().debug("Present::%x::%d::%d::%d::", radio().id(), it().node_type(), it().childs_count(), 0);
00648                     debug().debug("Present::%x::%d::", radio().id(), it().node_type(), it().childs_count(), 0);
00649 #ifdef SHAWN
00650                     debug().debug("\n");
00651 #endif
00652                 }
00653 //            }
00654  */
00655         }
00656 
00657         /*
00658          * RECEIVE
00659          * respond to the new messages received
00660          * callback from the radio
00661          * */
00662         void receive(node_id_t from, size_t len, block_data_t * recvm) {
00663 
00664             if (radio().id() == from)
00665                 return;
00666             if (!neighbor_discovery_->is_neighbor_bidi(from))
00667                 return;
00668 
00669 //CDOWN            uint8_t type = *recvm;
00670 
00671             if (*recvm == ATTRIBUTE) {
00672 #ifdef DEBUG_RECEIVED
00673                 debug().debug("Received::%x::%d::%x::%d::", radio().id(), *recvm, from, len);
00674 #endif
00675                 chd().receive(from, len, recvm);
00676             }
00677 
00678             if (*recvm == JOIN) {
00679                 //                if ((!status()) || (it().node_type() == HEAD)) return;
00680 
00681 #ifdef DEBUG_RECEIVED
00682                 debug().debug("Received::%x::%d::%x::%d::", radio().id(), *recvm, from, len);
00683 #endif
00684 
00685                 // check if the node Joins
00686                 if (jd().join(recvm, len)) {
00687 
00688                     // set values for iterator and join_decision
00689                     it().set_parent(from);
00690                     it().set_cluster_id(jd().cluster_id());
00691                     it().set_node_type(SIMPLE);
00692                     it().node_joined(from);
00693                     it().set_hops(jd().hops());
00694 
00695                     cluster_state_changed(NODE_JOINED);
00696                     this->state_changed(NODE_JOINED);
00697 
00698            ResumeClusterMsg<OsModel, Radio> msg =
00699                             it().get_resume_payload();
00700                     //do send the message
00701                     radio().send(it().parent(), msg.length(), (block_data_t *) & msg);
00702 #ifdef DEBUG_CLUSTERING
00703                     debug().debug("CL::Send::from%x::type%d::to%x::", radio().id(), msg.msg_id(),
00704                             it().parent());
00705 #ifdef SHAWN
00706                     debug().debug("\n");
00707 #endif
00708 #else
00709 //                    if (enable_debug_) {
00710                         debug().debug("CLS;%x;%d;%x", radio().id(), msg.msg_id(),
00711                                 it().parent());
00712  //                   }
00713 #endif
00714 
00715 
00716                 }
00717             } else if (*recvm == RESUME) {
00718                 if (from == parent()) return;
00719 
00720 //CDOWN                ResumeClusterMsg<OsModel, Radio> msg;
00721                 ResumeClusterMsg<OsModel, Radio> *msg;
00722                 msg = (ResumeClusterMsg<OsModel, Radio> *)recvm;
00723 //CDOWN                memcpy(&msg, recvm, len);
00724 #ifdef DEBUG_RECEIVED
00725                 debug().debug("Received::%x::%d::%x::%d::", radio().id(), msg->mess_id(), from, len);
00726 #endif
00727                 // if not a cluster head forward the message to head
00728                 if (it().node_type() != HEAD) {
00729 
00730                     //cluster is formed
00731                     status_ = 0;
00732 
00733                     //do send the message
00734                     radio().send(it().parent(), len, (block_data_t *) msg);
00735                     it().add_resume(from, msg->node_id());
00736 
00737 #ifdef DEBUG_CLUSTERING
00738                     debug().debug("CL::Send::from%x::type%d::to%x::forw::", radio().id(),
00739                             msg->msg_id(), it().parent()); //old4
00740 #ifdef SHAWN
00741                     debug().debug("\n");
00742 #endif
00743 #else
00744 //                    if (enable_debug_) {
00745                         debug().debug("CLS;%x;%d;%x", radio().id(),
00746                                 msg->msg_id(), it().parent()); //old4
00747 //                    }
00748 #endif
00749 
00750                 } else {
00751                     //if a cluster head add node to cluster nodes
00752                     it().node_joined(msg->node_id());
00753                     it().add_resume(from, msg->node_id());
00754                 }
00755 
00756                 notify_cradio(RESUME, msg->node_id(), from);
00757             }
00758         }
00759 
00760         void notify_cradio(uint8_t event, cluster_id_t from, node_id_t to) {
00761             if (cradio_delegate_ != 0) {
00762                 cradio_delegate_(event, from, to);
00763             }
00764         }
00765 
00766         // --------------------------------------------------------------------
00767 
00768         void wait_for_joins(void * data) {
00769 
00770             long wait_round = (long) data;
00771             if (it().node_type() == UNCLUSTERED) {
00772 
00773                 if (wait_round < maxhops_) {
00774 #ifdef DEBUG_CLUSTERING_EXTRA
00775                     debug().debug("Waiting::%x::%d::", radio().id(), wait_round);
00776 #endif
00777                     //reset the timer and wait for wait_round+1 hop cluster heads
00778                     timer().template set_timer
00779                             <self_type, &self_type::wait_for_joins >
00780                             (time_slice_ / 2, this, (void *) (wait_round + 1));
00781                 } else {
00782 
00783                     head_lost_ = false;
00784                     //no cluster head in maxhops
00785 
00786                     // set values for iterator and join_decision
00787                     it().set_parent(radio().id());
00788                     it().set_cluster_id(radio().id());
00789                     jd().set_cluster_id(radio().id());
00790                     it().set_hops(0);
00791                     jd().set_hops(0);
00792 
00793 #ifdef DEBUG_CLUSTERING
00794                     debug().debug("ForcedCH::%x::", radio().id());
00795 #ifdef SHAWN
00796                     debug().debug("\n");
00797 #endif
00798 #endif
00799                     //INFORM I AM A CLUSTER HEAD
00800                     cluster_state_changed(CLUSTER_HEAD_CHANGED);
00801                     this->state_changed(CLUSTER_HEAD_CHANGED);
00802                     reset_beacon_payload();
00803 
00804                     if (auto_reform_ > 0) {
00805                         // set timer to periodically reform the cluster
00806                         timer().template set_timer
00807                                 <self_type, &self_type::reform_cluster >
00808                                 ((auto_reform_ - maxhops_) * time_slice_, this, (void *) maxhops_);
00809                     }
00810 
00811                     // the cluster was formed
00812                     status_ = 0;
00813 
00814                     JoinClusterMsg<OsModel, Radio> join_msg = jd().get_join_request_payload();
00815                     // Forward message from previous node
00816                     radio().send(Radio::BROADCAST_ADDRESS, join_msg.length(), (block_data_t *) & join_msg);
00817 #ifdef DEBUG_CLUSTERING
00818                     debug().debug("Send::%x::%d::%x::%d::", radio().id(),
00819                             join_msg.msg_id(), Radio::BROADCAST_ADDRESS,
00820                             join_msg.hops());
00821 #ifdef SHAWN
00822                     debug().debug("\n");
00823 #endif
00824 #endif
00825 
00826 
00827                     //Check after some time if Any accept messages were received
00828                     //2*time_slice for messages to be sent and received
00829                     //timer().template set_timer<self_type, &self_type::wait2form_cluster > (2 * time_slice_, this, 0);
00830 
00831                     //call timer expired to finallize cluster formation
00832                     wait2form_cluster(0);
00833                 }
00834             } else {
00835                 head_lost_ = false;
00836                 if (hops() < maxhops_) {
00837                     JoinClusterMsg<OsModel, Radio> join_msg =
00838                             jd().get_join_request_payload();
00839                     // Forward message from previous node
00840                     radio().send(Radio::BROADCAST_ADDRESS, join_msg.length(),
00841                             (block_data_t *) & join_msg);
00842 #ifdef DEBUG_CLUSTERING
00843                     debug().debug("CL::Send::from%x::type%d::to%x::%d::", radio().id(),
00844                             join_msg.msg_id(), Radio::BROADCAST_ADDRESS,
00845                             join_msg.hops());
00846 #ifdef SHAWN
00847                     debug().debug("\n");
00848 #endif
00849 #else
00850 //                    if (enable_debug_) {
00851                         debug().debug("CLS;%x;%d;%x", radio().id(),
00852                                 join_msg.msg_id(), Radio::BROADCAST_ADDRESS);
00853 //                    }
00854 #endif
00855 
00856                     //set the timer to check for clustering end
00857                     timer().template set_timer
00858                             <self_type, &self_type::wait2form_cluster >
00859                             (2 * (maxhops_ - hops()) * time_slice_, this, (void*) 0);
00860                 } else {
00861                     // if no more hops to propagate the join message finalize cluster formation
00862                     wait2form_cluster(0);
00863                 }
00864                 //notify for join
00865                 cluster_state_changed(NODE_JOINED);
00866                 this->state_changed(NODE_JOINED);
00867                 reset_beacon_payload();
00868             }
00869         }
00870 
00871         // --------------------------------------------------------------------
00872 
00873         void reset_beacon_payload() {
00874             //reset my beacon according to the new status
00875             uint8_t buf[beacon_size()];
00876             get_beacon(buf);
00877             if (neighbor_discovery_->set_payload((uint8_t) CLUSTERING, buf,
00878                     it().cluster_id() != UNKNOWN_CLUSTER_HEAD ? beacon_size() : 0) != 0) {
00879 #ifdef DEBUG_CLUSTERING
00880                 debug_->debug("Error::%x::", radio_->id());
00881 #endif
00882             }
00883         }
00884         // --------------------------------------------------------------------
00885 
00886         void ND_callback(uint8_t event, node_id_t from, uint8_t len, uint8_t * data) {
00887             if (nb_t::NEW_PAYLOAD_BIDI == event) {
00888                 receive_beacon(from, len, data);
00889                 //reset my beacon according to the new status
00890                 reset_beacon_payload();
00891             } else if ((nb_t::LOST_NB_BIDI == event) || (nb_t::DROPPED_NB == event)) {
00892 #ifndef FIXED_ROLES
00893 #ifdef MAINTENANCE
00894                 node_lost(from);
00895 #endif
00896 #endif
00897             }
00898         }
00899 
00900     private:
00901         nb_t * neighbor_discovery_;
00902         bool enabled_;
00903 //        bool enable_debug_;
00904         uint8_t status_; // the status of the clustering algorithm
00905         int callback_id_; // receive message callback
00906         int maxhops_; // clustering parameter
00907         static const uint32_t time_slice_ = 2000; // time to wait for cluster accept replies
00908         int auto_reform_; //time to autoreform the clusters
00909         bool reform_; // flag to start reforming
00910         bool head_lost_; // flag when the head was lost
00911 
00912         cradio_delegate_t cradio_delegate_;
00913 
00914 
00915 
00916         /* CLustering algorithm modules */
00917         HeadDecision_t * chd_;
00918 
00919         inline HeadDecision_t & chd() {
00920             return *chd_;
00921         }
00922         JoinDecision_t * jd_;
00923 
00924         inline JoinDecision_t & jd() {
00925             return *jd_;
00926         }
00927         Iterator_t * it_;
00928 
00929         inline Iterator_t & it() {
00930             return *it_;
00931         }
00932 
00933         Radio * radio_; // radio module
00934         Timer * timer_; // timer module
00935         Debug * debug_; // debug module
00936 
00937         Rand * rand_;
00938 
00939         Radio & radio() {
00940             return *radio_;
00941         }
00942 
00943         Timer & timer() {
00944             return *timer_;
00945         }
00946 
00947         Debug & debug() {
00948 #ifdef SHAWN
00949           debug_->debug("\n");
00950 #endif
00951             return *debug_;
00952         }
00953 
00954         Rand & rand() {
00955             return *rand_;
00956         }
00957     };
00958 }
00959 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines