© Agus Kurniawan 2018
Agus KurniawanPractical Contiki-NGhttps://doi.org/10.1007/978-1-4842-3408-2_4

4. Contiki-NG and Computer Communication

Agus Kurniawan1 
(1)
Depok, Jawa Barat, Indonesia
 

Dada communication capabilities available on WSN motes enable the exchange of data among WSN motes. In this chapter, we will learn how Contiki-NG aids communication among WSN motes and from a WSN mote to a computer. We will also explore how to build middleware that enables WSN motes to communicate with other systems.

The following is a list of topics we will cover in this chapter:
  • Communication models for Contiki-NG

  • Serial communication

  • Building communication among Contiki-NG motes

  • Building communication between computer and Contiki-NG motes

  • Developing middleware

Communication Models for Contiki-NG

How you want to communicate between WSN motes and computers will determine what kind of communication model you use. As you know, each WSN mote usually has network capability so it can exchange data with WSN motes and computers.

A communication model for Contiki-NG is depicted in Figure 4-1. Some WSN motes have the capability to connect to servers directly, but other motes may not, so those motes use a hub/gateway/middleware to communicate with servers.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig1_HTML.jpg
Figure 4-1

Communication models in Contiki-NG

In this chapter, we will learn how WSN motes communicate with others. We need at least two motes to implement our demo.

Serial Communication

Serial communication can be defined as a process used to send and receive a bit at a time sequentially. Sometimes serial communication is called UART (Universal Asynchronous Receiver/Transmitter). Technically, we already used serial communication when we uploaded Contiki-NG programs to WSN motes in previous chapters. We also communicate with WSN motes via the printf() function. Then, we listen to the messages from printf() using the command make login.

A serial communication protocol is represented in Figure 4-2. In hardware implementation, a serial communication needs at least three pinouts. These are Rx (Receiver), Tx (Transmitter), and GND (Ground) pins.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig2_HTML.jpg
Figure 4-2

Serial communication

Communication Between Contiki Mote and Computer

In this section, we will build Contiki and Contiki-NG programs to communicate between a Contiki mote and a computer. This is useful because we can control our Contiki motes from the computer. Running applications on a computer has benefits, such as interacting with the database server and communicating with the cloud server.

There are a lot of methods used to communicate between a computer and a Contiki mote. We will focus on two methods: serial communication and shell. We will explore these methods in the next section.

Let’s build!

Access Contiki Motes via Serial Communication

Since our WSN motes are attached to the computer through serial communication, we can initiate communication between the computer and a WSN mote. Some application platforms, such as C/C++, Java, Python, C#, and Node.js, provide libraries with which to implement serial communication.

In this section, we will try to access WSN motes using Python through serial communication. To implement serial communication in Python, we use the pyserial library. You can find this library at https://pypi.python.org/pypi/pyserial . This library can be installed using pip.

You can verify if your computer has installed pip or not. You can type this command in Terminal:

$ which pip

If you don’t get a response, it means your computer is missing the pip program. You can install pip using this command in Terminal:

$ sudo apt-get install python-pip

Now, you can install the pyserial library by typing this command in Terminal:

$ pip install pyserial

You also can install the pyserial library using easy_install. You can type this command in Terminal:

$ easy_install -U pyserial

Make sure your computer is connected to the Internet.

Next, you must write a Python program to listen for incoming messages on a specific serial port. You should know which serial port is used by the Contiki mote. You need it because you will use it on your program.

To find a serial port from the Contiki mote, you can open Terminal and type this command:

$ ls /dev/tty*

You should see a list of connected serial ports available on your computer. Depending on your Contiki mote model, you can verify the port by turning the mote on/off so you should which a new attached serial port. For instance, my Contiki mote is detected as /dev/ttyUSB0. You can see it in Figure 4-3.

Now, you will develop the Python program. You will print all incoming data from the serial port to the console. Set the baudrate to 115200 for the serial-port speed. Create a file, called contiki-viewer.py, and write these complete scripts. Change the PORT value to that for your Contiki-NG mote:

#!/usr/bin/python
import serial
PORT ='/dev/ttyUSB0'
ser = serial.Serial(
        port=PORT,
        baudrate=115200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
        timeout=0)
print("connected to: " + ser.portstr)
ser.write("help ")
while True:
        line = ser.readline()
        if line:
                print(line),
ser.close()
Save this program.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig3_HTML.jpg
Figure 4-3

Getting a list of serial ports in your computer

To simulate this demo, you should upload the Contiki-NG program to a Contiki-NG mote. You can use the same program from Chapter 1, Hello World. You should upload that program into the Contiki mote.

After Contiki-NG is deployed with a Contiki-NG program, you can run the Python program, contiki-viewer.py, by typing this command:

$ python contiki-viewer.py

If you have error issues related to security access, you probably should run it with administrator privileges. Type this command:

$ sudo python contiki-viewer.py
After it has executed, you will see that this program is waiting for incoming messages from the serial port, as shown in Figure 4-4.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig4_HTML.jpg
Figure 4-4

Executing Python program for listening to the serial port

If you do not see anything, you should reset your Contiki mote. Now the message from the Hello World program can be seen on the console. You can see my program depicted in Figure 4-5.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig5_HTML.jpg
Figure 4-5

Reading data from serial port of Contiki using Python

I have also tested with Contiki-NG on a TelosB mote. It works. You can see that program output in Figure 4-6.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig6_HTML.jpg
Figure 4-6

Reading data from serial port of Contiki-NG using Python

How does this work?

This program starts by initializing the serial library and activating the serial port of the Contiki-NG mote:

import serial
PORT ='/dev/ttyUSB0'
ser = serial.Serial(
        port=PORT,
        baudrate=115200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS,
        timeout=0)

After the serial port is activated, we listen for incoming message from that serial port. We call readline() to read data from the serial port. Once we receive data, we print the data to the console:

while True:
      line = ser.readline()
      if line:
              print(line),
ser.close()

Last, we close our serial port by calling the close() method.

Contiki Shell

Contiki OS provides a shell API that we can utilize to communicate with internal Contiki-NG motes. We find the shell API in the Contiki source code in <Contiki-root>/apps/shell. You should see several API objects, shown in Figure 4-7.

Contiki shell is very useful. Let’s say you build and deploy a Contiki application onto a Contiki mote. Then, you want to analyze what is happening inside the Contiki mote. To do this, you can build a custom Contiki shell related to your needs. You call the shell from the Contiki-NG mote and perform your analysis.

One important thing that you should know is the limitations on Contiki mote storage and resources. Building more Contiki shell APIs means using more mote resources. Make sure your Contiki shell is optimal for your Contiki mote model.

In this section, we will learn how to build a Contiki shell application and then deploy it to a Contiki mote. For this simple demo, we will use a Contiki sample from the Contiki source code. You can see it at <Contiki-root>examples/example-shell. This program runs for native platforms such as a computer.

Open the example-shell.c file. You should see the PROCESS_THREAD(example_shell_process, ev, data) function, as follows:

PROCESS_THREAD(example_shell_process, ev, data)
{
  PROCESS_BEGIN();
  serial_shell_init();
  shell_base64_init();
  shell_blink_init();
  /*shell_coffee_init();*/
  shell_download_init();
  /*shell_exec_init();*/
  shell_file_init();
  shell_httpd_init();
  shell_irc_init();
  /*shell_ping_init();*/ /* uIP ping */
  shell_power_init();
  /*shell_profile_init();*/
  shell_ps_init();
  /*shell_reboot_init();*/
  shell_rime_debug_init();
  shell_rime_netcmd_init();
  shell_rime_ping_init(); /* Rime ping */
  shell_rime_sendcmd_init();
  shell_rime_sniff_init();
  shell_rime_init();
  /*shell_rsh_init();*/
  shell_run_init();
  shell_sendtest_init();
  /*shell_sky_init();*/
  shell_tcpsend_init();
  shell_text_init();
  shell_time_init();
  shell_udpsend_init();
  shell_vars_init();
  shell_wget_init();
  PROCESS_END();
}
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig7_HTML.jpg
Figure 4-7

Contiki shell APIs in Contiki source code

Each shell API is defined as shell_xxx(). Remarked codes are not supported for native platforms such as a computer.

Now, you can compile and run this program. Open Terminal and navigate to the <Contiki-root>examples/example-shell folder. Then, type these commands:

$ make TARGET=native
$ ./example-shell.native
If it succeeds, you should see the Contiki shell that is shown in Figure 4-8.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig8_HTML.jpg
Figure 4-8

Executing example-shell application

For this demo, you call one of the Contiki shells. To get a list of Contiki shells, you can call the help shell command:

Contiki > help
Contiki > echo hello world!
You should get a list of supported shells in the console. Then, execute echo shell command. A sample of the program’s output can be seen in Figure 4-9.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig9_HTML.jpg
Figure 4-9

Running shell sample

You have run a Contiki shell on the computer as a native application. Now, you will build a Contiki shell for a Contiki mote. For demo purposes, I will use TelosB hardware that’s type is Sky.

You will use a sample program from the Contiki source code. You can find shell-sky at <Contiki-root>examples/shell-sky folder. If you open the sky-shell.c file, you should see the PROCESS_THREAD(sky_shell_process, ev, data) code as follows:

PROCESS_THREAD(sky_shell_process, ev, data)
{
  PROCESS_BEGIN();
#if WITH_PERIODIC_DEBUG
  ctimer_set(&debug_timer, 20 * CLOCK_SECOND, periodic_debug, NULL);
#endif /* WITH_PERIODIC_DEBUG */
  serial_shell_init();
  shell_blink_init();
  /*  shell_file_init();
      shell_coffee_init();*/
  /*  shell_download_init();*/
  shell_rime_sendcmd_init();
  /*  shell_ps_init();*/
  shell_reboot_init();
  shell_rime_init();
  shell_rime_netcmd_init();
  /*  shell_rime_ping_init();
  shell_rime_debug_init();
  shell_rime_debug_runicast_init();*/
  /*  shell_rime_sniff_init();*/
  shell_sky_init();
  shell_power_init();
  shell_powertrace_init();
  /*  shell_base64_init();*/
  shell_text_init();
  shell_time_init();
  /*  shell_sendtest_init();*/
  shell_collect_view_init();
#if DEBUG_SNIFFERS
  rime_sniffer_add(&s);
#endif /* DEBUG_SNIFFERS */
  PROCESS_END();
}

You only use some essential shells due to the Contiki mote’s resource limitation. Other shell APIs are remarked.

Now, compile and upload this program into your Contiki mote. For instance, I use the Contiki-NG mote–based Sky. Open Terminal and navigate to the <Contiki-root>examples/shell-sky folder. You can type these commands to compile and upload the program to the Contiki-NG mote with sky as target:

$ make TARGET=sky
$ make TARGET=sky savetarget
$ make shell-sky.upload

After it has completed, you can monitor your Contiki mote. You can type this command:

$ make login

Then, reset your Contiki mote in order to use the Contiki shell. If it succeeds, you should see the Contiki shell terminal as follows:

$ ./example-shell.native
Contiki-3.x-3330-g719f712 started
Rime started with address 2.1
MAC nullmac RDC nullrdc NETWORK Rime
2.1: Contiki>
You can see a sample of the Contiki shell in Figure 4-10.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig10_HTML.jpg
Figure 4-10

Running Contiki shell on Contiki-NG mote

From the Contiki shell, you can test it using the commands help and echo. You can type these commands:

Contiki> help
Contiki> echo hello world!

A sample of the program output from the Contiki shell can be seen in Figure 4-11.

If you want to exit from the Contiki shell, you can type exit. If you get problems quitting from the Contiki shell, you can press CTRL+C to enforce the exit.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig11_HTML.jpg
Figure 4-11

Running shell sample on Contiki mote

Contiki-NG Shell

Contiki-NG has modified Contiki shell. Contiki-NG shell is defined into a module. You should enable a shell module if you want to use it. The shell structure can be found in the <Contiki-NG-root>/os/services/shell folder. You can see it in Figure 4-12.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig12_HTML.jpg
Figure 4-12

Code structure of Contiki-NG shell

You can enable the shell module in the Makefile file from your projects. Put this script in to enable this module:

MODULES += os/services/shell

Then, you can compile and upload your project program into your Contiki mote. Since Contiki-NG needs more space on the Contiki mote, your mote probably does not fit the program, so you will get an error while compiling and flashing the program.

After you succeed in uploading program, you can test it by connecting to the Contiki mote via a serial tool. You should get “>” on the serial Terminal. Not all Contiki motes can run the Contiki-NG shell due to ROM space size. My TelosB board cannot work with this shell. So, I tested it with the TI CC2650 LaunchPad board. It works. I then run this command to access the Contiki-NG serial:

$ make login PORT=/dev/ttyACM0 BOARD=launchpad/cc2650 TARGET=srf06-cc26xx

If you do not see “>,” try to reset the board. Then, press Enter. The program output can be seen in Figure 4-13.

Now, you can test Contiki-NG with several commands. Try to execute these shell commands:

> help
> ip-addr
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig13_HTML.jpg
Figure 4-13

Running Contiki-NG shell on TI CC2650 LaunchPad board

These commands will list all registered Contiki-NG shells and display current IP address. You can see my program output in Figure 4-14.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig14_HTML.jpg
Figure 4-14

Sample of executing Contiki-NG shell

Customizing Contiki Shell

In some cases you may need to customize the Contiki shell to fit your problems. The thing that you should be aware of is your space and resource usage while implementing a Contiki shell.

In this section, we will learn how to customize a Contiki shell on both Contiki and Contiki-NG. In Contiki-NG, a Contiki shell is called an NG shell. Each customizing shell topic will be explored in the next sections.

Custom Contiki Shell

In the previous section, we learned how to access Contiki and Contiki shells. Now, we will build our own Contiki shell API. For this simple demo, we will develop a Contiki shell with an addition math operation. This API will receive two number parameters. These number parameters will be added and then sent back as the Contiki shell output.

To build our own Contiki shell, we can add our shell objects to the <Contiki-root>/apps/shell folder. For our scenario, we add two files, shell-math.c and shell-math.h. You can see them in Figure 4-15.

There are two steps to building a custom Contiki shell. First, we create an object file (*.c) in which to declare all Contiki shell implementations. We declare the Contiki shell API using SHELL_COMMAND(). Then, we implement the shell API on a process by declaring it in PROCESS().

Last, we register and initialize our Contiki shell API by calling the shell_register_command() function. This function will be called on the shell_math_init() function. The Contiki program that will use this shell should call shell_math_init() function to access the shell API.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig15_HTML.jpg
Figure 4-15

Adding an additional Contiki shell API

For implementation, we start to write the program in the shell-math.c file. We receive two number input parameters. Then, we perform the addition operation. The following is the complete program for the shell-math.c file:

#include "contiki.h"
#include "shell.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
/*-----------------------------------------------------------*/
PROCESS(shell_math_process, "math");
SHELL_COMMAND(math_command,
              "math",
              "math: math number1 number2",
              &shell_math_process);
/*-----------------------------------------------------------*/
PROCESS_THREAD(shell_math_process, ev, data)
{
  char *numbers;
  int n1 = 0;
  int n2 = 0;
  char buf[32];
  PROCESS_BEGIN();
  numbers = data;
  if(numbers == NULL || strlen(numbers) == 0) {
    shell_output_str(&math_command,
                  "math number1 number2: number must be given", "");
    PROCESS_EXIT();
  }
  char * pch;
  pch = strtok (numbers," ");
  if (pch != NULL)
  {
      n1 = atoi(pch);
      pch = strtok (NULL, " ");
      if (pch != NULL)
      {
          n2 = atoi(pch);
      }else
      {
        shell_output_str(&math_command,
          "math number1 number2: number must be given", "");
      PROCESS_EXIT();
      }
  }else
  {
    shell_output_str(&math_command,
      "math number1 number2: number must be given", "");
    PROCESS_EXIT();
  }
  int s = n1 + n2;
  sprintf(buf, "%d + %d= %d", n1, n2, s);
  shell_output_str(&math_command, buf, "");
  PROCESS_END();
}
/*-----------------------------------------------------------*/
void
shell_math_init(void)
{
  shell_register_command(&math_command);
}
/*-----------------------------------------------------------*/

Input data from the user can be obtained from the data variables in the function parameters. We parse the data into two number variables.

Next, we write a header file, called shell-math.h, for our Contiki shell API. We only declare our function, shell_math_init(). The following is the complete program for the shell-math.h file:

#ifndef __SHELL_MATH_H__
#define __SHELL_MATH_H__
#include "shell.h"
void shell_math_init(void);
#endif

Save all the files.

Now, we should configure Makefile to include these files in compilation. You can open Makefile.shell in the same folder with the shell API files. Open this file and add your shell files. You can see them in the codes here:

...
shell_src = shell.c shell-reboot.c shell-vars.c shell-ps.c
            shell-blink.c shell-text.c shell-time.c
            shell-file.c shell-run.c
            shell-coffee.c
            shell-power.c
            shell-base64.c
            shell-memdebug.c
            shell-math.c
            shell-powertrace.c shell-crc.c
shell_dsc = shell-dsc.c
...

Our Contiki shell API is now ready for compiling.

The next step is to develop a Contiki application to use our Contiki shell API, math shell. We create a folder, called shell-math-demo. Then, we create two files:
  • shell-math-demo.c

  • Makefile

The shell-math-demo.c file consists of a program to use the Contiki math shell API. The following is the complete program in the shell-math-demo.c file:

#include "contiki.h"
#include "shell.h"
#include "serial-shell.h"
#include "collect-view.h"
/*-----------------------------------------------------------*/
PROCESS(sky_shell_process, "Sky Contiki shell");
AUTOSTART_PROCESSES(&sky_shell_process);
/*-----------------------------------------------------------*/
#define WITH_PERIODIC_DEBUG 0
#if WITH_PERIODIC_DEBUG
static struct ctimer debug_timer;
static void
periodic_debug(void *ptr)
{
  ctimer_set(&debug_timer, 20 * CLOCK_SECOND, periodic_debug, NULL);
  collect_print_stats();
}
#endif /* WITH_PERIODIC_DEBUG */
/*-----------------------------------------------------------*/
PROCESS_THREAD(sky_shell_process, ev, data)
{
  PROCESS_BEGIN();
#if WITH_PERIODIC_DEBUG
  ctimer_set(&debug_timer, 20 * CLOCK_SECOND, periodic_debug, NULL);
#endif /* WITH_PERIODIC_DEBUG */
  serial_shell_init();
  shell_blink_init();
  shell_reboot_init();
  shell_sky_init();
  shell_power_init();
  shell_powertrace_init();
  shell_text_init();
  shell_time_init();
  shell_collect_view_init();
  shell_math_init();
  PROCESS_END();
}
/*-----------------------------------------------------------*/

Furthermore, we write scripts in the Makefile. We include Contiki and the project path. You write these complete scripts as follows:

CONTIKI_PROJECT = shell-math-demo
all: $(CONTIKI_PROJECT)
APPS = serial-shell powertrace collect-view
CONTIKI = ../..
CONTIKI_WITH_RIME = 1
include $(CONTIKI)/Makefile.include

CONTIKI_WITH_RIME = 1 is used to enable the RIME protocol since Contiki shell uses it on some shell commands. We also supply a testing configuration by including this Makefile, /home/user/nes/testbed-scripts/Makefile.include, because some shell commands need it.

Save all files.

Now, we compile our program, shell-math-demo. Open Terminal and navigate to the shell-math-demo folder. Type these commands:

$ make TARGET=sky
$ make shell-math-demo.sky.upload TARGET=sky

After our program is uploaded to Contiki mote, we can monitor the mote. You can type this command:

$ make login

If it succeeds, you should see the Contiki shell. Now, we can call our Contiki shell API. We can type this command in the Contiki shell:

Contiki> math 10 5
This shell will call our Contiki shell API. Value inputs 10 and 5 will be executed to perform the addition operation. You can see a sample of the program output in Figure 4-16.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig16_HTML.jpg
Figure 4-16

Running custom Contiki shell API

Custom Contiki-NG Shell

Contiki-NG applies shell with a different approach. To customize a shell, we can add our shell command to the shell-commands.c file. You can find that file in the <contiki-ng-root>/os/services/shell folder. You can see it in Figure 4-17.

We add a new shell command to the shell-commands.c file. We define a “hello” command. We print the message "Hi, this is a custom shell" to Terminal. Write this code:

static
PT_THREAD(cmd_hello(struct pt *pt, shell_output_func output, char *args))
{
  PT_BEGIN(pt);
  SHELL_OUTPUT(output, "Hi, this custom shell ")
  PT_END(pt);
}

Next, we also register our shell in the shell_command_t shell_commands struct. We define the shell name, method call, and description. For instance, you can see the code for our custom NG-shell here:

struct shell_command_t shell_commands[] = {
  { "hello",   cmd_hello,   "'> hello': say hello" },
  { "help",    cmd_help,    "'> help': Shows this help" },
  { "reboot",  cmd_reboot,  "'> reboot': Reboot the board by watchdog_reboot()" },
  ...
};
Save all files.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig17_HTML.jpg
Figure 4-17

NG shell in Contiki-NG source code

Now, you can use the NG shell on your project. For instance, we can use a hello-world project and enable the Contiki-NG shell. We only enable shell service on Makefile:

MODULES += os/services/shell

After that, we compile and flash this program onto the Contiki-NG mote. You can now remote into the Contiki mote Terminal using mote login. For instance, I remote access my TI LaunchPad CC2650 using this command:

$ make login TARGET=srf06-cc26xx PORT=/dev/ttyUSB0

You should change TARGET and PORT to reflect your Contiki board. Please press the Reset button on the Contiki mote if you do not see anything in Terminal. Now, you can test your own shell:

shell> help
shell> hello
After calling our NG shell, we can see the shell response. You can see my shell output in Figure 4-18.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig18_HTML.jpg
Figure 4-18

Running custom NG shell on TI LaunchPad CC260

Communication among Contiki Motes

In this section, we will build a communication among Contiki-NG motes. There are a lot of methods for communicating among Contiki-NG motes. To show how to communicate among Contiki motes, we use broadcast via UDP protocol in Contiki-NG OS. UDP is a communication stack that provides a set of lightweight communication primitives ranging from local-area broadcast to reliable network flooding.

For this demo, we need at least two Contiki-NG motes. One mote will act as a sender and the other mote will be a receiver. You can see our demo scenario in Figure 4-19.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig19_HTML.jpg
Figure 4-19

Communication among Contiki-NG motes

Our demo scenario is that a mote sends data to all motes. If a mote receives data, it will be shown in Terminal. We use a program sample from Contiki-NG.

Sending Broadcast Messages

The objective of a mote sender is to broadcast data to other motes. For this demo, we use the simple-udp module that is located in the <contiki-ng-root>/os/net folder. We can use the simple_udp_sendto() function to broadcast a message. This method is defined in the simple-udp.h header file:

int simple_udp_sendto_port(struct simple_udp_connection *c,
                          const void *data, uint16_t datalen,
                          const uip_ipaddr_t *to, uint16_t to_port);
Note:
  • simple_udp_connection is simple-udp object

  • data is data that will be sent

  • datalen is length of data

  • to is ip address of target

  • to_port is the port of the target

For instance, we send data to a specific IP address:

simple_udp_sendto(&udp_conn, &count, sizeof(count), &dag->dag_id);

Receiving Broadcast Messages

A mote receiver listens for an incoming message that is sent by a mote sender. To build a mote receiver, we can listen for broadcast messages by creating a callback/event function. We can use simple_udp_register() to register our callback function.

For instance, we listen for incoming broadcast messages using this code:

static void
udp_rx_callback(struct simple_udp_connection *c,
         const uip_ipaddr_t *sender_addr,
         uint16_t sender_port,
         const uip_ipaddr_t *receiver_addr,
         uint16_t receiver_port,
         const uint8_t *data,
         uint16_t datalen)
{
  unsigned count = *(unsigned *)data;
  LOG_INFO("Received response %u from ", count);
  LOG_INFO_6ADDR(sender_addr);
  LOG_INFO_(" ");
}
...
simple_udp_register(&udp_conn, UDP_CLIENT_PORT, NULL,
                      UDP_SERVER_PORT, udp_rx_callback);

Demo: Middleware Application

Now, we implement our sender and receiver program for Contiki-NG motes. We use a program sample from Contiki-NG, rpl-udp. You can find this project in the <contiki-ng-root>/examples/ folder.

The rpl-udp project consists of two programs, udp-client.c and udp-server.c. The UDP client app (udp-client.c) will send and receive broadcast messages. The UDP server (udp-server.c) will listen for incoming broadcast messages.

In the Makefile file, we configure our project and Contiki-NG paths. Write these scripts for the Makefile file:

all: udp-client udp-server
.PHONY: renode
renode: all
ifneq ($(TARGET),cc2538dk)
        $(error Only the cc2538dk TARGET is supported for Renode demo scripts)
endif
ifndef SCRIPT
        $(warning SCRIPT not defined! Using "rpl-udp.resc" as default)
        renode rpl-udp.resc
else
ifeq ($(wildcard $(SCRIPT)),)
       $(error SCRIPT "$(SCRIPT)" does not exist!)
endif
       renode $(SCRIPT)
endif
CONTIKI=../..
include $(CONTIKI)/Makefile.include

Save all files.

Since we need at least two Contiki-NG motes, we should know the serial ports that are used by our Contiki-NG motes. You can check this using this command:

$ ls /dev/ttyUSB*
You should see a list of serial ports that are used by the Contiki-NG motes. For instance, my two TelosB motes are detected, shown in Figure 4-20.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig20_HTML.jpg
Figure 4-20

Getting a list of connected Contiki-NG motes

To compile and upload the program to a specific Contiki-NG mote, we should pass MOTES with the serial port of the targeted Contiki-NG mote. For instance, we flash a program to a Contiki mote on serial port /dev/ttyUSB0. You can type these commands:

$ make TARGET=sky
$ make TARGET=sky savetarget
$ make udp-client.upload TARGET=sky MOTES=/dev/ttyUSB0

For the second Contiki-NG mote, you can type these commands:

$ make udp-server.upload TARGET=sky MOTES=/dev/ttyUSB1

After all programs are uploaded to the Contiki-NG motes, we can monitor the data exchange among Contiki-NG motes. For Contiki-NG mote 1, we can monitor messages using this command:

$ make login TARGET=sky MOTES=/dev/ttyUSB0

For Contiki-NG mote 2, we can execute this command to see exchange data in Terminal. Type this command:

$ make login TARGET=sky MOTES=/dev/ttyUSB1
You should see an incoming message in Terminal. You can see it in Figure 4-21.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig21_HTML.jpg
Figure 4-21

Running Contiki-NG application on mote 1 and mote 2

Middleware Application for Contiki-NG

In this section, we will explore using middleware for a Contiki-NG application. In our scenario, WSN motes will broadcast sensor data. Then, we will use a Java tool application from Contiki-NG to read these sensor data on a computer. The result of reading this data will be displayed in Terminal.

Let’s build!

What Is Middleware?

Middleware is a “bridge” application that connects Contiki-NG motes to other systems in internal and external networks. A sink can be represented as middleware. You can see a general architecture scenario of middleware for a Contiki-NG application in Figure 4-22.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig22_HTML.jpg
Figure 4-22

General scenario model of middleware for Contiki-NG

Implementing middleware for a Contiki-NG application could enhance Contiki-NG’s capabilities. As you know, Contiki-NG applications have a limitation in protocol stacks since they have limited hardware resources. Middleware can act as a bridge to connect Contiki-NG motes to other systems, such as database servers, external servers, and RESTful servers.

Middleware Architecture for Contiki-NG

In this section, we will build simple middleware for a Contiki-NG application. For this demo scenario, the middleware will listen for sensor data and print them to Terminal using Python. A general design for our demo is shown in Figure 4-23.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig23_HTML.jpg
Figure 4-23

Middleware architecture for demo

Implementation

To implement our demo, we use our previous program, rpl-udp (<contiki-ng_root/examples/rpl-udp), to be flashed into the Contiki-NG motes. We also use a previous Python program (section: “Access Contiki Motes via Serial”) to listen on the serial port contiki-viewer.py.

Testing

First, we compile the program and upload it to the motes. For instance, I have two WSN motes that are attached on serial ports /dev/USB0 and /dev/USB1. Then, we run contiki-viewer.py with a specific port. You can see the program output in Figure 4-24. In the next chapter, we will work more with middleware.
../images/456327_1_En_4_Chapter/456327_1_En_4_Fig24_HTML.jpg
Figure 4-24

Listening for incoming message from Python

Summary

We have learned to communicate among Contiki-NG motes. We also developed an application to communicate with Contiki-NG motes from a computer. Finally, we built simple middleware for a Contiki-NG application using a Python application tool.

In the next chapter, we will learn to focus on sensing and actuating in Contiki-NG motes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.111.125