CoAP server with public IPv6/RPL/6LoWPAN network

 

Difficulty: High

Duration: 90 minutes

Prerequisites: Configure SSH Access / Get and compile firmware for M3 and A8-M3 nodes / Understand IPv6 subnetting / Public IPv6/6LoWPAN/RPL network with M3 nodes

Description: The aim of this tutorial is to discover the basics of Constrained Application Protocol (CoAP) . You will reserve some M3 nodes on the Grenoble site, set them up with flashing two firmwares nodes, and create a simple IPv6 network in IoT-LAB. You will access nodes over IPv6 using a Contiki tunslip6 bridge and launch requests on a CoAP Contiki Erbium server implementation.

  1. Log into the Web portal with your account credentials
  2. Submit a new experiment:
    • Set an experiment name (no spaces nor funny chars in the experiment name)
    • Duration: 60 minutes and starting “As soon as possible
    • Choose ten nodes with Architecture m3 (at86rf231) / Site = grenoble / Number = 10 and click “Add to experiment”
  3. Wait experiment state Running in the Schedule dashboard section. After click on experiment details and visualize which nodes you are booked and verify that you have Success in the deployment result
  4. Compile firmwares on SSH frontend.
    my_computer$ ssh <login>@grenoble.iot-lab.info
    • Border Router: bridge between the server and the IoT-LAB IPv6 network
      <login>@grenoble:~$ cd ~/iot-lab/parts/contiki/examples/ipv6/rpl-border-router

      Optionnal : setup CHANNEL and PANID, edit project-conf.h

      #ifndef PROJECT_ROUTER_CONF_H_
      #define PROJECT_ROUTER_CONF_H_
      
      #undef RF2XX_CHANNEL
      #define RF2XX_CHANNEL                     11
      #undef IEEE802154_CONF_PANID
      #define IEEE802154_CONF_PANID          0x0001
      

      Compile for iotlab-m3 target

      <login>@grenoble:~/iot-lab/parts/contiki/examples/ipv6/rpl-border-router$ make TARGET=iotlab-m3
      <login>@grenoble:~/iot-lab/parts/contiki/examples/ipv6/rpl-border-router$ ls
      ... border-router.iotlab-m3 ...
      <login>@grenoble:~/iot-lab/parts/contiki/examples/ipv6/rpl-border-router$ cp border-router.iotlab-m3 ~/
      
    • IoT-LAB version of CoAP Erbium server:
      <login>@grenoble:~$ cd ~/iot-lab/parts/contiki/examples/iotlab/04-er-rest-example

      Optionnal : setup CHANNEL and PANID, edit project-conf.h

      #ifndef __PROJECT_ERBIUM_CONF_H__
      #define __PROJECT_ERBIUM_CONF_H__
      
      /* Custom channel and PAN ID configuration for your project. */
      #undef RF2XX_CHANNEL
      #define RF2XX_CHANNEL                     11
      
      #undef IEEE802154_CONF_PANID
      #define IEEE802154_CONF_PANID          0x0001
      

      Compile for iotlab-m3 target

      <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/04-er-rest-example$ make TARGET=iotlab-m3
      <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/04-er-rest-example$ ls
      ... er-example-server.iotlab-m3 ...
      <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/04-er-rest-example$ cp er-example-server.iotlab-m3 ~/
      

    View Border Router and CoAP Server source code on GitHub.

  5. Choose an available IPv6 prefix for the site you are experimenting on. For example in Grenoble testbed :
    • we choose 2001:660:5307:3100::/64
  6. Choose one node in your nodes list to implement the Border Router (BR) node
    • we choose node m3-1
  7. Start tunslip6 on the SSH frontend:
    • <login>@grenoble:~$ sudo tunslip6.py -v2 -L -a m3-1 -p 20000 2001:660:5307:3100::1/64
      slip connected to ``172.16.10.1:20000''
      
      15:38:19 opened tun device ``/dev/tun0''
      0000.000 ifconfig tun0 inet `hostname` up
      0000.004 ifconfig tun0 add 2001:660:5307:3100::1/64
      0000.005 ifconfig tun0 add fe80::660:5307:3100:1/64
      0000.007 ifconfig tun0
      
      tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
                inet adr:192.168.1.4  P-t-P:192.168.1.4  Masque:255.255.255.255
                adr inet6: 2001:660:5307:3100::1/64 Scope:Global
                adr inet6: fe80::660:5307:3100:1/64 Scope:Lien
                UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
                RX packets:0 errors:0 dropped:0 overruns:0 frame:0
                TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
                collisions:0 lg file transmission:500
                RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    • Note 1: leave the terminal open (you don’t want to kill tunslip6, it bridges the BR to the front-end network)
    • Note 2: If you have an error “overlaps with routes”, it’s because another experiment is using the same ipv6 prefix (e.g. : 2001:660:5307:3100::/64).

      You can view currently used IPv6 prefixes on the frontend SSH with this command

      <login>@grenoble:~$ ip -6 route
      2001:660:5307:30fff::/64 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
      2001:660:5307:3100::/64 dev tun0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
      fe80::/64 dev eth1  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
      fe80::/64 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
      fe80::/64 dev tun0  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 4294967295
      default via 2001:660:5307:30ff:ff:: dev eth0  metric 1  mtu 1500 advmss 1440 hoplimit 4294967295
    • Note 3: if you did not already authenticate using iotlab-auth, do it now:
      <login>@grenoble:~$ iotlab-auth -u login
  8. Deploy the Border Router (BR) node on selected node using the CLI tool iotlab-node.
    <login>@grenoble:~$ iotlab-node --update ~/iot-lab/parts/contiki/examples/ipv6/rpl-border-router/border-router.iotlab-m3 -l grenoble,m3,1
    {
        "0": [
            "m3-1.grenoble.iot-lab.info"
        ]
    }
  9. Get the Border Router IPv6 address from tunslip output:
    ...
    Platform starting in 1...
    GO!
    [in clock_init() DEBUG] Starting systick timer at 100Hz
    
    0473.257 *** Address:2001:660:5307:3100::1 => 2001:0660:5307:3100
    0473.257  Starting 'Border router process' 'Web server'Got configuration message of type P
    0473.257 Setting prefix 2001:660:5307:3100::
    0473.257 Server IPv6 addresses:
    0473.257  2001:660:5307:3100::2354
    0473.257  fe80::2354
    
  10. Ping6 BR node using global address:
    <login>@grenoble:~$ ping6 2001:660:5307:3100::2354
  11. Choose one CoAP server node picking another node (here node 2). Open a new terminal and read serial port output
    <login>@grenoble:~$ nc m3-2 20000
  12. Flash CoAP server firmware on the other nodes.
    <login>@grenoble:~$ iotlab-node --update ~/iot-lab/parts/contiki/examples/iotlab/04-er-rest-example/er-example-server.iotlab-m3 -e grenoble,m3,1
    {
        "0": [
    		"m3-2.grenoble.iot-lab.info",
    		"m3-3.grenoble.iot-lab.info",
    		"m3-4.grenoble.iot-lab.info",
    		"m3-5.grenoble.iot-lab.info",
    		"m3-6.grenoble.iot-lab.info",
    		"m3-13.grenoble.iot-lab.info",
    		"m3-287.grenoble.iot-lab.info",
    		"m3-288.grenoble.iot-lab.info",
    		"m3-289.grenoble.iot-lab.info"
        ]
    }

    Let’s do the following with one CoAP server, for example m3-2. You can do the same with any other server.

  13. View CoAP server starting on the serial output
    <login>@grenoble:~$ nc m3-2 20000
    Platform starting in 1... 
    GO!
    [in clock_init() DEBUG] Starting systick timer at 100Hz
    Starting 'IoT-LAB CoAP Server'
    
  14. Grab the CoAP server node’s IPv6 address from the BR’s web interface
    <login>@grenoble:~$ lynx -dump http://[2001:660:5307:3100::2354]
    Neighbors
    fe80::9982
    Routes
    2001:660:5307:3100::9982/128 (via fe80::9982) 16711353s
    

    Understand M3 nodes uid / ipv6 address match.

  15. Ping the CoAP server’s global address from SSH frontend
    <login>@grenoble:~$ ping6 2001:660:5307:3100::9982
  16. For resource discovery, CoAP use the /.well-known/core path to provide resource descriptions in its CoRE Link Format. Send CoAP request with the aiocoap-client installed on the SSH frontend:
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/.well-known/core
    </.well-known/core>;ct=40,</test/hello>;title="Hello world: ?len=0..";rt="Text",</test/push>;title="Periodic demo";obs,</actuators/toggle>;title="Red LED";rt="Control",</sensors/light>;title="Ambient light (supports JSON)";rt="LightSensor",</sensors/pressure>;title="Pressure (supports JSON)";rt="PressureSensor",</sensors/gyros>;title="Three axis gyroscope (supports JSON)";rt="GyroscopeSensor",</sensors/accel>;title="Three axis accelerometer (supports JSON)";rt="AccelerometerSensor",</sensors/magne>;title="Three axis magnetometer (supports JSON)";rt="MagnetometerSensor"
    
  17. Test different GET requests to the different sensors resources
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/sensors/light
    0
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/sensors/pressure
    992
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/sensors/gyros
    -96;1557;-52
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/sensors/accel
    -107;-12;-1025
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/sensors/magne
    -75;-261;422
    
  18. Test the Hello world resource with path /test/hello
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/test/hello
    Hello World!
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/test/hello?len=42 # print 42 caracters
    Hello World! ABCDEFGHIJKLMNOPQRSTUVWXYZabc
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/test/hello?len=64 # print 64 caracters
    Hello World! ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy
    <login>@grenoble:~$ aiocoap-client coap://[2001:660:5307:3100::9982]:5683/test/hello?len=80 # print 64 caracters 
    Hello World! ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy
    

    The last output is 64 characters too, because the REST_MAX_CHUNK_SIZE, defined in the application’s project-conf.h, is 64 bytes.

  19. CoAP provides Observers support (publish/subscribe mechanism). They allow for a client to receive updates when a state changes. This reduces the need for constant polling but also introduces additional engineering overhead into the protocol when considering sleeping nodes and unreliable networks. Ther Erbium CoAP Server includes an example of PERIODIC resource, notifying each subscriber at a time interval (5 seconds) with the resource value (here a simple counter).
    <login>@grenoble:~$ aiocoap-client --observe coap://[2001:660:5307:3100::9982]:5683/test/push
     VERY LONG EVENT 235
    VERY LONG EVENT 236
    VERY LONG EVENT 237
    ...
    

    Note : Regarding the counter value, you will understand that the server starts the periodic resource on the node at the starting of the server even if you don’t have subscribers.

  20. The server also provides the support for EVENT resource. To illustrate this feature we handle an event when an input has been received from the serial port of the node and we send a CoAP response with the data input.
    • This resource is disabled by default, so you need to uncomment the line 159 in er-example-server.c
      rest_activate_resource(&res_event, "test/serial");
    • Compile and flash this new firmware
      <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/04-er-rest-example$ make TARGET=iotlab-m3 && iotlab-node --update -l grenoble,m3,2
    • Observe this resource
      <login>@grenoble:~$ aiocoap-client --observe coap://[2001:660:5307:3100::9982]:5683/test/serial
    • Each time a string is sended into the serial port, a notification is sended by the CoAP server
      <login>@grenoble:~$ nc m3-2 20000
      ...
      coap event # write this string and press enter
      
      <login>@grenoble:~$ aiocoap-client --observe coap://[2001:660:5307:3100::9982]:5683/test/serial
      ...
      coap event