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 __UTIL_WISEBED_NODE_API_VIRTUAL_RADIO_MODEL_H 00020 #define __UTIL_WISEBED_NODE_API_VIRTUAL_RADIO_MODEL_H 00021 00022 #include "util/wisebed_node_api/response_types.h" 00023 #include "util/wisebed_node_api/command_types.h" 00024 #include "util/wisebed_node_api/virtual_link_in_message.h" 00025 #include "util/wisebed_node_api/virtual_link_out_message.h" 00026 #include "util/delegates/delegate.hpp" 00027 #include "util/serialization/simple_types.h" 00028 #include "util/pstl/vector_static.h" 00029 #include "util/pstl/pair.h" 00030 #include <stdint.h> 00031 00032 namespace wiselib 00033 { 00034 00040 template<typename OsModel_P, 00041 typename Radio_P, 00042 typename Uart_P, 00043 typename Debug_P = typename OsModel_P::Debug, 00044 int MAX_VIRTUAL_LINKS = 10> 00045 class VirtualRadioModel 00046 { 00047 public: 00048 typedef OsModel_P OsModel; 00049 typedef typename OsModel::Os Os; 00050 typedef Radio_P Radio; 00051 typedef Uart_P Uart; 00052 typedef Debug_P Debug; 00053 typedef VirtualRadioModel<OsModel, Radio, Uart, Debug, MAX_VIRTUAL_LINKS> self_type; 00054 typedef self_type* self_pointer_t; 00055 00056 typedef VirtualLinkInMessage<OsModel, Radio> InMessage; 00057 typedef VirtualLinkOutMessage<OsModel, Radio> OutMessage; 00058 00059 typedef typename Radio::node_id_t node_id_t; 00060 typedef typename Radio::size_t size_t; 00061 typedef typename Radio::block_data_t block_data_t; 00062 typedef typename Radio::message_id_t message_id_t; 00063 00064 typedef typename Radio::radio_delegate_t radio_delegate_t; 00065 // typedef typename Radio::extended_radio_delegate_t extended_radio_delegate_iss_t; 00066 00067 typedef vector_static<OsModel, radio_delegate_t, 10> Receivers; 00068 typedef typename Receivers::iterator ReceiversIterator; 00069 00070 typedef vector_static<OsModel, node_id_t, 10> DestinationVector; 00071 typedef typename DestinationVector::iterator DestinationVectorIterator; 00072 00073 typedef vector_static<OsModel, node_id_t, 10> DeadLinksVector; 00074 typedef typename DeadLinksVector::iterator DeadLinksVectorIterator; 00075 // -------------------------------------------------------------------- 00076 Receivers receivers_; 00077 DestinationVector destinations_; 00078 DeadLinksVector deadlinks_; 00079 00080 bool nodeactive_; 00081 node_id_t virtual_node_id_; 00082 // -------------------------------------------------------------------- 00083 enum SpecialNodeIds 00084 { 00085 BROADCAST_ADDRESS = Radio::BROADCAST_ADDRESS, 00086 NULL_NODE_ID = Radio::NULL_NODE_ID 00087 }; 00088 // -------------------------------------------------------------------- 00089 enum Restrictions 00090 { 00091 MAX_MESSAGE_LENGTH = Radio::MAX_MESSAGE_LENGTH 00092 }; 00093 // -------------------------------------------------------------------- 00094 void init( Radio& radio, Uart& uart, Debug& debug ) 00095 { 00096 radio_ = &radio; 00097 uart_ = &uart; 00098 debug_ = &debug; 00099 } 00100 // -------------------------------------------------------------------- 00101 void destruct() 00102 {} 00103 // -------------------------------------------------------------------- 00104 void send( node_id_t to, size_t len, block_data_t *buf ) 00105 { 00106 // send virtual link message over uart 00107 if ((nodeactive_ == true) && (!destinations_.empty() )) 00108 { 00109 OutMessage message; 00110 message.set_command_type( NODE_OUTPUT_VIRTUAL_LINK ); 00111 message.set_destination( to ); 00112 message.set_source( id() ); 00113 message.set_rssi( 0 ); 00114 message.set_lqi( 0 ); 00115 message.set_payload( len, buf ); 00116 uart().write( message.buffer_size(), (uint8_t*)(&message) ); 00117 #ifdef VIRTUAL_RADIO_DEBUG 00118 debug().debug( "SENT to uart!" ); 00119 #endif 00120 } 00121 else 00122 { 00123 #ifdef VIRTUAL_RADIO_DEBUG 00124 debug().debug( "NOT sent to uart, dests empty!" ); 00125 #endif 00126 } 00127 00128 // send message over physical radio 00129 if ((nodeactive_ == true) && (node_in_deadlink_vector(to) == false)) 00130 { 00131 radio().send( to, len, buf ); 00132 #ifdef VIRTUAL_RADIO_DEBUG 00133 debug().debug("Send to %d (len %d)", to, len); 00134 #endif 00135 } 00136 else 00137 { 00138 #ifdef VIRTUAL_RADIO_DEBUG 00139 debug().debug( "NOT sent to radio, node in deadlink vector!" ); 00140 #endif 00141 } 00142 }; 00143 // -------------------------------------------------------------------- 00144 void 00145 receive_message( node_id_t id, size_t len, block_data_t *buf ) 00146 { 00147 #ifdef VIRTUAL_RADIO_DEBUG 00148 debug().debug("Received from %d (len %d)", id, len); 00149 #endif 00150 for ( ReceiversIterator 00151 it = receivers_.begin(); 00152 it != receivers_.end(); 00153 ++it ) 00154 (*it)( id, len, buf ); 00155 } 00156 // -------------------------------------------------------------------- 00157 void set_virtual_link( block_data_t* data) 00158 { 00159 uint8_t request_id = read<OsModel, block_data_t, uint8_t>( data ); 00160 node_id_t dest = read<OsModel, block_data_t, uint64_t>( data +1); 00161 destinations_.push_back( dest ); 00162 00163 send_response_message(SET_VIRTUAL_LINK, request_id, COMMAND_SUCCESS, 0, NULL); 00164 } 00165 // -------------------------------------------------------------------- 00166 void destroy_virtual_link( block_data_t* data) 00167 { 00168 uint8_t request_id = read<OsModel, block_data_t, uint8_t>( data ); 00169 node_id_t dest = read<OsModel, block_data_t, uint64_t>( data +1); 00170 00171 for ( DestinationVectorIterator it = destinations_.begin(); it != destinations_.begin(); ++it ) 00172 { 00173 if ( *it == dest ) 00174 destinations_.erase( it ); 00175 } 00176 00177 send_response_message(DESTROY_VIRTUAL_LINK, request_id, COMMAND_SUCCESS, 0, NULL); 00178 } 00179 // -------------------------------------------------------------------- 00180 void enable_physical_link( block_data_t* data) 00181 { 00182 uint8_t request_id = read<OsModel, block_data_t, uint8_t>( data ); 00183 node_id_t dest = read<OsModel, block_data_t, uint64_t>( data +1); 00184 00185 for ( DeadLinksVectorIterator it = deadlinks_.begin(); it != deadlinks_.begin(); ++it ) 00186 { 00187 if ( *it == dest ) 00188 deadlinks_.erase( it ); 00189 } 00190 00191 send_response_message(ENABLE_PHYSICAL_LINK, request_id, COMMAND_SUCCESS, 0, NULL); 00192 } 00193 // -------------------------------------------------------------------- 00194 void disable_physical_link( block_data_t* data) 00195 { 00196 uint8_t request_id = read<OsModel, block_data_t, uint8_t>( data ); 00197 node_id_t dest = read<OsModel, block_data_t, uint64_t>( data +1); 00198 00199 deadlinks_.push_back( dest ); 00200 00201 send_response_message(DISABLE_PHYSICAL_LINK, request_id, COMMAND_SUCCESS, 0, NULL); 00202 } 00203 // -------------------------------------------------------------------- 00204 bool node_in_deadlink_vector( node_id_t dest ) 00205 { 00206 for ( DeadLinksVectorIterator it = deadlinks_.begin(); it != deadlinks_.begin(); ++it ) 00207 { 00208 if ( *it == dest ) 00209 return true; 00210 } 00211 00212 return false; 00213 } 00214 // -------------------------------------------------------------------- 00215 void enable_node( block_data_t* data) 00216 { 00217 uint8_t request_id = read<OsModel, block_data_t, uint8_t>( data ); 00218 00219 nodeactive_ = true; 00220 00221 send_response_message(ENABLE_NODE, request_id, COMMAND_SUCCESS, 0, NULL); 00222 } 00223 // -------------------------------------------------------------------- 00224 void disable_node( block_data_t* data) 00225 { 00226 uint8_t request_id = read<OsModel, block_data_t, uint8_t>( data ); 00227 00228 nodeactive_ = false; 00229 00230 send_response_message(DISABLE_NODE, request_id, COMMAND_SUCCESS, 0, NULL); 00231 } 00232 // -------------------------------------------------------------------- 00233 void rcv_uart_packet( size_t len, block_data_t* data ) 00234 { 00235 switch (*data) 00236 { 00237 case VIRTUAL_LINK_MESSAGE: 00238 { 00239 InMessage *msg = (InMessage*)data; 00240 // debug().debug( "RECEIVED VIRTUAL LINK from %d to %d with size %d", 00241 // (uint32_t)msg->source(), (uint32_t)msg->destination(), msg->payload_length() ); 00242 00243 if ( msg->destination() == radio().id() || 00244 msg->destination() == Radio::BROADCAST_ADDRESS ) 00245 receive_message( msg->source(), msg->payload_length(), msg->payload() ); 00246 00247 send_response_message(VIRTUAL_LINK_MESSAGE, msg->request_id(), COMMAND_SUCCESS, 0, NULL); 00248 00249 break; 00250 } 00251 case ENABLE_NODE: 00252 enable_node( data + sizeof(block_data_t)); 00253 break; 00254 case DISABLE_NODE: 00255 disable_node( data + sizeof(block_data_t)); 00256 break; 00257 case SET_VIRTUAL_LINK: 00258 set_virtual_link( data + sizeof(block_data_t)); 00259 break; 00260 case DESTROY_VIRTUAL_LINK: 00261 destroy_virtual_link( data + sizeof(block_data_t)); 00262 break; 00263 case ENABLE_PHYSICAL_LINK: 00264 enable_physical_link( data + sizeof(block_data_t)); 00265 break; 00266 case DISABLE_PHYSICAL_LINK: 00267 disable_physical_link( data + sizeof(block_data_t)); 00268 break; 00269 default: 00270 uint8_t command_type = read<OsModel, block_data_t, uint8_t>( data ); 00271 uint8_t request_id = read<OsModel, block_data_t, uint8_t>( data +1); 00272 send_response_message(command_type, request_id, UNKNOWN_PARAMETER, 0, NULL); 00273 break; 00274 } 00275 } 00276 // -------------------------------------------------------------------- 00277 void send_response_message( uint8_t command_type, uint8_t request_id, 00278 uint8_t result, uint8_t len, block_data_t* payload) 00279 { 00280 uint8_t buf_len = 3+len; 00281 uint8_t uart_buf[buf_len]; 00282 00283 uart_buf[0] = command_type; 00284 uart_buf[1] = request_id; 00285 uart_buf[2] = result; 00286 00287 memcpy( uart_buf + 3, payload, len); 00288 00289 uart().write( buf_len, (uint8_t*)(&uart_buf) ); 00290 } 00291 // -------------------------------------------------------------------- 00292 void enable_radio() 00293 { 00294 nodeactive_ = true; 00295 virtual_node_id_ = radio().id(); 00296 00297 radio().enable_radio(); 00298 radio().template reg_recv_callback<self_type, &self_type::receive_message>(this); 00299 uart().enable_serial_comm(); 00300 uart().template reg_read_callback<self_type, &self_type::rcv_uart_packet>(this); 00301 } 00302 // -------------------------------------------------------------------- 00303 void disable_radio() 00304 { 00305 nodeactive_ = false; 00306 00307 uart().disable_serial_comm(); 00308 radio().disable_radio(); 00309 } 00310 // -------------------------------------------------------------------- 00311 node_id_t id() 00312 { 00313 return radio().id(); 00314 } 00315 // -------------------------------------------------------------------- 00316 template<class T, void (T::*TMethod)( node_id_t, size_t, block_data_t* )> 00317 int reg_recv_callback( T *obj_pnt ) 00318 { 00319 receivers_.push_back( radio_delegate_t::template from_method<T, TMethod>( obj_pnt ) ); 00320 // TODO: return real id! 00321 return 0; 00322 } 00323 // -------------------------------------------------------------------- 00324 void unreg_recv_callback( int idx ) 00325 {} 00326 00327 private: 00328 Radio& radio() 00329 { return *radio_; } 00330 00331 Uart& uart() 00332 { return *uart_; } 00333 00334 Debug& debug() 00335 { return *debug_; } 00336 00337 Radio* radio_; 00338 Uart* uart_; 00339 Debug* debug_; 00340 }; 00341 } 00342 00343 #endif