00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "simlpy/interpreter_defs.h"
00032 #include "simlpy/interpreter_hooks.h"
00033
00034 #include "MobileNode.h"
00035 #include "BeaconConsumer.h"
00036 #include "MobileApp.h"
00037 #include "pydtn/BundleEvent.h"
00038 #include "simlpy/Clock.h"
00039 #include "simlpy/SimulationException.h"
00040
00041 #include <iostream>
00042 #include <stdlib.h>
00043
00044 using namespace Mobility;
00045
00046 const std::string MobileNode::kIdentifier( "node:mobile" );
00047
00048 MobileNode::MobileNode() :
00049 m_beaconTime( 0 )
00050 {
00051 m_beaconC = new BeaconConsumer( this );
00052 addConsumer( m_beaconC );
00053 }
00054
00055 MobileNode::~MobileNode()
00056 {
00057
00058 }
00059
00060 Entity*
00061 MobileNode::create() const
00062 {
00063 MobileNode* n = new MobileNode;
00064 n->trigger();
00065 return n;
00066 }
00067
00068 void
00069 MobileNode::configure( const ArgList& args )
00070 {
00071 unsigned int nargs = args.size();
00072 if ( nargs < 2 )
00073 {
00074 std::cerr << "config() takes at least 2 arguments ("
00075 << nargs << " given)"
00076 << std::endl;
00077 throw SimulationException( __FILE__ , __LINE__ );
00078 }
00079 std::string command = parse_string(args[0]);
00080 if ( "position" == command )
00081 {
00082 if ( nargs < 2 )
00083 {
00084 std::cerr << "config('position') requires at least two coordinates"
00085 << std::endl;
00086 throw SimulationException( __FILE__ , __LINE__ );
00087 }
00088 Position pos = parse_position( args[1] );
00089 setWaypoint( Presence( Clock::time(), pos, Time() ) );
00090 return;
00091 }
00092 if ( "beacon" == command )
00093 {
00094 if ( nargs < 2 )
00095 {
00096 std::cerr << "config('beacon') requires at least two coordinates"
00097 << std::endl;
00098 throw SimulationException( __FILE__ , __LINE__ );
00099 }
00100 if ( 0 == m_beaconC )
00101 {
00102 std::cerr << "No beacon manager was found at this node." << std::endl;
00103 throw SimulationException( __FILE__ , __LINE__ );
00104 }
00105 m_beaconTime = parse_double( args[1] );
00106 double t = 3 * m_beaconTime;
00107 long int ts = (long int) ::floor( t );
00108 long int tus = (long int) ( Time::MILLION * ( t - ::floor(t) ) );
00109 m_beaconC->setTimeout( Time(ts,tus) );
00110 return;
00111 }
00112 WrapNode::configure(args);
00113 }
00114
00115 void
00116 MobileNode::emit( const ArgList& args )
00117 {
00118 unsigned int nargs = args.size();
00119 if ( nargs < 3 )
00120 {
00121 std::cerr << "emit() takes at least 3 arguments ("
00122 << nargs << " given)"
00123 << std::endl;
00124 throw SimulationException( __FILE__ , __LINE__ );
00125 }
00126
00127 Time t = parse_time(args[0]);
00128
00129 std::string command = parse_string(args[1]);
00130
00131 if ( "waypoint" == command )
00132 {
00133 if ( nargs < 6 )
00134 {
00135 std::cerr << "emit(t,'waypoint') takes at least 6 arguments ("
00136 << nargs << " given)"
00137 << std::endl;
00138 throw SimulationException( __FILE__ , __LINE__ );
00139 }
00140 Time wpt = parse_time(args[2]);
00141 Time wpd = parse_time(args[3]);
00142 Position pos = parse_position( args[4] );
00143 Clock::schedule( new WaypointEvent(this,this,t,Presence(wpt,pos,wpd)) );
00144 return;
00145 }
00146
00147 WrapNode::emit(args);
00148 }
00149
00150 InterpreterItem
00151 MobileNode::get( const ArgList& args )
00152 {
00153 unsigned int nargs = args.size();
00154 if ( 0 == nargs )
00155 {
00156 std::cerr << "No attribute specified" << std::endl;
00157 throw SimulationException( __FILE__ , __LINE__ );
00158 }
00159
00160 std::string attr = parse_string(args[0]);
00161
00162 if ( "position" == attr )
00163 {
00164 Position p = position();
00165 ArgList alist;
00166 alist.push_back( construct_double( p.x() ) );
00167 alist.push_back( construct_double( p.y() ) );
00168 alist.push_back( construct_double( p.z() ) );
00169 return construct_list( alist );
00170 }
00171 if ( "beacon_interval" == attr )
00172 {
00173 return construct_double( m_beaconTime );
00174 }
00175 if ( "last_beacon" == attr )
00176 {
00177 ArgList alist;
00178 alist.push_back( construct_long( m_lastBeacon.tv.tv_sec ) );
00179 alist.push_back( construct_long( m_lastBeacon.tv.tv_usec ) );
00180 return construct_list( alist );
00181 }
00182 if ( "visible" == attr )
00183 {
00184 if ( 0 == m_beaconC )
00185 {
00186 std::cerr << "mobile node has no beacon consumer attached"
00187 << std::endl;
00188 throw SimulationException( __FILE__ , __LINE__ );
00189 }
00190 return m_beaconC->visible_list();
00191 }
00192
00193 return WrapNode::get(args);
00194 }
00195
00196 void
00197 MobileNode::addMobileApp( MobileApp* app )
00198 {
00199 if ( 0 == app ) return;
00200 addApplication(app);
00201 m_mobileApps.push_back(app);
00202 }
00203
00204 bool
00205 MobileNode::handler( WaypointEvent& event )
00206 {
00207 setWaypoint( event.waypoint() );
00208 return true;
00209 }
00210
00211 bool
00212 MobileNode::handler( HelloTrigger& event )
00213 {
00214 if ( 0 == m_beaconC ) return false;
00215 Time t = Clock::time();
00216
00217
00218 bool needBeacon = m_beaconC->lastSend() <= m_lastBeacon;
00219 m_lastBeacon = m_beaconC->lastSend();
00220 if ( needBeacon )
00221 {
00222 DTN::Bundle::BundleType type =
00223 DTN::Bundle::kBcast | DTN::Bundle::kNoACK;
00224 Time e = t + bundleLifetime();
00225 DTN::Bundle* b =
00226 new DTN::Bundle( node().nextSeq(),
00227 addr(),
00228 addr(),
00229 DTN::ByteString(),
00230 t.tv,
00231 e.tv,
00232 type );
00233 if ( 0 != b )
00234 {
00235
00236 Clock::tentative( new BundleEvent(this,this,t,t,b,false) );
00237 m_lastBeacon = t;
00238 }
00239 }
00240
00241
00242 double d = m_beaconTime/2 + m_beaconTime*prng();
00243 long int ds = (long int) ::floor(d);
00244 long int dus = (long int) ( Time::MILLION * ( d - ::floor(d) ) );
00245 Time tTrig = t + Time(ds,dus);
00246 Clock::tentative( new HelloTrigger(this,this,tTrig) );
00247
00248 m_beaconC->clean();
00249 return true;
00250 }
00251
00252 Position
00253 MobileNode::position() const
00254 {
00255 return position( Clock::time() );
00256 }
00257
00258 Position
00259 MobileNode::position( const Time& t ) const
00260 {
00261
00262 if ( 0 == m_waypoints.size() ) return Position();
00263
00264 Presence key( t, Position(), Time() );
00265 PresenceSet::const_iterator after = m_waypoints.lower_bound(key);
00266 PresenceSet::const_iterator before = after;
00267 --before;
00268
00269
00270 if ( m_waypoints.end() == after )
00271 {
00272 return before->position();
00273 }
00274
00275
00276 if ( *after == t )
00277 {
00278 return after->position();
00279 }
00280
00281 if ( ( t - before->time() ) < before->duration() )
00282 {
00283 return before->position();
00284 }
00285
00286
00287 if ( m_waypoints.begin() == after )
00288 {
00289 return Position();
00290 }
00291
00292
00293 Presence current = before->towards( *after, t );
00294
00295 return current.position();
00296 }
00297
00298 bool
00299 MobileNode::visible( const DTN::ByteString& addr )
00300 {
00301 if ( 0 == m_beaconC ) return false;
00302 return m_beaconC->visible(addr);
00303 }
00304
00305 void
00306 MobileNode::trigger()
00307 {
00308 Clock::tentative( new HelloTrigger(this,this,Clock::time()) );
00309 }
00310
00311 void
00312 MobileNode::notifyApps( const DTN::ByteString& addr )
00313 {
00314 MobileAppList::iterator itr = m_mobileApps.begin();
00315 MobileAppList::iterator end = m_mobileApps.end();
00316 for ( ; itr != end ; ++itr )
00317 {
00318 (*itr)->newNeighbor(addr);
00319 }
00320 }
00321
00322 void
00323 MobileNode::setWaypoint( const Presence& wp )
00324 {
00325 if ( wp.time() < Clock::time() )
00326 {
00327 std::cerr << "Cannot schedule a waypoint in the past"
00328 << std::endl;
00329 throw SimulationException( __FILE__ , __LINE__ );
00330 }
00331 m_waypoints.insert( wp );
00332 }
00333
00334 Position
00335 MobileNode::parse_position( const InterpreterItem p )
00336 {
00337 double x = 0;
00338 double y = 0;
00339 double z = 0;
00340 if ( ! PyList_Check( p ) )
00341 {
00342 throw SimulationException( __FILE__ , __LINE__ );
00343 }
00344 int n = PyList_Size( p );
00345
00346 if ( n < 2 )
00347 {
00348 throw SimulationException( __FILE__ , __LINE__ );
00349 }
00350 x = parse_double( PyList_GetItem(p,0) );
00351 y = parse_double( PyList_GetItem(p,1) );
00352 if ( n > 2 )
00353 {
00354 z = parse_double( PyList_GetItem(p,2) );
00355 }
00356 return Position( x, y, z );
00357 }