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.
- Log into the Web portal with your account credentials
- 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”
- 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
- 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.
- Border Router: bridge between the server and the IoT-LAB IPv6 network
- Choose an available IPv6 prefix for the site you are experimenting on. For example in Grenoble testbed :
- we choose 2001:660:5307:3100::/64
- Choose one node in your nodes list to implement the Border Router (BR) node
- we choose node m3-1
- 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
-
- 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" ] }
- 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
- Ping6 BR node using global address:
<login>@grenoble:~$ ping6 2001:660:5307:3100::2354
- 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
- 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.
- 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'
- 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.
- Ping the CoAP server’s global address from SSH frontend
<login>@grenoble:~$ ping6 2001:660:5307:3100::9982
- 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"
- 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
- 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.
- 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.
- 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
- This resource is disabled by default, so you need to uncomment the line 159 in er-example-server.c