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_INDIVIDUAL_LINK_METRICS_H__ 00020 #define __ALGORITHMS_METRICS_INDIVIDUAL_LINK_METRICS_H__ 00021 00022 #include "algorithms/metrics/individual_link/individual_link_metrics_message.h" 00023 00024 #define DEBUG_INDIVIDUAL_LINK_METRICS 00025 00026 namespace wiselib 00027 { 00028 00034 template<typename OsModel_P, 00035 typename Radio_P, 00036 typename Timer_P, 00037 typename Clock_P, 00038 typename Debug_P, 00039 typename DataItemContainer_P> 00040 class IndividualLinkMetrics 00041 { 00042 public: 00043 enum { 00044 MESSAGE_SIZE = 40 00045 }; 00046 00047 typedef OsModel_P OsModel; 00048 typedef Radio_P Radio; 00049 typedef Timer_P Timer; 00050 typedef Clock_P Clock; 00051 typedef Debug_P Debug; 00052 typedef DataItemContainer_P DataItemContainer; 00053 00054 typedef typename DataItemContainer::iterator DataItemContainerIterator; 00055 00056 typedef IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P> self_type; 00057 typedef IndividualLinkMetricsMessage<OsModel, Radio, MESSAGE_SIZE> LinkMessage; 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 00063 typedef typename Clock::time_t time_t; 00064 00065 typedef typename Timer::millis_t millis_t; 00066 // -------------------------------------------------------------------- 00067 enum ErrorCodes 00068 { 00069 SUCCESS = OsModel::SUCCESS, 00070 ERR_UNSPEC = OsModel::ERR_UNSPEC 00071 }; 00072 // -------------------------------------------------------------------- 00075 struct MetricsData 00076 { 00077 MetricsData(): total_sent(0), lost(0) {}; 00078 00079 uint16_t total_sent; 00080 uint16_t lost; 00081 00082 DataItemContainer link_times; 00083 }; 00085 00088 IndividualLinkMetrics(); 00089 ~IndividualLinkMetrics(); 00091 00094 int init( Radio_P& r, Timer_P& t, Clock_P& c, Debug_P& d); 00095 inline int init(); 00096 inline int destruct( void ); 00097 void start( node_id_t receiver, millis_t ti, uint16_t packets_to_send ); 00099 00102 MetricsData& metrics_data( void ) 00103 { return metrics_data_; }; 00105 00108 void timer_elapsed( void *userdata ); 00110 00113 void receive( node_id_t from, size_t len, block_data_t *data ); 00115 00116 private: 00117 00118 Radio& radio() 00119 { return *radio_; } 00120 00121 Timer& timer() 00122 { return *timer_; } 00123 00124 Clock& clock() 00125 { return *clock_; } 00126 00127 Debug& debug() 00128 { return *debug_; } 00129 00132 enum IndividualLinkMetricsMsgIds { 00133 LinkMetricsRequest = 143, 00134 LinkMetricsReply = 144 00135 }; 00136 00137 MetricsData metrics_data_; 00138 00139 node_id_t receiver_; 00140 millis_t transmit_interval_; 00141 uint16_t packets_to_send_; 00142 00143 typename Radio::self_pointer_t radio_; 00144 typename Timer::self_pointer_t timer_; 00145 typename Clock::self_pointer_t clock_; 00146 typename Debug::self_pointer_t debug_; 00147 00148 bool ack_; 00149 time_t sent_; 00150 }; 00151 // ----------------------------------------------------------------------- 00152 // ----------------------------------------------------------------------- 00153 // ----------------------------------------------------------------------- 00154 template<typename OsModel_P, 00155 typename Radio_P, 00156 typename Timer_P, 00157 typename Clock_P, 00158 typename Debug_P, 00159 typename DataItemContainer_P> 00160 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00161 IndividualLinkMetrics() 00162 : receiver_ ( Radio::NULL_NODE_ID ), 00163 transmit_interval_ ( 100 ), 00164 packets_to_send_ ( 0 ), 00165 radio_(0), 00166 timer_(0), 00167 clock_(0), 00168 debug_(0) 00169 {}; 00170 // ----------------------------------------------------------------------- 00171 template<typename OsModel_P, 00172 typename Radio_P, 00173 typename Timer_P, 00174 typename Clock_P, 00175 typename Debug_P, 00176 typename DataItemContainer_P> 00177 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00178 ~IndividualLinkMetrics() 00179 { 00180 #ifdef DEBUG_INDIVIDUAL_LINK_METRICS 00181 debug().debug( "IndividualLinkMetrics Destroyed\n" ); 00182 #endif 00183 }; 00184 // ----------------------------------------------------------------------- 00185 template<typename OsModel_P, 00186 typename Radio_P, 00187 typename Timer_P, 00188 typename Clock_P, 00189 typename Debug_P, 00190 typename DataItemContainer_P> 00191 int 00192 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00193 init( Radio_P& r, Timer_P& t, Clock_P& c, Debug_P& d) 00194 { 00195 radio_ = &r; 00196 timer_ = &t; 00197 clock_ = &c; 00198 debug_ = &d; 00199 00200 #ifdef DEBUG_INDIVIDUAL_LINK_METRICS 00201 debug().debug( "IndividualLinkMetrics Boots for %i\n", radio().id() ); 00202 #endif 00203 radio().enable_radio(); 00204 radio().template reg_recv_callback<self_type, &self_type::receive>(this); 00205 00206 return SUCCESS; 00207 } 00208 // ----------------------------------------------------------------------- 00209 template<typename OsModel_P, 00210 typename Radio_P, 00211 typename Timer_P, 00212 typename Clock_P, 00213 typename Debug_P, 00214 typename DataItemContainer_P> 00215 int 00216 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00217 init( void ) 00218 { 00219 return ERR_UNSPEC; 00220 } 00221 // ----------------------------------------------------------------------- 00222 template<typename OsModel_P, 00223 typename Radio_P, 00224 typename Timer_P, 00225 typename Clock_P, 00226 typename Debug_P, 00227 typename DataItemContainer_P> 00228 int 00229 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00230 destruct( void ) 00231 { 00232 radio().disable_radio(); 00233 return SUCCESS; 00234 } 00235 // ----------------------------------------------------------------------- 00236 template<typename OsModel_P, 00237 typename Radio_P, 00238 typename Timer_P, 00239 typename Clock_P, 00240 typename Debug_P, 00241 typename DataItemContainer_P> 00242 void 00243 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00244 start( node_id_t receiver, millis_t ti, uint16_t packets_to_send ) 00245 { 00246 #ifdef DEBUG_INDIVIDUAL_LINK_METRICS 00247 debug().debug( "Start IndividualLinkMetrics: %i -> %i \n", radio().id(), receiver ); 00248 #endif 00249 receiver_ = receiver; 00250 transmit_interval_ = ti; 00251 packets_to_send_ = packets_to_send; 00252 00253 metrics_data_.link_times = DataItemContainer(); 00254 metrics_data_.total_sent = 1; 00255 metrics_data_.lost = 0; 00256 metrics_data_.link_times.clear(); 00257 00258 ack_ = false; 00259 sent_ = clock().time(); 00260 LinkMessage req( LinkMetricsRequest ); 00261 radio().send( receiver_, req.buffer_size(), (uint8_t*)&req ); 00262 00263 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00264 transmit_interval_, this, 0 ); 00265 } 00266 // ----------------------------------------------------------------------- 00267 template<typename OsModel_P, 00268 typename Radio_P, 00269 typename Timer_P, 00270 typename Clock_P, 00271 typename Debug_P, 00272 typename DataItemContainer_P> 00273 void 00274 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00275 timer_elapsed( void *userdata ) 00276 { 00277 if ( !ack_ ) 00278 metrics_data_.lost++; 00279 00280 if ( metrics_data_.total_sent == packets_to_send_ ) 00281 { 00282 #ifdef DEBUG_INDIVIDUAL_LINK_METRICS 00283 debug().debug( "IndividualLinkMetrics done\n" ); 00284 #endif 00285 return; 00286 } 00287 00288 LinkMessage req( LinkMetricsRequest ); 00289 ack_ = false; 00290 sent_ = clock().time(); 00291 #ifdef DEBUG_INDIVIDUAL_LINK_METRICS 00292 debug().debug( "+\n" ); 00293 #endif 00294 radio().send( receiver_, req.buffer_size(), (uint8_t*)&req ); 00295 metrics_data_.total_sent++; 00296 00297 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00298 transmit_interval_, this, 0 ); 00299 } 00300 // ----------------------------------------------------------------------- 00301 template<typename OsModel_P, 00302 typename Radio_P, 00303 typename Timer_P, 00304 typename Clock_P, 00305 typename Debug_P, 00306 typename DataItemContainer_P> 00307 void 00308 IndividualLinkMetrics<OsModel_P, Radio_P, Timer_P, Clock_P, Debug_P, DataItemContainer_P>:: 00309 receive( node_id_t from, size_t len, block_data_t *data ) 00310 { 00311 uint8_t msg_id = *data; 00312 if ( msg_id == LinkMetricsRequest ) 00313 { 00314 LinkMessage reply( LinkMetricsReply ); 00315 radio().send( from, reply.buffer_size(), (uint8_t*)&reply ); 00316 } 00317 else if ( msg_id == LinkMetricsReply ) 00318 { 00319 ack_ = true; 00320 time_t now = clock().time(); 00321 time_t duration = now - sent_; 00322 metrics_data_.link_times.push_back( duration ); 00323 #ifdef DEBUG_INDIVIDUAL_LINK_METRICS 00324 debug().debug( "#\n" ); 00325 #endif 00326 #ifdef DEBUG_INDIVIDUAL_LINK_METRICS 00327 // debug().debug( "now is %i, sent is %i, dur is %i, size is %i\n", now, sent_, duration, metrics_data_.link_times.size() ); 00328 #endif 00329 } 00330 } 00331 00332 } 00333 #endif