Wiselib
wiselib.stable/algorithms/routing/tree/tree_routing.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  ** This file is part of the generic algorithm library Wiselib.           **
00003  ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project.      **
00004  **                                                                       **
00005  ** The Wiselib is free software: you can redistribute it and/or modify   **
00006  ** it under the terms of the GNU Lesser General Public License as        **
00007  ** published by the Free Software Foundation, either version 3 of the    **
00008  ** License, or (at your option) any later version.                       **
00009  **                                                                       **
00010  ** The Wiselib is distributed in the hope that it will be useful,        **
00011  ** but WITHOUT ANY WARRANTY; without even the implied warranty of        **
00012  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
00013  ** GNU Lesser General Public License for more details.                   **
00014  **                                                                       **
00015  ** You should have received a copy of the GNU Lesser General Public      **
00016  ** License along with the Wiselib.                                       **
00017  ** If not, see <http://www.gnu.org/licenses/>.                           **
00018  ***************************************************************************/
00019 #ifndef __ALGORITHMS_ROUTING_TREEROUTING_H__
00020 #define __ALGORITHMS_ROUTING_TREEROUTING_H__
00021 
00022 #include "util/base_classes/routing_base.h"
00023 #include "util/serialization/simple_types.h"
00024 #include "algorithms/routing/tree/tree_broadcast_message.h"
00025 #include "algorithms/routing/tree/tree_routing_message.h"
00026 #include "config.h"
00027 
00028 namespace wiselib
00029 {
00030 
00041    template<typename OsModel_P,
00042             typename Radio_P = typename OsModel_P::Radio,
00043             typename Timer_P = typename OsModel_P::Timer,
00044             typename Debug_P = typename OsModel_P::Debug>
00045    class TreeRouting
00046       : public RoutingBase<OsModel_P, Radio_P>
00047    {
00048    public:
00049       typedef OsModel_P OsModel;
00050       typedef Radio_P Radio;
00051       typedef Timer_P Timer;
00052       typedef Debug_P Debug;
00053 
00054       typedef TreeRouting<OsModel, Radio, Timer, Debug> self_type;
00055       typedef self_type* self_pointer_t;
00056 
00057       typedef typename Radio::node_id_t node_id_t;
00058       typedef typename Radio::size_t size_t;
00059       typedef typename Radio::block_data_t block_data_t;
00060       typedef typename Radio::message_id_t message_id_t;
00061 
00062       typedef typename Timer::millis_t millis_t;
00063 
00064       typedef TreeBroadcastMessage<OsModel, Radio> BroadcastMessage;
00065       typedef TreeRoutingMessage<OsModel, Radio> RoutingMessage;
00066       // --------------------------------------------------------------------
00067       enum ErrorCodes
00068       {
00069          SUCCESS = OsModel::SUCCESS,
00070          ERR_UNSPEC = OsModel::ERR_UNSPEC,
00071          ERR_NOTIMPL = OsModel::ERR_NOTIMPL,
00072          ERR_NETDOWN = OsModel::ERR_NETDOWN
00073       };
00074       // --------------------------------------------------------------------
00075       enum SpecialNodeIds
00076       {
00077          BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 
00078          NULL_NODE_ID      = Radio_P::NULL_NODE_ID      
00079       };
00080       // --------------------------------------------------------------------
00081       enum Restrictions
00082       {
00083          MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH - RoutingMessage::PAYLOAD_POS  
00084       };
00085       // --------------------------------------------------------------------
00088       TreeRouting();
00089       ~TreeRouting();
00091 
00092       int init( Radio& radio, Timer& timer, Debug& debug )
00093       {
00094          radio_ = &radio;
00095          timer_ = &timer;
00096          debug_ = &debug;
00097          return SUCCESS;
00098       }
00099 
00100       inline int init();
00101       inline int destruct();
00102 
00105 
00125       int enable_radio( void );
00130       int disable_radio( void );
00135       inline void set_sink( bool sink );
00137 
00140 
00142       int send( node_id_t receiver, size_t len, block_data_t *data );
00148       void receive( node_id_t from, size_t len, block_data_t *data );
00151       typename Radio::node_id_t id()
00152       { return radio_->id(); }
00154 
00157 
00165       void timer_elapsed( void *userdata );
00167 
00168       uint8_t hops() {
00169         return hops_;
00170       };
00171 
00172       node_id_t parent() {
00173         return parent_;
00174       };
00175 
00176    private:
00177       Radio& radio()
00178       { return *radio_; }
00179 
00180       Timer& timer()
00181       { return *timer_; }
00182 
00183       Debug& debug()
00184       { return *debug_; }
00185 
00186       typename Radio::self_pointer_t radio_;
00187       typename Timer::self_pointer_t timer_;
00188       typename Debug::self_pointer_t debug_;
00189 
00192       enum TreeRoutingMsgIds
00193       {
00194          TrMsgIdBroadcast = 100, 
00195          TrMsgIdRouting   = 101  
00196       };
00197 
00198       enum TreeRoutingState
00199       {
00200          TrGateway,
00201          TrConnected,
00202          TrUnconnected
00203       };
00204 
00205       TreeRoutingState state_;
00207       millis_t work_period_;
00208       node_id_t parent_;
00209       uint8_t hops_;
00210    };
00211    // -----------------------------------------------------------------------
00212    // -----------------------------------------------------------------------
00213    // -----------------------------------------------------------------------
00214    template<typename OsModel_P,
00215             typename Radio_P,
00216             typename Timer_P,
00217             typename Debug_P>
00218    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00219    TreeRouting()
00220       : state_         ( TrUnconnected ),
00221          work_period_  ( 5000 ),
00222          parent_       ( Radio::NULL_NODE_ID ),
00223          hops_         ( 0 )
00224    {}
00225    // -----------------------------------------------------------------------
00226    template<typename OsModel_P,
00227             typename Radio_P,
00228             typename Timer_P,
00229             typename Debug_P>
00230    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00231    ~TreeRouting()
00232    {
00233 #ifdef ROUTING_TREE_DEBUG
00234       debug().debug( "TreeRouting: Destroyed\n" );
00235 #endif
00236    }
00237    // -----------------------------------------------------------------------
00238    template<typename OsModel_P,
00239             typename Radio_P,
00240             typename Timer_P,
00241             typename Debug_P>
00242    int
00243    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00244    init( void )
00245    {
00246       if ( state_ == TrConnected )
00247       {
00248          state_ = TrUnconnected;
00249          parent_ = Radio::NULL_NODE_ID;
00250          hops_ = 0;
00251       }
00252       enable_radio();
00253 
00254       return SUCCESS;
00255    }
00256    // -----------------------------------------------------------------------
00257    template<typename OsModel_P,
00258             typename Radio_P,
00259             typename Timer_P,
00260             typename Debug_P>
00261    int
00262    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00263    destruct( void )
00264    {
00265       return disable_radio();
00266    }
00267    // -----------------------------------------------------------------------
00268    template<typename OsModel_P,
00269             typename Radio_P,
00270             typename Timer_P,
00271             typename Debug_P>
00272    int
00273    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00274    enable_radio( void )
00275    {
00276       radio().enable_radio();
00277       radio().template reg_recv_callback<self_type, &self_type::receive>( this );
00278 #ifdef ROUTING_TREE_DEBUG
00279       debug().debug( "TreeRouting: Boot for %i\n", radio().id() );
00280 #endif
00281       if ( state_ == TrGateway )
00282       {
00283          parent_ = radio().id();
00284          hops_ = 0;
00285 #ifdef ROUTING_TREE_DEBUG
00286          debug().debug( "TreeRouting: Start as sink/gateway\n" );
00287 #endif
00288       }
00289       else
00290       {
00291          parent_ = radio().NULL_NODE_ID;
00292          hops_   = 0xff;
00293 #ifdef ROUTING_TREE_DEBUG
00294          debug().debug( "TreeRouting: Start as ordinary node\n" );
00295 #endif
00296       }
00297 
00298       timer().template set_timer<self_type, &self_type::timer_elapsed>(
00299                                  work_period_, this, 0 );
00300 
00301       return SUCCESS;
00302    }
00303    // -----------------------------------------------------------------------
00304    template<typename OsModel_P,
00305             typename Radio_P,
00306             typename Timer_P,
00307             typename Debug_P>
00308    int
00309    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00310    disable_radio( void )
00311    {
00312 #ifdef ROUTING_TREE_DEBUG
00313       debug().debug( "TreeRouting: Should stop routing now...\n" );
00314 #endif
00315       return ERR_NOTIMPL;
00316    }
00317    // -----------------------------------------------------------------------
00318    template<typename OsModel_P,
00319             typename Radio_P,
00320             typename Timer_P,
00321             typename Debug_P>
00322    void
00323    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00324    set_sink( bool sink )
00325    {
00326       if ( sink )
00327          state_ = TrGateway;
00328       else
00329          state_ = TrUnconnected;
00330    }
00331    // -----------------------------------------------------------------------
00332    template<typename OsModel_P,
00333             typename Radio_P,
00334             typename Timer_P,
00335             typename Debug_P>
00336    int
00337    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00338    send( node_id_t receiver, size_t len, block_data_t *data )
00339    {
00340       if ( parent_ != radio().NULL_NODE_ID )
00341       {
00342 #ifdef ROUTING_TREE_DEBUG
00343          debug().debug( "TreeRouting: Send to Gate over %i...\n", parent_ );
00344 #endif
00345          RoutingMessage message( TrMsgIdRouting, radio().id() );
00346          message.set_payload( len, data );
00347          radio().send( parent_, message.buffer_size(), (uint8_t*)&message );
00348 
00349          return SUCCESS;
00350       }
00351       else
00352       {
00353 #ifdef ROUTING_TREE_DEBUG
00354          debug().debug( "TreeRouting: Not Connected. Cannot send.\n" );
00355 #endif
00356          return ERR_NETDOWN;
00357       }
00358    }
00359    // -----------------------------------------------------------------------
00360    template<typename OsModel_P,
00361             typename Radio_P,
00362             typename Timer_P,
00363             typename Debug_P>
00364    void
00365    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00366    timer_elapsed( void* userdata )
00367    {
00368 #ifdef ROUTING_TREE_DEBUG
00369       debug().debug( "TreeRouting: Execute Task 'TreeRouting' at %i\n", radio().id() );
00370 #endif
00371 
00372       switch ( state_ )
00373       {
00374          case TrGateway:
00375          case TrConnected:
00376          {
00377             BroadcastMessage message( TrMsgIdBroadcast, hops_, parent_ );
00378             radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*)&message );
00379             break;
00380          }
00381          case TrUnconnected:
00382 #ifdef ROUTING_TREE_DEBUG
00383             debug().debug( "TreeRouting: Not connected. Waiting for FloodingMessage\n" );
00384 #endif
00385             break;
00386 #ifdef ROUTING_TREE_DEBUG
00387          default:
00388             debug().debug( "TreeRouting: Warning! Should not be reached!\n" );
00389 #endif
00390       }
00391 
00392       timer().template set_timer<self_type, &self_type::timer_elapsed>(
00393                                  work_period_, this, 0 );
00394    }
00395    // -----------------------------------------------------------------------
00396    template<typename OsModel_P,
00397             typename Radio_P,
00398             typename Timer_P,
00399             typename Debug_P>
00400    void
00401    TreeRouting<OsModel_P, Radio_P, Timer_P, Debug_P>::
00402    receive( node_id_t from, size_t len, block_data_t *data )
00403    {
00404 #ifdef ROUTING_TREE_DEBUG
00405      //debug().debug( "TreeRouting: Received t %i l %i f %i\n", (block_data_t)*data, len, from );
00406 #endif
00407 
00408       if ( from == radio().id() )
00409          return;
00410 
00411       message_id_t msg_id = read<OsModel, block_data_t, message_id_t>( data );
00412       if ( msg_id == TrMsgIdBroadcast )
00413       {
00414          BroadcastMessage *message = reinterpret_cast<BroadcastMessage*>(data);
00415          if ( message->hops() + 1 < hops_ )
00416          {
00417             hops_ = message->hops() + 1;
00418             parent_ = from;
00419             state_ = TrConnected;
00420 #ifdef ROUTING_TREE_DEBUG
00421             debug().debug( "TreeRouting:   -> Updated hop count to %i (at %i with p %i)\n",
00422                hops_, radio().id(), parent_ );
00423 #endif
00424          }
00425       }
00426       else if ( msg_id == TrMsgIdRouting )
00427       {
00428          if ( state_ == TrGateway )
00429          {
00430             RoutingMessage *message = reinterpret_cast<RoutingMessage*>(data);
00431             notify_receivers( message->source(), message->payload_size(), message->payload() );
00432 #ifdef ROUTING_TREE_DEBUG
00433             debug().debug( "TreeRouting: Routing message at Gate from %i\n", message->source() );
00434 #endif
00435          }
00436          else if ( parent_ != radio().NULL_NODE_ID )
00437          {
00438             radio().send( parent_, len, data );
00439 #ifdef ROUTING_TREE_DEBUG
00440             debug().debug( "TreeRouting: Forward routing message at %i to %i\n", radio().id(), parent_ );
00441 #endif
00442          }
00443       }
00444    }
00445 
00446 }
00447 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines