[6LoWPAN] UDP Server in Contiki

The mainly motivation of this post is about a friend of mine called Anass who that sent me an e-mail about UDP with Contiki. As in the first post, the tutorial just end with nothing really applicable in engineering, and now I want to teach a simple way to communicate with 6LoWPAN nodes using UDP sockets.

Setup Cooja

As I wrote in the first post, Cooja is a great tool to develop something with Contiki and test before deploy into real nodes, it take much less time to get things up and running. I'll use Cooja because I don't have any 6LoWPAN nodes nearby and it's more easy to show the concept using the simulator. In this setup let's create a simulation like the first post, if you don't have an idea how to do this, what the final video to get something like the image below:
setup_cooja The mote/node 1 uses the rpl-border-router firmware compiled for the target Z1, as in the tutorial in the link before. For the other motes, I mean, the clients UDP or the "sensors" of our network that'll send data to the gateway we'll create a different firmware.

Client device UDP

Lets create a specific firmware for the motes. Do the following steps:

cd contiki/examples  
mkdir udp-demo  
cd udp-demo  
touch udp-demo.c Makefile Makefile.target project-conf.h  

In the Makefile write:

CONTIKI_PROJECT = udp-demo  
CONTIKI = ../..  
include $(CONTIKI)/Makefile.include  

And in the Makefile.target

TARGET = z1  

In the project-conf.h, to be quick, let's use some project conf example from erbium CoAP demo:


#define NETSTACK_CONF_RDC              contikimac_driver


#define UIP_CONF_TCP                   0

#define NETSTACK_CONF_MAC     csma_driver
#define NETSTACK_CONF_MAC     nullmac_driver

#define REST_MAX_CHUNK_SIZE            48

#define RPL_CONF_WITH_DAO_ACK          0

#undef RPL_CONF_OF
#define RPL_CONF_OF                    rpl_of0


At the end, use the code below in the udp-demo.c, the code is very simple it just connect to through the simple-udp API to the border router address (tunneled by our SLIP connection) and after sends some data by 2 seconds of interval, but if you have some doubt, just send me an e-mail that I would appreciate to help:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include "contiki.h"
#include "contiki-net.h"
#include "dev/serial-line.h"
#include "net/ipv6/uip-ds6.h"
#include "sys/etimer.h"
#include "simple-udp.h"
#include "net/ip/uip-debug.h"

#define UDP_PORT_CENTRAL 7878
#define UDP_PORT_OUT 5555
static struct simple_udp_connection broadcast_connection;  
static uip_ipaddr_t server_addr;  
static uint16_t central_addr[] = {0xaaaa, 0, 0, 0, 0, 0, 0, 0x1};

void connect_udp_server();  
void uip_debug_ipaddr_print(const uip_ipaddr_t *addr);  
int ipaddr_sprintf(char *buf, uint8_t buf_len, const uip_ipaddr_t *addr);  
int sicslowpan_get_last_rssi();

PROCESS(init_system_proc, "Init system process");  

PROCESS_THREAD(init_system_proc, ev, data){  
        static struct etimer periodic_timer;

        //Init IPv6 network
        uint8_t buff_udp[50],
        sprintf((char *)device_id,"%02X%02X%02X%02X%02X%02X%02X%02X",
        sprintf((char *)device_address,"[%c%c%c%c]-Device-%s",device_id[12],device_id[13],device_id[14],device_id[15],device_id);
        etimer_set(&periodic_timer, CLOCK_REPORT);
        printf("Device initialized - %s\n", device_address);

        while (1) {

                int def_rt_rssi = sicslowpan_get_last_rssi();
                char def_rt_str[64];
                memset(def_rt_str, 0, sizeof(def_rt_str));
                ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose());
                sprintf((char *)buff_udp, "Hello my data -> addr:%02X%02X|%ddBm|%s",linkaddr_node_addr.u8[6],linkaddr_node_addr.u8[7],def_rt_rssi,def_rt_str);

                if (etimer_expired(&periodic_timer)) {
                        printf("Sending data to UDP Server at border router...");
                        simple_udp_sendto(&broadcast_connection, buff_udp, strlen((const char *)buff_udp), &server_addr);

void cb_receive_udp(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) {
        printf("########## UDP #########");
        printf("\nReceived from UDP Server:%s\n",data);

void connect_udp_server(){  
        printf("IPv6 UDP server: ");



int ipaddr_sprintf(char *buf, uint8_t buf_len, const uip_ipaddr_t *addr)  
        uint16_t a;
        uint8_t len = 0;
        int i, f;
        for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
                a = (addr->u8[i] << 8) + addr->u8[i + 1];
                if(a == 0 && f >= 0) {
                        if(f++ == 0) {
                                len += snprintf(&buf[len], buf_len - len, "::");
                } else {
                        if(f > 0) {
                                f = -1;
                        } else if(i > 0) {
                                len += snprintf(&buf[len], buf_len - len, ":");
                        len += snprintf(&buf[len], buf_len - len, "%x", a);

        return len;

Then, after edited the files, make the project:

make all  

Server UDP - Outside of the 6LoWPAN Network

With all copied right, let's create the UDP Server in node.js (you could use any other socket in another language, but this is more fast to use :P). Create the folder and the javascript server as below:

mkdir server-udp  
cd server-udp  
touch server.js  
npm install dgram --save  

Paste this code on server.js:

'use strict';  
let portIPv6 = 7878;  
let hostIPv6 = 'aaaa::1';  
let dgram = require('dgram');  
let serverUDP = dgram.createSocket('udp6');  
let disableLogs = false;

serverUDP.on('listening', function() {  
    var address = serverUDP.address();
    console.log('[UDP - IPV6] Active IPv6 server addr.:' + address.address + ":" + address.port);

serverUDP.on('message', processMessage);

serverUDP.bind(portIPv6, hostIPv6);

function processMessage(message, remote) {  
    if (!disableLogs)
        console.log('[UDP - IPv6] ' + new Date().toISOString() + ' ' + remote.address + ' Port:' + remote.port + ' - ' + message);
    let dataArray = message.toString().split('|');

Bring it on!

Go to Cooja and create the UDP Client mote (Motes >> Add motes >> Create new mote type >> Z1 mote...) and point to the firmware compiled before (udp-demo.z1). Once ready, add 4 or 10 motes at time (depends how much RAM you're willing to use :D) in the simulation and start the tunneled bridge with:

cd contiki/tools  
sudo ./tunslip6 -a aaaa::1/64  

Start the simulation clicking on START from Cooja panel and then go to the directory of our javascript udp server created before and start it too.

cd contiki/examples/udp-demo/server-udp  
node server.js  

If you have done alright, you should have something like this:

Yes, each mote/node is reporting yours information in the UDP Server!!!!

The format of the payload message must be:

Hello my data -> addr:Last byte address|RSSI from the last messagedBm|Neighbor address

To help anyone who had some problem in the edit the files, I created a repository with all things configured.

[Link of the repository] (https://github.com/aignacio/udp-contiki-ipv6)

This example works very well on real devices, in the next tutorial maybe I use some real node to demonstrate the performance behind. If you don't understand some part, just read the first post before comment and see if it's not in that post the answer. If you liked, share and subscribe for more tutorials like this.


Ânderson Ignacio da Silva

Electrical Engineer with electronic and protocols skills.

Rio Grande do Sul - Brasil http://aignacio.com

Subscribe to @aignacio's blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!