Wiselib
wiselib.testing/algorithms/metrics/one_hop_link/one_hop_link_metrics.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines