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_CONTROLLEDTOPOLOGYTREEROUTING_H__ 00020 #define __ALGORITHMS_ROUTING_CONTROLLEDTOPOLOGYTREEROUTING_H__ 00021 00022 #include "util/pstl/algorithm.h" 00023 #include "util/base_classes/routing_base.h" 00024 #include "algorithms/routing/tree/tree_broadcast_message.h" 00025 #include "algorithms/routing/tree/tree_routing_message.h" 00026 00027 namespace wiselib 00028 { 00029 00038 template<typename OsModel_P, 00039 typename Timer_P = typename OsModel_P::Timer, 00040 typename Radio_P = typename OsModel_P::Radio, 00041 typename Debug_P = typename OsModel_P::Debug, 00042 typename OsModel_P::size_t MAX_NEIGHBORS=32> 00043 class ControlledTopologyTreeRouting 00044 : public RoutingBase<OsModel_P, Radio_P> 00045 { 00046 public: 00047 typedef OsModel_P OsModel; 00048 typedef Timer_P Timer; 00049 typedef Radio_P Radio; 00050 typedef Debug_P Debug; 00051 00052 typedef ControlledTopologyTreeRouting<OsModel, Timer, Radio, Debug, MAX_NEIGHBORS> self_type; 00053 00054 typedef typename Radio::node_id_t node_id_t; 00055 typedef typename Radio::size_t size_t; 00056 typedef typename Radio::block_data_t block_data_t; 00057 typedef uint8_t message_id_t; 00058 00059 typedef typename Timer::millis_t millis_t; 00060 00061 typedef TreeBroadcastMessage<OsModel, Radio> BroadcastMessage; 00062 typedef TreeRoutingMessage<OsModel, Radio> RoutingMessage; 00063 00064 typedef vector_static<OsModel,node_id_t,MAX_NEIGHBORS> Neighbors; 00065 00066 // -------------------------------------------------------------------- 00067 enum ErrorCodes 00068 { 00069 SUCCESS = OsModel::SUCCESS, 00070 ERR_UNSPEC = OsModel::ERR_UNSPEC, 00071 ERR_NOTIMPL = OsModel::ERR_NOTIMPL, 00072 ERR_HOSTUNREACH = OsModel::ERR_HOSTUNREACH 00073 }; 00074 // -------------------------------------------------------------------- 00075 enum SpecialNodeIds { 00076 BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 00077 NULL_NODE_ID = Radio_P::NULL_NODE_ID 00078 }; 00079 // -------------------------------------------------------------------- 00080 enum Restrictions { 00081 MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH - RoutingMessage::PAYLOAD_POS 00082 }; 00083 // -------------------------------------------------------------------- 00084 00087 ControlledTopologyTreeRouting(); 00088 ~ControlledTopologyTreeRouting(); 00090 00093 00113 void enable( void ); 00118 void disable( void ); 00123 inline void set_sink( bool sink ); 00125 00128 00131 void send( node_id_t receiver, size_t len, block_data_t *data ); 00133 00136 00144 void timer_elapsed( void *userdata ); 00146 00149 00154 void receive( node_id_t from, size_t len, block_data_t *data ); 00156 00157 void set_topology(Neighbors *t=0){ 00158 topology_=t; 00159 } 00160 00161 Neighbors *topology(){ 00162 return topology_; 00163 } 00164 00165 node_id_t parent() const { 00166 return parent_; 00167 } 00168 00169 #ifdef DEBUG 00170 void init( Radio& radio, Timer& timer, Debug& debug ) { 00171 radio_ = &radio; 00172 timer_ = &timer; 00173 debug_ = &debug; 00174 } 00175 #else 00176 void init( Radio& radio, Timer& timer) { 00177 radio_ = &radio; 00178 timer_ = &timer; 00179 } 00180 #endif 00181 00182 void destruct() { 00183 } 00184 00185 private: 00186 Radio& radio() 00187 { return *radio_; } 00188 00189 Timer& timer() 00190 { return *timer_; } 00191 00192 #ifdef DEBUG 00193 Debug& debug() 00194 { return *debug_; } 00195 #endif 00196 00197 Radio * radio_; 00198 Timer * timer_; 00199 #ifdef DEBUG 00200 Debug * debug_; 00201 #endif 00202 00205 enum TreeRoutingMsgIds { 00206 TrMsgIdBroadcast = 209, 00207 TrMsgIdRouting = 210 00208 }; 00209 00210 enum TreeRoutingState { 00211 TrGateway, 00212 TrConnected, 00213 TrUnconnected 00214 }; 00215 00216 TreeRoutingState state_; 00218 millis_t work_period_; 00219 node_id_t parent_; 00220 uint8_t hops_; 00221 Neighbors *topology_; 00222 bool enabled; 00223 }; 00224 // ----------------------------------------------------------------------- 00225 // ----------------------------------------------------------------------- 00226 // ----------------------------------------------------------------------- 00227 template<typename OsModel_P, 00228 typename Timer_P, 00229 typename Radio_P, 00230 typename Debug_P, 00231 typename OsModel_P::size_t MAX_NEIGHBORS> 00232 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00233 ControlledTopologyTreeRouting() 00234 : state_ ( TrUnconnected ), 00235 work_period_ ( 5000 ), 00236 parent_ ( Radio::NULL_NODE_ID ), 00237 topology_ ( 0 ), 00238 enabled(false) 00239 { 00240 // Attention! Depending on where an instance is created, there may be not 00241 // all information available. E.g., if a ControlledTopologyTreeRouting object is a global 00242 // one, accessing OsModel::get_firmware_instance() may fail because the 00243 // firmware instance may not exist yet. 00244 // 00245 // Hence, only /private assignments/ are allowed to be done here! 00246 } 00247 // ----------------------------------------------------------------------- 00248 template<typename OsModel_P, 00249 typename Timer_P, 00250 typename Radio_P, 00251 typename Debug_P, 00252 typename OsModel_P::size_t MAX_NEIGHBORS> 00253 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00254 ~ControlledTopologyTreeRouting() 00255 { 00256 #ifdef DEBUG 00257 debug().debug( "ControlledTopologyTreeRouting: Destroyed\n" ); 00258 #endif 00259 } 00260 // ----------------------------------------------------------------------- 00261 template<typename OsModel_P, 00262 typename Timer_P, 00263 typename Radio_P, 00264 typename Debug_P, 00265 typename OsModel_P::size_t MAX_NEIGHBORS> 00266 void 00267 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00268 enable( void ) 00269 { 00270 enabled=true; 00271 // work_period_ = 15000; 00272 00273 //radio().enable_radio(); 00274 radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00275 #ifdef DEBUG 00276 debug().debug( "ControlledTopologyTreeRouting: Boot for %i\n", radio().id() ); 00277 #endif 00278 if ( state_ == TrGateway ) 00279 { 00280 parent_ = radio().id(); 00281 hops_ = 0; 00282 #ifdef DEBUG 00283 debug().debug( "ControlledTopologyTreeRouting: Start as sink/gateway\n" ); 00284 #endif 00285 } 00286 else 00287 { 00288 parent_ = Radio::NULL_NODE_ID; 00289 hops_ = 0xff; 00290 #ifdef DEBUG 00291 debug().debug( "ControlledTopologyTreeRouting: Start as ordinary node\n" ); 00292 #endif 00293 } 00294 00295 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00296 work_period_, this, 0 ); 00297 } 00298 // ----------------------------------------------------------------------- 00299 template<typename OsModel_P, 00300 typename Timer_P, 00301 typename Radio_P, 00302 typename Debug_P, 00303 typename OsModel_P::size_t MAX_NEIGHBORS> 00304 void 00305 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00306 disable( void ) 00307 { 00308 enabled=false; 00309 #ifdef DEBUG 00310 debug().debug( "ControlledTopologyTreeRouting: Should stop routing now...\n" ); 00311 #endif 00312 } 00313 // ----------------------------------------------------------------------- 00314 template<typename OsModel_P, 00315 typename Timer_P, 00316 typename Radio_P, 00317 typename Debug_P, 00318 typename OsModel_P::size_t MAX_NEIGHBORS> 00319 void 00320 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00321 set_sink( bool sink ) 00322 { 00323 if ( sink ) 00324 state_ = TrGateway; 00325 else 00326 state_ = TrUnconnected; 00327 } 00328 // ----------------------------------------------------------------------- 00329 template<typename OsModel_P, 00330 typename Timer_P, 00331 typename Radio_P, 00332 typename Debug_P, 00333 typename OsModel_P::size_t MAX_NEIGHBORS> 00334 void 00335 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00336 send( node_id_t receiver, size_t len, block_data_t *data ) 00337 { 00338 if(!enabled) 00339 return; 00340 if ( parent_ != Radio::NULL_NODE_ID ) 00341 { 00342 #ifdef DEBUG 00343 debug().debug( "ControlledTopologyTreeRouting: 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 #ifdef DEBUG 00350 else 00351 debug().debug( "ControlledTopologyTreeRouting: Not Connected. Cannot send.\n" ); 00352 #endif 00353 } 00354 // ----------------------------------------------------------------------- 00355 template<typename OsModel_P, 00356 typename Timer_P, 00357 typename Radio_P, 00358 typename Debug_P, 00359 typename OsModel_P::size_t MAX_NEIGHBORS> 00360 void 00361 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00362 timer_elapsed( void* userdata ) 00363 { 00364 if(!enabled) 00365 return; 00366 #ifdef DEBUG 00367 debug().debug( "ControlledTopologyTreeRouting: Execute Task 'ControlledTopologyTreeRouting' at %i\n", radio().id() ); 00368 #endif 00369 00370 switch ( state_ ) 00371 { 00372 case TrGateway: 00373 case TrConnected: 00374 { 00375 BroadcastMessage message( TrMsgIdBroadcast, hops_, parent_ ); 00376 radio().send( Radio::BROADCAST_ADDRESS, message.buffer_size(), (uint8_t*)&message ); 00377 break; 00378 } 00379 case TrUnconnected: 00380 #ifdef DEBUG 00381 debug().debug( "ControlledTopologyTreeRouting: Not connected. Waiting for FloodingMessage\n" ); 00382 #endif 00383 break; 00384 #ifdef DEBUG 00385 default: 00386 debug().debug( "ControlledTopologyTreeRouting: Warning! Should not be reached!\n" ); 00387 #endif 00388 } 00389 00390 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00391 work_period_, this, 0 ); 00392 } 00393 // ----------------------------------------------------------------------- 00394 template<typename OsModel_P, 00395 typename Timer_P, 00396 typename Radio_P, 00397 typename Debug_P, 00398 typename OsModel_P::size_t MAX_NEIGHBORS> 00399 void 00400 ControlledTopologyTreeRouting<OsModel_P, Timer_P, Radio_P, Debug_P, MAX_NEIGHBORS>:: 00401 receive( node_id_t from, size_t len, block_data_t *data ) 00402 { 00403 if(!enabled) 00404 return; 00405 #ifdef DEBUG 00406 //debug().debug( "ControlledTopologyTreeRouting: Received t %i l %i f %i\n", (block_data_t)*data, len, from ); 00407 #endif 00408 00409 if ( from == radio().id() ) 00410 return; 00411 00412 message_id_t msg_id = *data; 00413 00414 if ( msg_id == TrMsgIdBroadcast ) 00415 { 00416 if(topology_&&find(topology_->begin(),topology_->end(),from)==topology_->end()) 00417 return; 00418 BroadcastMessage *message = reinterpret_cast<BroadcastMessage*>(data); 00419 if ( message->hops() + 1 < hops_ ) 00420 { 00421 hops_ = message->hops() + 1; 00422 parent_ = from; 00423 state_ = TrConnected; 00424 #ifdef DEBUG 00425 debug().debug( "ControlledTopologyTreeRouting: -> Updated hop count to %i (at %i with p %i)\n", 00426 hops_, radio().id(), parent_ ); 00427 #endif 00428 } 00429 } 00430 else if ( msg_id == TrMsgIdRouting ) 00431 { 00432 if ( state_ == TrGateway ) 00433 { 00434 RoutingMessage *message = reinterpret_cast<RoutingMessage*>(data); 00435 notify_receivers( message->source(), message->payload_size(), message->payload() ); 00436 #ifdef DEBUG 00437 debug().debug( "ControlledTopologyTreeRouting: Routing message at Gate from %i\n", message->source() ); 00438 #endif 00439 } 00440 else if ( parent_ != Radio::NULL_NODE_ID ) 00441 { 00442 radio().send( parent_, len, data ); 00443 #ifdef DEBUG 00444 debug().debug( "ControlledTopologyTreeRouting: Forward routing message at %i to %i\n", radio().id(), parent_ ); 00445 #endif 00446 } 00447 } 00448 } 00449 00450 } 00451 #endif