Objective
The objective of this post is to show you how to send information between two processes in Contiki OS, more specifically, i will show you how to send a structure from one process to the other. I tested the following example in a CM5000 sensor node, using Contiki OS 3.0 and ubuntu 16.04.
General Description of the C example
The example that is proposed here has two processes known as: read_temperature_light and example_unicast_process. The former process is in charge of reading the temperature and light values from the CM5000 sensor node, then it saves this information in a structure called environment. Then, this structure is sent to the process example_unicast_process via the function process_post(). Finally, the process example_unicast_process sends the structure environment wirelessly to the sink.
Process 1: read_temperature_light
The first process is in charge of reading the temperature and light values, saving this information in the structure environment and then passing this information to the second process example_unicast_process. The code below presents this process. Next, i will explain the most relevant lines:
- static struct etimer et: This line defines the structure known as et, which is a timer that post an event each 5 seconds. This means that each 5 seconds the timer expires and the process read_temperature_light is ejecuted.
- etimer_set(&et, CLOCK_SECOND * 5): This line sets the timer to expire in 5 seconds
- PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)): This line makes the process wait until the timer expires (5 seconds)
- envir.sequence = sequence: When the timer expires then the sequence is saved in the structure environment
- envir.temp = temporal: When the timer expires then the temperature is saved in the structure environment
- envir.light = temporal: When the timer expires then the light is saved in the structure environment
- process_post(&example_unicast_process, PROCESS_EVENT_CONTINUE , &(envir) ) : This is the most important line. With this line the current process read_temperature_light post an event to the process example_unicast_process, this means that the latter process will execute next. Besides, the information that is sent to the process example_unicast_process is the structure environment, which contains the light and temperature value read by the sensor.
Until now, we have stored the light and temperature values in the structure environment, then we called the process example_unicast_process and sent it the information contained in the structure named environment. In the process 2 example_unicast_process we will read the information from the structure environment.
PROCESS_THREAD(read_temperature_light, ev, data) // Process for reading the temperature and light values { static struct etimer et; // Struct used for the timer int temporal; //Temporal Variable PROCESS_BEGIN(); // Says where the process starts while(1){ etimer_set(&et, CLOCK_SECOND * 5); // Configure timer to expire in 5 seconds SENSORS_ACTIVATE(light_sensor); // Activate light sensor SENSORS_ACTIVATE(sht11_sensor); // Activate temperature sensor PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); // Wait until timer expires printf("Data\t"); // Print the string "Data" sequence++; printf("%d\t", sequence); // Print the sequence number envir.sequence = sequence; // To save the sequence in the struct envir printf("%d\t", temporal = get_temp()); // Print the temperature value envir.temp = temporal; // To save the temperature in the struct envir printf("%d\n", temporal = get_light()); // Print the light value envir.light = temporal; // To save the light in the struct envir process_post(&example_unicast_process, PROCESS_EVENT_CONTINUE , &(envir) ); // This function posts an asynchronous event to the process example_unicast_process with the information of the structure called envir etimer_reset(&et); // Reset timer SENSORS_DEACTIVATE(light_sensor); // Deactivate light sensor SENSORS_DEACTIVATE(sht11_sensor); // Deactivate temperature sensor } PROCESS_END();//Says where the process ends }
Process 2: example_unicast_process
In this process we will read the information from the structure environment. The code below presents this process. We will explain the most relevant lines:
- PROCESS_WAIT_EVENT(): This process executes whenever an event is posted. It means each time the process read_temperature_light post an event via the function process_post
- struct environment *envirRX = data: This line takes the data that the process received and save it into the structure pointer named *envirRX
- printf("%d\t", envirRX->sequence ): In order to access a structure's element we use the operator ->
- packetbuf_copyfrom( envirRX , sizeof( (*envirRX) ) ): We copy the structure envirRX in the packet buffer to send it wirelessly via the unicast_send() function
PROCESS_THREAD(example_unicast_process, ev, data) // Process for sending a unicast message { PROCESS_EXITHANDLER(unicast_close(&uc);)//Specify an action when a process exits. PROCESS_BEGIN(); // Says where the process starts unicast_open(&uc, 146, &unicast_callbacks); //Opens a unicast connection while(1) { linkaddr_t addr; //Declares the addr variable PROCESS_WAIT_EVENT(); //Wait for an event to be posted to the process. struct environment *envirRX = data; //Saves the information that comes from the other process (read_temperature_light) into a structure pointer called *envirRX printf("Data\t"); // Print the string "Data" printf("%d\t", envirRX->sequence ); // Print the sequence number printf("%d\t", envirRX->temp ); // Print the temperature value printf("%d\n", envirRX->light ); // Print the light value packetbuf_copyfrom( envirRX , sizeof( (*envirRX) ) ); addr.u8[0] = 1; //This is the sink's address addr.u8[1] = 0; //This is the sink's address if(!linkaddr_cmp(&addr, &linkaddr_node_addr)) { //if the address is diferent from the current's node unicast_send(&uc, &addr); //Send a unicast message to the sink } } PROCESS_END(); //Says where the process ends }
Full Example
The below code presents the full example.
/* * Copyright (c) 2007, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This file is part of the Contiki operating system. * */ /** * \file * Example of a node sending messages to a sink * \author * Sergio Diaz */ #include "contiki.h" #include "net/rime/rime.h" #include "dev/button-sensor.h" #include "dev/leds.h" #include//Libraries to manage the sensors #include "/home/sink/Desktop/contiki-3.0/dev/sht11/sht11-sensor.h" #include "/home/sink/Desktop/contiki-3.0/platform/sky/dev/light-sensor.h" #include "/home/sink/Desktop/contiki-3.0/core/dev/leds.h" //#include "example-uni-temp.h" // Declares the struct environment struct environment{ //You can put this structure declaration in an archive called example-uni-temp.h int sequence; //To save the sequence number int temp; // To save the temperature value int light; // To save the light value } /*---------------------------------------------------------------------------*/ PROCESS(example_unicast_process, "Example unicast"); // Process for sending a unicast message PROCESS(read_temperature_light, "Reads the Sensors Information"); // Process for reading the temperature and light values AUTOSTART_PROCESSES(&example_unicast_process, &read_temperature_light); //Start the process when the node boots struct environment envir; // Struct used to store the temperature and light values /*---------------------------------------------------------------------------*/ static int get_light(void) //Get the light value from sensor { return 10 * light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC) / 7; } /*---------------------------------------------------------------------------*/ static int get_temp(void) //Get the temperature value from sensor { return ((sht11_sensor.value(SHT11_SENSOR_TEMP) / 10) - 396) / 10; } /*---------------------------------------------------------------------------*/ int sequence = 0; // A sequence number that enumerates the data from 0 and increases in 1 each time. /*---------------------------------------------------------------------------*/ static void recv_uc(struct unicast_conn *c, const linkaddr_t *from) { //The node does not need to receive packets } static const struct unicast_callbacks unicast_callbacks = {recv_uc}; //Every time a packet arrives the function recv_uc is called. static struct unicast_conn uc; // Declares the unicast connection uc /*---------------------------------------------------------------------------*/ PROCESS_THREAD(read_temperature_light, ev, data) // Process for reading the temperature and light values { static struct etimer et; // Struct used for the timer int temporal; //Temporal Variable PROCESS_BEGIN(); // Says where the process starts while(1){ etimer_set(&et, CLOCK_SECOND * 5); // Configure timer to expire in 5 seconds SENSORS_ACTIVATE(light_sensor); // Activate light sensor SENSORS_ACTIVATE(sht11_sensor); // Activate temperature sensor PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); // Wait until timer expires printf("Data\t"); // Print the string "Data" sequence++; printf("%d\t", sequence); // Print the sequence number envir.sequence = sequence; // To save the sequence in the struct envir printf("%d\t", temporal = get_temp()); // Print the temperature value envir.temp = temporal; // To save the temperature in the struct envir printf("%d\n", temporal = get_light()); // Print the light value envir.light = temporal; // To save the light in the struct envir process_post(&example_unicast_process, PROCESS_EVENT_CONTINUE , &(envir) ); // This function posts an asynchronous event to the process example_unicast_process with the information of the structure called envir etimer_reset(&et); // Reset timer SENSORS_DEACTIVATE(light_sensor); // Deactivate light sensor SENSORS_DEACTIVATE(sht11_sensor); // Deactivate temperature sensor } PROCESS_END();//Says where the process ends } /*---------------------------------------------------------------------------*/ PROCESS_THREAD(example_unicast_process, ev, data) // Process for sending a unicast message { PROCESS_EXITHANDLER(unicast_close(&uc);)//Specify an action when a process exits. PROCESS_BEGIN(); // Says where the process starts unicast_open(&uc, 146, &unicast_callbacks); //Opens a unicast connection while(1) { linkaddr_t addr; //Declares the addr variable PROCESS_WAIT_EVENT(); //Wait for an event to be posted to the process. struct environment *envirRX = data; //Saves the information that comes from the other process (read_temperature_light) into a structure pointer called *envirRX printf("Data\t"); // Print the string "Data" printf("%d\t", envirRX->sequence ); // Print the sequence number printf("%d\t", envirRX->temp ); // Print the temperature value printf("%d\n", envirRX->light ); // Print the light value packetbuf_copyfrom( envirRX , sizeof( (*envirRX) ) ); addr.u8[0] = 1; //This is the sink's address addr.u8[1] = 0; //This is the sink's address if(!linkaddr_cmp(&addr, &linkaddr_node_addr)) { //if the address is diferent from the current's node unicast_send(&uc, &addr); //Send a unicast message to the sink } } PROCESS_END(); //Says where the process ends } /*---------------------------------------------------------------------------*/
As we execute, the first line that comes up is
ReplyDeletefatal: Not a git repository: '../../.git'
why does this occur?
I tried to use this idea for my project, I get an error which says the process which used "process_post" function ,does not recognize the other process which sent data to. the exact error sentence is "undefined reference to 'process_thread_receive_process' ". do you know how to fix it?
ReplyDeletehi, I'm a Halima. I executed the programme of DV-HOP with contiki cooja, in the first step I got good result but when I repeat the simulation with another value I didn't get any results.please help me to resolve this problem .
ReplyDeletehalima.ghribi33@gmail.com
hi, I want to implement an algorithm that can calculate the complexity of DV-HOP.please help me .
ReplyDeleteemail: halima.ghribi33@gmail.com