Wiselib
|
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