Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
[Tutorial] Configure IoTivity on a RaspberryPi and test it with RIOT based nodes
Clone this wiki locally
This tutorial shows how to deploy and test IoTivity among RaspberryPi and RIOT-based nodes.
- Step 1) Prepare the RaspberryPi
- Step 2) Install IoTivity on a RaspberryPi
- Step 3) Setup the RIOT-OS building environment on a RaspberryPi
- Step 4) Prepare RIOT nodes
- Step 5) Run the 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.
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.
$ sudo apt-get update && sudo apt-get dist-upgrade
and accept any request. Now, you are ready to go to the next step.
$ 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
$ sudo -k ./install_iotivity.sh
The terminal will prompt:
IoTivity will be installed with the following settings: TARGET_OS: linux TARGET_ARCH: arm TARGET_TRANSPORT: ALL SECURED: 0 RELEASE: yes ROUTING: EP BUILD_SAMPLE:OFF 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.
$ 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
examples folders, respectively).
Examples are now available.
$ 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.
$ 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 #
$ 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.
$ 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.
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.
$ 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 Choice:
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: oic.wk.p Resource Interfaces: oic.if.r oic.if.baseline Host: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789 URI: /oic/d Resource Types: oic.d.light Resource Interfaces: oic.if.r oic.if.baseline Host: coap://[2001:db8::5859:1c2a:64c7:c48a]:56789 URI: /light/1 Resource Types: oic.r.light Resource Interfaces: oic.if.rw oic.if.baseline 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 Choice:
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 Choice:
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 Attribute:
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 Attribute: 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.