How to write a module in OpenWSN firmware

OpenWSN firmware C code is written in module manner. It's similar with object-oriented programming, though C is not an object language. This structure keeps the code clear and expandable. This is usually used when you want to add a new feature to the code. To write in such way, first thing is to think about what variable that the feature should be maintained, what services that the feature can serve and what's the relationship with other modules in the code (e.g. the each layer protocol has a module corresponded). 

In this page, you will learn how to implement the feature into OpenWSN firmware and how to integrate it into python simulation. To make things easier, we will use neighbors as an example. neighbors  is a module that manages mote's neighbor information. The source code is located at openwsn-fw/openstack/02b-MAChigh/.

Write Source Code

There are two mainly part to implement a new feature. 1. the variable that this feature required to maintain. 2. the interface that this feature serves.The first thing to do is add two files into your project. For example,  neighbors.c and neighbors.h. 

create module variable

The new module variable type needs to be defined in neighbors.h file. When define a new module variable type, the type name has to be ended with suffix of vars_t. For example, neighbors_vars_t is the name of neighbors module type, like this:

typedef struct {
   neighborRow_t        neighbors[MAXNUMNEIGHBORS];
   dagrank_t            myDAGrank;
   uint8_t              debugRow;
   icmpv6rpl_dio_ht*    dio; //keep it global to be able to debug correctly.
} neighbors_vars_t;

Then you need to define a global variable in neighbors.c file, like this:

neighbors_vars_t neighbors_vars;

add module functions

The module functions are the interface that the feature what's other modules to call. The initial function is usually required to set the default value of module variables. For example: neighbors_init is the initial functions name of adaptive_sync module. The name of the functions need to begin with the module name with an underline following. For example the initial function is started with  neighbors_.

Define the functions that other modules may call them in header file (.h file). If the function is used by the module itself, declare it in source file (.c file). All the functions are implemented in source file.

Integrate into simulation system

To make the simulation compilation works, there are 4 files that required to modify: openwsnmodule_obj.hopenwsnmodule.cSConscript and SConscript.env

Modify openwsnmodule_obj.h file

add following code  in openwsnmodule_obj.h.

#include "neighbors_obj.h"

add following code in openwsnmodule_obj.h file.

neighbors_vars_t neighbors_vars;

Modify openwsnmodule.c file

add following code in openwsnmodule.c file

PyObject* neighbors_vars;

add following code in openwsnmodule.c file

// neighbors_vars
neighbors_vars = PyDict_New();

// TODO
PyDict_SetItemString(returnVal, "neighbors_vars", neighbors_vars);

Modify SConscript file

add following code in SConscript file

os.path.join('02b-MAChigh','neighbors.c'),

add following code in SConscript file

os.path.join('02b-MAChigh','neighbors.h'),

Modify SConscript.env file

add following code in SConscript.env file

'neighbors_vars',

add all functions implemented in your source file in SConscript.env  file

    # neighbors
    'neighbors_init',
    'neighbors_getMyDAGrank',
    'neighbors_getNumNeighbors',
    'neighbors_getPreferredParentEui64',
    'neighbors_getKANeighbor',
    'neighbors_isStableNeighbor',
    'neighbors_isPreferredParent',
    'neighbors_isNeighborWithLowerDAGrank',
    'neighbors_isNeighborWithHigherDAGrank',
    'neighbors_indicateRx',
    'neighbors_indicateTx',
    'neighbors_indicateRxDIO',
    'neighbors_getNeighbor',
    'neighbors_updateMyDAGrankAndNeighborPreference',
    'neighbors_removeOld',
    'debugPrint_neighbors',
    'registerNewNeighbor',
    'isNeighbor',
    'removeNeighbor',
    'isThisRowMatching',
    'neighbors_setMyDAGrank',

Add header file in SConscript.env

'neighbors',

Test

If everything works, you can use following command to test whether it works:

scons board=python toolchain=gcc oos_openwsn -c
scons board=python toolchain=gcc oos_openwsn

If you saw the following information, congratulations! it works. 

Archiving          build\python_gcc\bsp\boards\libbsp.a
Indexing           build\python_gcc\bsp\boards\libbsp.a
gcc -shared -o build\python_gcc\projects\common\oos_openwsn.pyd build\python_gcc\projects\common\03o
os_openwsn\03oos_openwsn_obj.o build\python_gcc\projects\common\03oos_openwsn\openwsnmodule_obj.o -L
C:\Python27\libs -Lbuild\python_gcc\bsp\boards -Lbuild\python_gcc\kernel\openos -Lbuild\python_gcc\d
rivers -Lbuild\python_gcc\openstack -Lbuild\python_gcc\openapps -lopenstack -lopenapps -lkernel -ldr
ivers -lbsp -lpython27 -Wl,--out-implib,build\python_gcc\projects\common\liboos_openwsn.a
scons: done building targets.

If you see something else, you need check whether you have done everything mentioned above. If you meet any problem with this tutorial, don't hesitate to contact Tengfei Chang!