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_METRICS_ONE_HOP_LINK_METRICS_H__ 00020 #define __ALGORITHMS_METRICS_ONE_HOP_LINK_METRICS_H__ 00021 00022 #include "algorithms/metrics/one_hop_link/one_hop_link_metrics_request.h" 00023 #include "algorithms/metrics/one_hop_link/one_hop_link_metrics_reply.h" 00024 00025 #define DEBUG_ONE_HOP_LINK_METRICS 00026 00027 namespace wiselib 00028 { 00029 00030 template<typename node_id_t> 00031 struct OneHopLinkMetricsDataItem 00032 { 00033 node_id_t id; 00034 uint16_t packets_received; 00035 }; 00036 00037 00043 template<typename OsModel_P, 00044 typename Radio_P, 00045 typename Timer_P, 00046 typename Clock_P, 00047 typename MetricsDataContainer_P, 00048 typename Debug_P> 00049 class OneHopLinkMetrics 00050 { 00051 public: 00052 typedef OsModel_P OsModel; 00053 typedef Radio_P Radio; 00054 typedef Timer_P Timer; 00055 typedef Clock_P Clock; 00056 typedef MetricsDataContainer_P MetricsDataContainer; 00057 typedef Debug_P Debug; 00058 00059 typedef typename MetricsDataContainer::iterator MetricsDataContainerIterator; 00060 00061 typedef OneHopLinkMetricsDataItem<typename Radio::node_id_t> MetricsDataItem; 00062 00063 typedef OneHopLinkMetrics<OsModel, Radio, Timer, Clock, MetricsDataContainer, Debug> self_type; 00064 typedef OneHopLinkMetricsRequestMessage<OsModel, Radio> RequestMessage; 00065 typedef OneHopLinkMetricsReplyMessage<OsModel, Radio> ReplyMessage; 00066 00067 typedef typename Radio::node_id_t node_id_t; 00068 typedef typename Radio::size_t size_t; 00069 typedef typename Radio::block_data_t block_data_t; 00070 00071 typedef typename Clock::time_t time_t; 00072 00073 typedef typename Timer::millis_t millis_t; 00074 // -------------------------------------------------------------------- 00075 enum ErrorCodes 00076 { 00077 SUCCESS = OsModel::SUCCESS, 00078 ERR_UNSPEC = OsModel::ERR_UNSPEC 00079 }; 00080 // -------------------------------------------------------------------- 00083 struct MetricsData { 00084 MetricsData(): start_time(time_t()), stop_time(time_t()), 00085 total_received(0) {}; 00086 00087 time_t start_time; 00088 time_t stop_time; 00089 00090 uint16_t total_received; 00091 00092 MetricsDataContainer link_metrics; 00093 }; 00095 00098 OneHopLinkMetrics(); 00099 ~OneHopLinkMetrics(); 00101 00104 int init( Radio_P& r, Timer_P& t, Clock_P& c, Debug_P& d); 00105 int init( void ); 00106 int destruct( void ); 00107 void start( millis_t ti, uint16_t pts, uint16_t ps ); 00109 00112 MetricsData& metrics_data( void ) 00113 { return metrics_data_; }; 00115 00118 void timer_elapsed( void *userdata ); 00120 00123 void receive( node_id_t from, size_t len, block_data_t *data ); 00125 00126 private: 00127 00128 Radio& radio() 00129 { return *radio_; } 00130 00131 Timer& timer() 00132 { return *timer_; } 00133 00134 Clock& clock() 00135 { return *clock_; } 00136 00137 Debug& debug() 00138 { return *debug_; } 00139 00142 enum OneHopLinkMetricsMsgIds { 00143 LinkMetricsRequest = 145, 00144 LinkMetricsReply = 146, 00145 }; 00146 00147 MetricsData metrics_data_; 00148 00149 node_id_t sink_; 00150 uint32_t transmit_interval_; 00151 int packets_to_send_; 00152 int packet_size_; 00153 int seq_num_; 00154 00155 bool running_; 00156 00157 typename Radio::self_pointer_t radio_; 00158 typename Timer::self_pointer_t timer_; 00159 typename Clock::self_pointer_t clock_; 00160 typename Debug::self_pointer_t debug_; 00161 }; 00162 // ----------------------------------------------------------------------- 00163 // ----------------------------------------------------------------------- 00164 // ----------------------------------------------------------------------- 00165 template<typename OsModel_P, 00166 typename Radio_P, 00167 typename Timer_P, 00168 typename Clock_P, 00169 typename MetricsDataContainer_P, 00170 typename Debug_P> 00171 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00172 OneHopLinkMetrics() 00173 : sink_ ( Radio::NULL_NODE_ID ), 00174 transmit_interval_ ( 100 ), 00175 packets_to_send_ ( 0 ), 00176 packet_size_ ( 0 ), 00177 seq_num_ ( 0 ), 00178 running_ ( false ), 00179 radio_(0), 00180 timer_(0), 00181 clock_(0), 00182 debug_(0) 00183 {}; 00184 // ----------------------------------------------------------------------- 00185 template<typename OsModel_P, 00186 typename Radio_P, 00187 typename Timer_P, 00188 typename Clock_P, 00189 typename MetricsDataContainer_P, 00190 typename Debug_P> 00191 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00192 ~OneHopLinkMetrics() 00193 { 00194 #ifdef DEBUG_ONE_HOP_LINK_METRICS 00195 debug().debug( "OneHopLinkMetrics Destroyed\n" ); 00196 #endif 00197 }; 00198 // ----------------------------------------------------------------------- 00199 template<typename OsModel_P, 00200 typename Radio_P, 00201 typename Timer_P, 00202 typename Clock_P, 00203 typename MetricsDataContainer_P, 00204 typename Debug_P> 00205 int 00206 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00207 init( Radio_P& r, Timer_P& t, Clock_P& c, Debug_P& d) 00208 { 00209 radio_ = &r; 00210 timer_ = &t; 00211 clock_ = &c; 00212 debug_ = &d; 00213 00214 #ifdef DEBUG_ONE_HOP_LINK_METRICS 00215 debug().debug( "OneHopLinkMetrics Boots for %i\n", radio().id() ); 00216 #endif 00217 radio().enable_radio(); 00218 radio().template reg_recv_callback<self_type, &self_type::receive>(this); 00219 00220 return SUCCESS; 00221 } 00222 // ----------------------------------------------------------------------- 00223 template<typename OsModel_P, 00224 typename Radio_P, 00225 typename Timer_P, 00226 typename Clock_P, 00227 typename MetricsDataContainer_P, 00228 typename Debug_P> 00229 int 00230 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00231 init( void ) 00232 { 00233 return ERR_UNSPEC; 00234 } 00235 // ----------------------------------------------------------------------- 00236 template<typename OsModel_P, 00237 typename Radio_P, 00238 typename Timer_P, 00239 typename Clock_P, 00240 typename MetricsDataContainer_P, 00241 typename Debug_P> 00242 int 00243 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00244 destruct( void ) 00245 { 00246 radio().disable_radio(); 00247 return SUCCESS; 00248 } 00249 // ----------------------------------------------------------------------- 00250 template<typename OsModel_P, 00251 typename Radio_P, 00252 typename Timer_P, 00253 typename Clock_P, 00254 typename MetricsDataContainer_P, 00255 typename Debug_P> 00256 void 00257 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00258 start( millis_t ti, uint16_t pts, uint16_t ps ) 00259 { 00260 #ifdef DEBUG_ONE_HOP_LINK_METRICS 00261 debug().debug( "Start OneHopLinkMetrics at %i\n", radio().id() ); 00262 #endif 00263 metrics_data_.start_time = clock().time(); 00264 metrics_data_.stop_time = clock().time(); 00265 metrics_data_.total_received = 0; 00266 metrics_data_.link_metrics.clear(); 00267 00268 RequestMessage req( LinkMetricsRequest, radio().id(), pts, ps, ti ); 00269 radio().send( Radio::BROADCAST_ADDRESS, req.buffer_size(), (uint8_t*)&req ); 00270 } 00271 // ----------------------------------------------------------------------- 00272 template<typename OsModel_P, 00273 typename Radio_P, 00274 typename Timer_P, 00275 typename Clock_P, 00276 typename MetricsDataContainer_P, 00277 typename Debug_P> 00278 void 00279 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00280 timer_elapsed( void *userdata ) 00281 { 00282 seq_num_++; 00283 ReplyMessage reply( LinkMetricsReply, packet_size_ ); 00284 radio().send( sink_, reply.buffer_size(), (uint8_t*)&reply ); 00285 00286 if( seq_num_ < packets_to_send_ ) 00287 { 00288 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00289 transmit_interval_, this, 0 ); 00290 } 00291 else 00292 { 00293 #ifdef DEBUG_ONE_HOP_LINK_METRICS 00294 debug().debug( "#fin at %i\n", radio().id() ); 00295 #endif 00296 running_ = false; 00297 } 00298 } 00299 // ----------------------------------------------------------------------- 00300 template<typename OsModel_P, 00301 typename Radio_P, 00302 typename Timer_P, 00303 typename Clock_P, 00304 typename MetricsDataContainer_P, 00305 typename Debug_P> 00306 void 00307 OneHopLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, MetricsDataContainer_P, Debug_P>:: 00308 receive( node_id_t from, size_t len, block_data_t *data ) 00309 { 00310 if ( from == radio().id() ) 00311 return; 00312 uint8_t msg_id = *data; 00313 if ( msg_id == LinkMetricsRequest && !running_ ) 00314 { 00315 RequestMessage *message = (RequestMessage *)data; 00316 sink_ = message->sink(); 00317 packets_to_send_ = message->pts(); 00318 packet_size_ = message->ps(); 00319 transmit_interval_ = message->ti(); 00320 00321 seq_num_ = 0; 00322 running_ = true; 00323 00324 #ifdef DEBUG_ONE_HOP_LINK_METRICS 00325 debug().debug( "Received request at %i\n", radio().id() ); 00326 debug().debug( " -> type: %i\n", (int)message->msg_id() ); 00327 debug().debug( " -> sink: %i\n", sink_ ); 00328 debug().debug( " -> pts : %i\n", packets_to_send_ ); 00329 debug().debug( " -> ps : %i\n", packet_size_ ); 00330 debug().debug( " -> ti : %i\n", transmit_interval_ ); 00331 #endif 00332 00333 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00334 transmit_interval_, this, 0 ); 00335 } 00336 else if ( msg_id == LinkMetricsReply ) 00337 { 00338 metrics_data_.stop_time = clock().time(); 00339 00340 bool found = false; 00341 for ( MetricsDataContainerIterator 00342 it = metrics_data_.link_metrics.begin(); 00343 it != metrics_data_.link_metrics.end(); 00344 ++it ) 00345 if ( (*it).id == from ) 00346 { 00347 (*it).packets_received++; 00348 found = true; 00349 break; 00350 } 00351 00352 if ( !found ) 00353 { 00354 MetricsDataItem item; 00355 item.id = from; 00356 item.packets_received = 1; 00357 metrics_data_.link_metrics.push_back( item ); 00358 } 00359 00360 metrics_data_.total_received++; 00361 } 00362 } 00363 00364 } 00365 #endif