[Tutorial] Configure IoTivity on a RaspberryPi and test it with RIOT based nodes

Mattia Antonini edited this page Feb 1, 2017 · 10 revisions

This tutorial shows how to deploy and test IoTivity among RaspberryPi and RIOT-based nodes.


#Scenario The scenario we are considering is the following: Scenario

The IoTivity client is running on a RaspberryPi3 (RPi). It is equipped with Raspian (Version: September 2016) and IoTivity (Version: 1.2.0) compiled for ARM architecture. The client wants to interact with IoTivity servers that are running on RIOT-based nodes (they are SAMR21-XPRO boards). They implements the IoTivity-Constrained library, a lightweight implementation of the OCF specifications.

In order to deploy an IEEE802.15.4 constrained network, a Border Router(BR) is necessary. It is able to forward unicast packets between the RPi and constrained nodes. Our scenario requires an enhanced version of it that forwards also multicast packets with destination IPv6 address ff03::158 and port 5683 (OCF multicast packets).

#Step 1) Prepare the RaspberryPi Now, we download, install and configure the operating system for the Raspberry Pi. If you have already downloaded and configured your RPi, you can skip this part and go to the IoTivity Setup step.

##1.1) Install Raspian First of all, we have to install Raspian on a Raspberry Pi. You can find SD images and tools on the official wiki here.

##1.2) First boot Remove the SD from your computer and insert it in the RPi. Connect the power adapter, a keyboard and the HDMI cable to the board. After some seconds, the desktop will be ready.

For this tutorial, we assume we are using the board connected to a monitor. Everything can also be done through SSH connections.

##1.3) Setup an Internet Connection If you have a Wi-Fi enabled RPi, you can connect it to a Wi-Fi network. You can find here an exhaustive tutorial for the board configuration. Otherwise, you can connect it to an Ethernet cable.

##1.4) Updates Open a new terminal window by pressing CTRL+ALT+T and type

 $ sudo apt-get update && sudo apt-get dist-upgrade

and accept any request. Now, you are ready to go to the next step.

#Step 2) Install IoTivity on a RaspberryPi In this step, we compile and install IoTivity 1.2.0 on a RaspberryPi.

##2.1) Clone the Agile-IoTivity Repo Open a terminal window and type

 $ git clone https://github.com/Agile-IoT/agile-iotivity

this command downloads the entire repo.

Now, enter in the agile-iotivity folder by typing

 $ cd agile-iotivity

##2.2) Start the installation script Inside this folder there is a script called install_iotivity.sh, run it by typing

 $ sudo -k ./install_iotivity.sh

The terminal will prompt:

IoTivity will be installed with the following settings:

TARGET_OS: linux
IoTivity Version: 1.2.0
IoTivity working directory: /home/pi/agile-iotivity/iotivity_wdir

If you agree type Y otherwise N: 

If you enter Y, the setup starts, otherwise it exits. You can change this configuration by editing the #Setup Params section inside the file. The installation step requires some hours (usually 2/3 hours on a RPi3).

Whet it finishes you can continue to the next step.

#Step 3) Setup the RIOT-OS building environment on a RaspberryPi With this step we install the building environment for RIOT-OS on a RaspberryPi. We will install only tool-chain for ARM architecture and native. Go to the root directory of the agile-iotivity repository and type

$ sudo -k install_build_env_RIOT.sh

When it finishes, the environment is ready.

#Step 4) Prepare RIOT nodes During this step, we will flash the IoTivity server and the Border Router code on nodes.

##4.1) Download the RIOT code Open a terminal window and type

 $ git clone https://github.com/RIOT-OS/RIOT
 $ cd RIOT
 $ git checkout 2016.10

The RIOT Release 2016.10 is compatible with the IoTivity pkg. Now, copy the RIOT/pkg/iotivity and the RIOT/examples/iotivity_examples folders from the agile-iotivity clone-directory into the RIOT clone-directory (under the pkg and examples folders, respectively).

Examples are now available.

##4.2) Nodes detection Now, connect your nodes to the USB ports, go to /examples/iotivity_examples/server/ and type

 $ make list-ttys

This command shows the list of USB-Connected nodes. The output will be similar to

/sys/bus/usb/devices/2-1.3: Atmel Corp. EDBG CMSIS-DAP serial: 'ATML2127031800001234', tty(s): ttyACM0
/sys/bus/usb/devices/2-1.4: Atmel Corp. EDBG CMSIS-DAP serial: 'ATML2127031800004321', tty(s): ttyACM1

We will use Serial Numbers in order to identify the designed node during the compilation phase.

##4.3) Deploy the Server We are in /examples/iotivity_examples/server/. Now, we compile compile and flash the server on the node, so type

 $ make all BOARD=samr21-xpro
 $ make flash BOARD=samr21-xpro SERIAL=server_node_serial

After this step the server is deployed on the node. Finally, we open the node shell in order to see the terminal output by typing

 $ make term BOARD=samr21-xpro SERIAL=server_node_serial

The server output should be like

2016-11-25 12:52:33,599 - INFO # Connect to serial port /dev/ttyACM1
Welcome to pyterm!
Type '/exit' to exit.
2016-11-25 12:52:38,747 - INFO # main(): This is RIOT! (Version: 2016.07-devel-1173-g3e410-mattia-Latitude-E6410-pkg/iotivity)
2016-11-25 12:52:48,783 - INFO # server_oic: Waiting for address autoconfiguration...ipadapter: waiting for server requests...
2016-11-25 12:52:48,787 - INFO # ipadapter: waiting for multicast requests...
2016-11-25 12:52:48,789 - INFO # server_oic: LED0 is OFF
2016-11-25 12:52:48,792 - INFO # oc_main: Stack successfully initialized
2016-11-25 12:52:48,796 - INFO # server_oic: Configured network interfaces:
2016-11-25 12:52:48,802 - INFO # Iface  6   HWaddr: 44:8a  Channel: 26  Page: 0  NID: 0x23
2016-11-25 12:52:48,806 - INFO #            Long HWaddr: 5a:59:1c:2a:64:c7:c4:8a 
2016-11-25 12:52:48,813 - INFO #            TX-Power: 0dBm  State: IDLE  max. Retrans.: 3  CSMA Retries: 4 
2016-11-25 12:52:48,820 - INFO #            ACK_REQ  CSMA  MTU:1280  HL:64  6LO  RTR  IPHC  
2016-11-25 12:52:48,822 - INFO #            Source address length: 8
2016-11-25 12:52:48,824 - INFO #            Link type: wireless
2016-11-25 12:52:48,828 - INFO #            inet6 addr: ff02::1/128  scope: local [multicast]
2016-11-25 12:52:48,834 - INFO #            inet6 addr: fe80::5859:1c2a:64c7:c48a/64  scope: local
2016-11-25 12:52:48,840 - INFO #            inet6 addr: ff02::1:ffc7:c48a/128  scope: local [multicast]
2016-11-25 12:52:48,846 - INFO #            inet6 addr: ff02::1a/128  scope: local [multicast]
2016-11-25 12:52:48,863 - INFO #            inet6 addr: ff03::158/128  scope: global [multicast]
2016-11-25 12:52:48,869 - INFO #            inet6 addr: 2001:db8::5859:1c2a:64c7:c48a/64  scope: global
2016-11-25 12:52:48,875 - INFO #            inet6 addr: ff02::2/128  scope: local [multicast]
2016-11-25 12:52:48,876 - INFO #            

##4.4) Deploy the Border Router Now, we flash the Border Router code on a node. Move to /example/iotivity_examples/br_fw and type

 $ make all BOARD=samr21-xpro
 $ make flash BOARD=samr21-xpro SERIAL=br_node_serial

When the flashing finishes, the BR is ready. You can go to the next step.

#Step 5) Run the Scenario Our scenario is ready to be used.

##5.1) Start the Border Router You should be in RIOT/examples/iotivity_examples/br_fw, if not go to this directory. Now, reset every node by pressing the RESET button on board and type

$ PORT=/dev/ttyACM0 make term

It creates and configures a TAP interface. The terminal output should be like

net.ipv6.conf.tap0.forwarding = 1
net.ipv6.conf.tap0.accept_ra = 0
----> ethos: sending hello.
----> ethos: activating serial pass through.
----> ethos: hello reply received
uhcp_client(): timeout waiting for reply
uhcp_client(): sending REQ...

We have to complete the routing strategy by typing in the border router shell

 > ifconfig 7 add 2001:db8::2
 > fibroute add :: via 2001:db8::1 dev 7

Now, the network is ready and configured as follow:

  • Serial Port: /dev/ttyACM0
  • Interface: tap0
  • Address Prefix: 2001:db8::\64
  • Routing on tap0 of multicast packet with destination ff03::158

When the Border Router receives an OCF Multicast Request it prints on terminal

forwarder: got multicast request
forwarder: pck from [2001:0db8:0000:0000:0000:0000:0000:0001]:59560
forwarder: payload size 26 B
forwarder: waiting for multicast requests...

It is possible to configure the network with different parameters by invoking directly the initialization script instead of executing the make term command:

 $ make host-tools
 $ sudo ./start_network_mcast.sh <serial-port> <tap-device> <IPv6-prefix> <IPv6-mcast>

If you boot the network with different parameters, you have to change also the routing strategy inside the BR.

##5.2) Check the Server reachability If you have followed this tutorial step by step, the server should be reachable. Go to the Border Router shell and type

 > routers

it will prompt something like

if  Router                          state      type
 6  2001:db8::5859:1c2a:64c7:c48a   REACHABLE   REG

The IPv6 address should be the server address. Open a new terminal window and type

 $ ping6 2001:db8::5859:1c2a:64c7:c48a

If it the ping is successful, the server is reachable. If it does not work, kill the Border Router by pressing CTRL+C and return to Step 5.

##5.3) Test the IoTivity Client Open a new terminal window, go to agile-iotivity/IoTivity/Interactive-Client-Linux and compile the client by invoking

 $ make client

then run the client

 $ bin/client ff03::158

It starts the discovery phase:

Client: destination address is ff03::158
Client: Starting...
Client: NEW Resource Found: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/oic/p
Client: NEW Resource Found: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/oic/d
Client: NEW Resource Found: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/light/1
Client: There are 3 resource(s) in cache

Once it is completed, and it has found at least one resource, it enters in the Main Menu:

||                                                ||
||                 IoTivity CLIENT                ||
||                                                ||

Destination Address: ff03::158
Resource(s) discovered: 3

What do you want to do?
1 - Discovery ALL
2 - Print Resources information (From Cache)
3 - Show all Devices (From Nodes)
4 - Interact with Resources

0 - Exit

Type one option and it enters in the chosen option (without typing ENTER). ###Discovery ALL This feature allows to discover new resources that are not found during the previous discoveries. The output is:

Client: Discovery...
0: listenCallback(): failed to create resource. clientResponse: 255
Client: Resource Found: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/oic/p
Client: Resource Found: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/oic/d
Client: Resource Found: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/light/1
Client: NEW Resource Found: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/fan/1
Client: There are 4 resource(s) in cache

Client: Press any key to return to main menu...

If a resource is just discovered it is marked with the NEW label.

###Print Resources information (From Cache) This functionality prints the information on cached (discovered) resources. It returns Host, URI, Types and Interfaces:

Client: Resource(s) discovered:

Host: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789
URI: /oic/p
Resource Types:
Resource Interfaces: 

Host: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789
URI: /oic/d
Resource Types:
Resource Interfaces: 

Host: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789
URI: /light/1
Resource Types:
Resource Interfaces: 

Client: Press any key to return to main menu...

###Show all Devices (From Nodes) This feature sends a GET query to every resource with URI /oic/d. It parses responses and returns information:

Client: Host: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789
Client: Name: RIOT's light
Client: UUID: 0d9f5186-7a60-42df-6e6c-02890136b058
Client: Resource Type: oic.d.light

###Interact with Resources This functionality allows to create custom requests to discovered resources. First of all, choose a resource:

||                                                ||
||             Interact with Resources            ||
||                                                ||

Choose a resource:
1 - coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/oic/p
2 - coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/oic/d
3 - coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/light/1

0 - Return to Main Menu

For example 3:

You have selected: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789/light/1
Choose an operation:
1 -  Retrieve (GET)
2 -  Create (POST)
3 -  Update (PUT)
4 -  Delete (DELETE)

0 - Choose another resource

Now, you can select the desired option. At the moment, only Retrieve and Update are available.

####Retrieve It performs a GET request to the selected resource:

Performing GET...
state: false
Client: Press any key to return to continue...

The server terminal output should be like

2016-11-25 12:56:07,320 - INFO # ipadapter: got server request
2016-11-25 12:56:07,326 - INFO # Incoming message from [2001:0db8:0000:0000:0000:0000:0000:0001]:59560
2016-11-25 12:56:07,330 - INFO # ipadapter: waiting for server requests...
2016-11-25 12:56:07,332 - INFO # server_oic: GET request
2016-11-25 12:56:07,335 - INFO # server_oic: Light state 0
2016-11-25 12:56:07,341 - INFO # Outgoing message to [2001:0db8:0000:0000:0000:0000:0000:0001]:59560

####Update It performs a PUT request to the selected resource. It is possible to set which attributes you want.

Client: Now, you can define attributes for the request.
Client: Datatype supported:
Client: 		bool
Client: 		string
Client: 		uint8, int8, uint16, int16, int32
Client: syntax: <type> <name> <value>
Client: Type ENTER to continue
Client: e.g. bool state false
Client: e.g. uint8 power 4
Client: e.g. string something HelloWorld

Now, enter your attributes, e.g. bool state true and type ENTER. If you want, you can enter a new attributes. Leave the attribute empty to send the request.

Attribute: bool state true
Client: 1 attribute(s) set
Performing PUT...
Client: PUT Successful
Client: Press any key to return to continue...

The server changes the resource status and the terminal output should be like

2016-11-25 12:57:31,465 - INFO # ipadapter: got server request
2016-11-25 12:57:31,471 - INFO # Incoming message from [2001:0db8:0000:0000:0000:0000:0000:0001]:59560
2016-11-25 12:57:31,474 - INFO # ipadapter: waiting for server requests...
2016-11-25 12:57:31,476 - INFO # server_oic: PUT request
2016-11-25 12:57:31,479 - INFO # server_oic: key: state value: 1
2016-11-25 12:57:31,482 - INFO # server_oic: LED0 is ON
2016-11-25 12:57:31,487 - INFO # Outgoing message to [2001:0db8:0000:0000:0000:0000:0000:0001]:59560

You can verify if the resource is changed by performing a GET on this resource. Note: PUT requests can be performed to resource without the oic.if.r (READABLE) interface.