Skip to content

Generic wiselib application

Dimitrios Amaxilatis edited this page Jul 22, 2013 · 1 revision

The most flexible way of Wiselib application development is to write a Generic Wiselib Application, which can be useful if algorithms are tested on different hardware/software platforms, or when dealing with heterogeneous networks. The basic idea is that the Wiselib provides an own main() function that can be used for a starting point of own applications. This main() function can then be used to create an instance of an own class, which initializes the required Os facets and the used algorithms. Basically, the process consists of three steps: Writing a class that contains algorithms, creating an instance of that class, and executing it in the main() function. However, there are examples available that can be found in the applications folder, which is located parallel to wiselib.stable and wiselib.testing in the Wiselib SVN.

Compiling your Application

A generic Wiselib application can be compiled for different platforms (e.g., Shawn or Contiki) - whereby each target needs its own preparation. In the following, the setup for all supported platforms is described:

An overview over all available is given here:

Target Description
scw_msb ScatterWeb2 1.1 firmware on ScatterWeb MSB nodes.
contiki_msb Contiki 2.4 on ScatterWeb MSB nodes.
contiki_sky Contiki 2.4 on Tmote Sky and TelosB nodes.
contiki_micaz Contiki 2.4 on Micaz nodes.
shawn Shawn simulation environment.
isense iSense firmware on iSense nodes.
isense-pacemate iSense firmware on Pacemates.
tinyos-micaz TinyOs 2.1.1 on Micaz nodes.
tinyos-telosb TinyOs 2.1.1 on Micaz nodes.
tinyos-tossim TinyOs 2.1.1 with TOSSIM.
flash-jtag Download hex file via msp430-jtag to node. Tested with ScatterWeb MSB nodes.
flash-sky Download hex file via msp430-bsl-linux to Tmote Sky/TelosB nodes attached on /dev/ttyUSB0. If at another port, add parameter PORT=....
flash-micaz Download hex file via uisp to MicaZ nodes attached on /dev/ttyUSB0. If at another port, add parameter PORT=....
flash-tinyos-sky Download hex file (TinyOs hex file) via tos-bsl to Tmote Sky/TelosB nodes attached on /dev/ttyUSB0. If at another port, add parameter PORT=...
tinyos-nodeid-micaz Change node id in MicaZ TinyOs image - given via TOS_NODE_ID=.... Default is 1.
tinyos-nodeid-telosb Change node id in TelosB/TMote Sky TinyOs image - given via TOS_NODE_ID=.... Default is 1.
clean Delete all object/binary files.

Understanding the Code

First of all, an own class must be implemented that provides a method called init() expecting a parameter of type Os::AppMainParameter&. Os can be of type wiselib::OSMODEL, since OSMODEL is defined in each makefile in the applications directory. That way, the application adapts automatically to the currently used make target - and it can be compiled for any supported platform just by changing the make target. Currently the following macros are defined:

Platform Macro
Shawn SHAWN
iSense ISENSE
ScatterWeb __SCATTERWEB__
Contiki CONTIKI
OSA (Os Abstraction Layer) WISELIB_OSA
TinyOs TINYOS
TinyOs (for TOSSIM) TINYOS_TOSSIM
FeuerWare FEUERWARE

With the aid of the passed Os::AppMainParameter, it is possible to get instances of Os facets. This is done by the wiselib::FacetProvider, which returns an Os facet for the currently used platform. For example, on Contiki it returns a static instance (since there is no dynamic memory allocation available), whereas for Shawn a new instance is created that fits to the currently active processor (in Shawn, the main() function is called once per processor).

Then, a timer is registered that executes the start() method of our example after 5000ms (5s). When this method is finally called, it sends a debug message to the radio (broadcast address).

The example looks as follows:

#include "external_interface/external_interface.h"
#include "algorithms/routing/tree/tree_routing.h"

typedef wiselib::OSMODEL Os;

class ExampleApplication
{
   public:
      void init( Os::AppMainParameter& value )
      {
         radio_ = &wiselib::FacetProvider<Os, Os::Radio>::get_facet( value );
         timer_ = &wiselib::FacetProvider<Os, Os::Timer>::get_facet( value );
         debug_ = &wiselib::FacetProvider<Os, Os::Debug>::get_facet( value );

         debug_->debug( "Hello World from Example Application!\n" );

         radio_->reg_recv_callback<ExampleApplication,
                                   &ExampleApplication::receive_radio_message>( this );
         timer_->set_timer<ExampleApplication,
                           &ExampleApplication::start>( 5000, this, 0 );
      }  
      // --------------------------------------------------------------------
      void start( void* )
      {
         debug_->debug( "broadcast message at %d \n", radio_->id() );
         Os::Radio::block_data_t message[] = "hello world!\0";
  	   radio_->send( Os::Radio::BROADCAST_ADDRESS, sizeof(message), message );

         // following can be used for periodic messages
         // timer_->set_timer<ExampleApplication,
         //                  &ExampleApplication::start>( 5000, this, 0 );
      }  
      // --------------------------------------------------------------------
      void receive_radio_message( Os::Radio::node_id_t from, Os::Radio::size_t len,   Os::Radio::block_data_t *buf )
      {
           debug_->debug( "received msg at %u from %u\n", radio_->id(), from );
         debug_->debug( "  message is %s\n", buf );
      }
   private:
      Os::Radio::self_pointer_t radio_;
      Os::Timer::self_pointer_t timer_;
      Os::Debug::self_pointer_t debug_;
};  

Create a Wiselib Application

Next, an instance (as a global variable) of type WiselibApplication must be created, which in turn is a class template expecting the Os and the class of which an instance should be created as template parameters. As with the previously described FacetProvider, it automatically adapts the currently used platform (using Contiki, there is only one static instance available, whereas on Shawn there is one instance per processor). The example is pretty simple, and contains only one line of code:

wiselib::WiselibApplication<Os, ExampleApplication> example_app;

Initialize your class from the main() function

Finally, the main() function must be implemented, which is called application_main and expects a type Os::AppMainParameter& as parameter. The function can contain only one line of code: Calling the init() method of the WiselibApplication, which in turn calls the init() method of the just created class (here: ExampleApplication):

void application_main( Os::AppMainParameter& value )
{
   example_app.init( value );
}
Clone this wiki locally