Wiselib
wiselib.testing/util/wisebed_node_api/virtual_radio.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 __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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines