Use LWM2M running on top of a RPL network and M3 nodes

 

Difficulty: High

Duration: 60 minutes

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

Description: The aim of this tutorial is to discover the basics of OMA Lightweight M2M Protocol. You will reserve some M3 nodes on the Grenoble site, set them up with flashing LwM2M client firmware, and create a simple IPv6 network in IoT-LAB. After LwM2M client nodes will register with Leshan Eclispe server and you can understand Object resources model and data.

 

LwM2M overview

The LwM2M protocol was specified by industry experts in the Device Management Working Group at the Open Mobile Alliance (OMA). LwM2M is a secure, efficient and deployable client-server protocol for managing resource constrained devices. LwM2M uses architectural design based on REST, defines an extensible resource and data model and builds on data transfer standard called the Constrained Application Protocol (CoAP), standardized by the Internet Engineering Taskforce (IETF)

leshan-overview

Book and configure LwM2M nodes

 

  1. Connect to a site’s SSH frontend
    my_computer$ ssh <login>@grenoble.iot-lab.info
  2. Setup the contiki repository
    <login>@grenoble:~$ git clone https://github.com/iot-lab/iot-lab.git
    <login>@grenoble:~$ cd iot-lab
    <login>@grenoble:~$ make setup-contiki
    <login>@grenoble:~$ cd parts/contiki/
  3. If it is not alreay done, set your credentials for CLI tools with:
    <login>@grenoble:~/iot-lab/parts/contiki$ iotlab-auth -u <login>
  4. Submit a new experiment:
    • Duration: 60 minutes
    • Choose ten nodes: Archi = m3:at86rf231 / Site = grenoble / Number = 10

    Use this command with CLI tools:

    <login>@grenoble:~/iot-lab/parts/contiki$ iotlab-experiment submit -n lwm2m -d 60 -l 10,archi=m3:at86rf231+site=grenoble
  5. Wait for your experiment to be running:
    <login>@grenoble:~/iot-lab/parts/contiki$ iotlab-experiment wait
  6. Get the list of nodes of your experiments:
    <login>@grenoble:~/iot-lab/parts/contiki$ iotlab-experiment get -r
    {
     "items": [
     {
     ...
     "network_address": "m3-105.grenoble.iot-lab.info",
     "uid": "b576", 
     ...

    Pick one node that will be later used as Border Router and write down its ID and UID (e.g. m3-105 and b576).

  7. Choose an available IPv6 prefix for the site you are experimenting on. For example in Grenoble testbed :
    • we choose 2001:660:5307:3100::/64
  8. Launch tunslip6:
    <login>@grenoble:~$ sudo tunslip6.py -v2 -L -a m3-105 -p 20000 2001:660:5307:3100::1/64

    Note: 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 ipv6 prefix used on the frontend SSH with this command and choose another prefix .

    <login>@grenoble:~$ ip -6 route
    2001:660:5307:3100::/64 dev tun0  proto kernel  metric 256 
    fe80::/64 dev eth1  proto kernel  metric 256  
    fe80::/64 dev eth0  proto kernel  metric 256
  9. Program your BR node
    <login>@grenoble:~/iot-lab/parts/contiki$ cd examples/ipv6/rpl-border-router 
    <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$ iotlab-node -up border-router.iotlab-m3 -l grenoble,m3,105
  10. From another terminal, ping the Border Router:You can view the border router ipv6 address in the tunslip6 shell
    0750.128 Platform starting in 1... 
    0750.129 GO!
    0750.129 [in clock_init() DEBUG] Starting systick timer at 100Hz
    0750.131 
    0750.131 *** Address:2001:660:5307:3100::1 => 2001:0660:5307:3100
    0750.173  Starting 'Border router process' 'Web server'Got configuration message of type P
    0750.173 Setting prefix 2001:660:5307:3100::
    0751.130 Server IPv6 addresses:
    0751.130  2001:660:5307:3100::b576
    0751.131  fe80::b576
    
    <login>@grenoble:~$ ping6 2001:660:5307:3100::b576
  11. Choose one LwM2M client node picking another node (here node 108 and uid 8477). Open a new terminal and read serial port output
    <login>@grenoble:~$ nc m3-108 20000
  12. Program your LwM2M client nodes (iotlab-node -e option = flash firmware except BR node)
    <login>@grenoble:~/iot-lab/parts/contiki$ cd examples/iotlab/07-lwm2m-example
    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example$ make TARGET=iotlab-m3
    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example$ iotlab-node -up lwm2m-example-client.iotlab-m3 -e grenoble,m3,105
  13. Get the list of neighbors and links from the Border Router:
    <login>@grenoble:~$ lynx -dump http://[2001:660:5307:3100::b576]
     Neighbors
    fe80::a775
    fe80::9382
    fe80::b179
    fe80::b468
    fe80::9881
    fe80::1062
    fe80::a770
    fe80::8477
    
       Routes
    2001:660:5307:3100::b468/128 (via fe80::b468) 1666s
    2001:660:5307:3100::1062/128 (via fe80::1062) 1601s
    2001:660:5307:3100::a770/128 (via fe80::a770) 1494s
    2001:660:5307:3100::a775/128 (via fe80::a775) 1485s
    2001:660:5307:3100::9382/128 (via fe80::9382) 1408s
    2001:660:5307:3100::b179/128 (via fe80::b179) 1152s
    2001:660:5307:3100::9881/128 (via fe80::9881) 816s
    2001:660:5307:3100::8477/128 (via fe80::8477) 813s
    
  14. Ping6 LwM2M client node:
    <login>@grenoble:~$ ping6 2001:660:5307:3100::8477
  15. Verify on the serial port output that the LwM2M client has registered with the LwM2M server (eg. Eclipse Leshan)
    <login>@grenoble:~$ nc m3-108 20000
    Platform starting in 1... 
    GO!
    [in clock_init() DEBUG] Starting systick timer at 100Hz
     Starting 'IoT-LAB LWM2M client example'
    RD Client started with endpoint '?ep=M3000000008477'
    Registering with [2001:660:5307:3200::2]:5683 lwm2m endpoint '?ep=M3000000008477': '<3/0>,<3303/0>,<3311/0>,<3313/0>,<3314/0>,<3334/0>,<3341/0>'

LwM2M server and objects resources model

  1. Go to Leshan server web interface and visualize the clients list. You can view all LwM2M client nodes with a client endpoint like M300000000<uid>
  2. Select one client and visualize the instance tab. You shoud get two attributes like “Manufacturer” and “Model Number” with Read button.These parameters are mapping in the firmware with Contiki project-conf.h file variables
    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example$ cat project-conf.h
    //////////LWM2M DEVICE//////////////
    
    #ifndef LWM2M_DEVICE_MANUFACTURER
    #define LWM2M_DEVICE_MANUFACTURER "IoT-LAB"
    #endif
    
    #ifndef LWM2M_DEVICE_TYPE
    #define LWM2M_DEVICE_TYPE "STM32F103REY"
    #endif
    
    #ifndef LWM2M_DEVICE_MODEL_NUMBER
    #define LWM2M_DEVICE_MODEL_NUMBER "M3"
    #endif
    
  3. LwM2M objects/resources are accessed with simple URIs: /{Object ID}/{Object Instance}/{Resource ID}. For example with temperature The LwM2M technical specification itself defines eight objects; the repository contains many more contributed by IPSO alliance, oneM2M, and from vendors. You can view the temperature object XML definition here and view the table below:Go to temperature object tab and read resources on Leshan interface. You can also use observe instead of read request on the sensor value resource and it will be update automatically every 30 seconds. Whenever the state of a resource changes, the client notifies each server registered as observer for the resource.Indeed in the firmware code you should see a timer which handle temperature object notification
    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example$ cat lwm2m-example-client.c
      etimer_set(&timer, CLOCK_SECOND *30);
    
      while(1) {
        PROCESS_WAIT_EVENT();
        if (ev == PROCESS_EVENT_TIMER) {
          /* Call the temperature object handler */
          object_temperature_handle();
          etimer_restart(&timer);
        }
    

    Moreover you should visualize the IPSO temperature object definition in the source code with the handle method

    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example/ipso-objects$ cat obj-temperature.c
    /*---------------------------------------------------------------------------*/
    LWM2M_RESOURCES(temperature_resources,
                    /* Temperature (Current) */
                    LWM2M_RESOURCE_CALLBACK(5700, { temp, NULL, NULL }),
                    /* Min Range Value */
                    LWM2M_RESOURCE_FLOATFIX(5603, TEMPERATURE_MIN),
                    /* Max Range Value */
                    LWM2M_RESOURCE_FLOATFIX(5604, TEMPERATURE_MAX),
                    /* Units */
                    LWM2M_RESOURCE_STRING(5701, "Cel"),
                    );
    LWM2M_INSTANCES(temperature_instances,
                    LWM2M_INSTANCE(0, temperature_resources));
    LWM2M_OBJECT(temperature, 3303, temperature_instances);
    /*---------------------------------------------------------------------------*/
    
    void
    object_temperature_handle(void)
    {
      printf("Notify observer temperature sensor\n");
      lwm2m_object_notify_observers(&temperature, "/0/5700");
    }
    
  4. Go to leds object tab in leshan interface. Try ro read resources Colour (Green by default) and sensor units. If you see the object XML definition you can see that the resource Colour is in read/write mode. So choose Colour (Red or Blue) and try to write the resource.View the source code of leds object and understand how you can write the On/Off resource.
    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example/ipso-objects$ cat obj-leds-control.c
    /*---------------------------------------------------------------------------*/
    LWM2M_RESOURCES(leds_control_resources,
                    LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }),
                    LWM2M_RESOURCE_CALLBACK(5706, { read_color, write_color, NULL }),
                    /* Units */
                    LWM2M_RESOURCE_STRING(5701, "Lux"),
                    );
    LWM2M_INSTANCES(leds_control_instances,
                    LWM2M_INSTANCE(0, leds_control_resources));
    LWM2M_OBJECT(leds_control, 3311, leds_control_instances);
    
    /*---------------------------------------------------------------------------*/
    
  5. You can test the last object tab with “Addressable Text Display” object. The idea is to interact with the serial port of the LwM2M client node. For this purpose you must find the node name which corresponding to client endpoint. In this example we use client M3000000008477 (eg. m3-108). Firstly you can read “Text” resource on leshan web interface and verify that you have no serial input. After write on the serial port of the node “Hello World!” and read again “Text” resource to see the update value in leshan interface
    <login>@grenoble:~$ nc m3-108 20000
    Hello World!
    

    Next try observe button and write on serial port to verify that the “Text” resource is updated automatically. Finally use Write button in leshan interface and visualize that your string is print on serial port

    View in the source code the serial event handler and the “Addressable Text Display” object to understand the behaviour.

    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example$ cat lwm2m-example-client.c
    while(1) {
        PROCESS_WAIT_EVENT();
        ...
        if(ev == serial_line_event_message) {
          obj_serial_data = (char*)data;
          /* Call the serial object handler */
          object_serial_handle();
        }
    
    <login>@grenoble:~/iot-lab/parts/contiki/examples/iotlab/07-lwm2m-example/ipso-objects$ cat obj-serial.c
    /*---------------------------------------------------------------------------*/
    LWM2M_RESOURCES(serial_resources,
                    /* serial text */
                    LWM2M_RESOURCE_CALLBACK(5527, { read_serial, write_serial, NULL }),
                    );
    LWM2M_INSTANCES(serial_instances,
                    LWM2M_INSTANCE(0, serial_resources));
    LWM2M_OBJECT(serial, 3341, serial_instances);
    /*---------------------------------------------------------------------------*/
    
    void
    object_serial_handle(void)
    {
      printf("Notify observer serial sensor\n");
      lwm2m_object_notify_observers(&serial, "/0/5527");
    }
    

Congratulations you have finished the tutorial!!!!