Send data from Raspberry Pi to Oracle IoT Cloud Service

Tweet about this on TwitterShare on Facebook0Share on LinkedIn25Share on Google+0

Today we are experiencing the transformation caused by the Internet of Things (IoT) and it is common to see simple IoT projects such as humidity and temperature monitoring or complex projects such as connected cars. Most simple projects are using low cost platforms like Arduino or Raspberry Pi and anyone can start their own IoT project easily.

In this post, we’ll learn how to send humidity and temperature data from Raspberry Pi to Oracle Internet of Things Cloud Service.
I will use my Raspberry Pi 3 Model B and a DHT11 sensor.

For this project I will use C language and C Posix SDK provided by Oracle, but you have other programming language options.

Go to your Iot Cloud Service instance and create a new application. Name it as “Humidity and Temperature” and click the Create button.

Click the Humidity and Temperature application and create a new Device Model. Name it as “Humidity and Temperature Sensor” and set URN as “urn:com:oracle:iot:device:humidity_temperature”.

Add two Custom Attributes, humidity and temperature.
Set both attributes as Number type.

Click the Save button.
Go to Registration page and click the Register Single Device button.

Fill out the form and click the Register button.

To generate the device provisioning file, specify a password and click the Download Provisioning File button.

Log in to your Raspberry Pi and execute the following command:

sudo apt-get install libssl-dev -y

At this moment the last version of C POSIX Client Software Library is 17.2.5.0.0-5, but I recommend that you verify the current version here: Oracle IoT Cloud Service Client Software Library downloads page.
Execute the following command to create a new iotcs-cposix folder and download the Binary file for C POSIX Client Software Library:

mkdir iotcs-cposix

cd iotcs-cposix

wget http://download.oracle.com/otn_software/samples/cloud/iotcs-csl-posix-bin-17.2.5.0.0-5.zip

Execute the following command to extract the content of the iotcs-csl-posix-bin-17.2.5.0.0-5.zip file.

unzip iotcs-csl-posix-bin-17.2.5.0.0-5.zip

In the bin directory (/home/pi/iotcs-cposix/iotcs/csl/posix/bin), create a new humidity_temperature.c file and use the following code:

/*
 * An example of a directly connected device which is capable of communicating
 * directly with Oracle IoT Cloud Service. This sample illustrates 
 * C code for sending data to the cloud service and does not fully explore the Client Library API.
 *
 * The sample uses the virtualization API. It presents a simple messenger.
 *
 * Device implements a device model. A device model is a set of related
 * attributes, actions, and message formats that can be represented in
 * a real device. For this example the "Hello World" device model is used.
 * This device model must be uploaded to the server before running this example.
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wiringPi.h>
#include <stdint.h>
 
/* include common public types */
#include "iotcs.h"
/* include iot cs device model APIs */
#include "iotcs_virtual_device.h"
/* include methods for device client*/
#include "iotcs_device.h"
 
/* Current humidity value */
static int current_humidity_value;
/* Current temperature value */
static int current_temperature_value;
/* Device model handle */
static iotcs_device_model_handle device_model_handle = NULL;
/* Device handle */
static iotcs_virtual_device_handle device_handle = NULL;

#define MAXTIMINGS  85
#define DHTPIN    15
int dht11_dat[5] = { 0, 0, 0, 0, 0 };
 
static void finalize_library() {
    /* free device handle */
    if (device_handle) {
        iotcs_free_virtual_device_handle(device_handle);
        device_handle = NULL;
    }
	
    /* free device model handle */
    if (device_model_handle) {
        iotcs_free_device_model_handle(device_model_handle);
        device_model_handle = NULL;
    }
	
    iotcs_finalize();
}

/* print error message and terminate the program execution */
static void error(const char* message) {
    printf("Error occurred: %s\n", message);
    finalize_library();
    exit(EXIT_FAILURE);
}

void sensor_work() {
    uint8_t laststate = HIGH;
    uint8_t counter   = 0;
    uint8_t j   = 0, i;
    float f; /* fahrenheit */

    dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;

    /* pull pin down for 18 milliseconds */
    pinMode( DHTPIN, OUTPUT );
    digitalWrite( DHTPIN, LOW );
    delay( 18 );
    /* then pull it up for 40 microseconds */
    digitalWrite( DHTPIN, HIGH );
    delayMicroseconds( 40 );
    /* prepare to read the pin */
    pinMode( DHTPIN, INPUT );

    /* detect change and read data */
    for ( i = 0; i < MAXTIMINGS; i++ ) {
        counter = 0;
        while ( digitalRead( DHTPIN ) == laststate ) {
            counter++;
            delayMicroseconds( 1 );
            if ( counter == 255 ) {
                break;
            }
        }
        laststate = digitalRead( DHTPIN );

        if ( counter == 255 ) {
            break;
        }

        /* ignore first 3 transitions */
        if ( (i >= 4) && (i % 2 == 0) ) {
            /* shove each bit into the storage bytes */
            dht11_dat[j / 8] <<= 1;
            if ( counter > 16 ) {
                dht11_dat[j / 8] |= 1;
            }
            j++;
        }
    }

    /*
     * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
     * print it out if data is good
     */
    if ( (j >= 40) && (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) ) {
        f = dht11_dat[2] * 9. / 5. + 32;
        current_humidity_value = dht11_dat[0];
        current_temperature_value = dht11_dat[2];
        printf( "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
    } else  {
        current_humidity_value = 0;
        current_temperature_value = 0;
        printf( "Data not good, skip\n" );
    }
}
 
int main(int argc, char** argv) {
    /* This is the URN of your device model. */
    const char* device_urns[] = {
        "urn:com:oracle:iot:device:humidity_temperature",
        NULL
    };
 
    iotcs_result rv;
 
    if (argc < 3) {
        error("Too few parameters.\n"
                "\nUsage:"
                "\n\tdirectly_connected_device.out path password"
                "\n\tpath is a path to trusted assets store."
                "\n\tpassword is a password for trusted assets store.");
    }
    const char* ts_path = argv[1];
    const char* ts_password = argv[2];
  
    /*
     * Initialize the library before any other calls.
     * Initiate all subsystems like ssl, TAM, request dispatcher,
     * async message dispatcher, etc which needed for correct library work.
     */
    if (iotcs_init(ts_path, ts_password) != IOTCS_RESULT_OK) {
        error("Initialization failed");
    }
 
    /*
     * Activate the device, if it's not already activated.
     * Always check if the device is activated before calling activate.
     * The device model URN is passed into the activate call to tell
     * the server the device model(s) that are supported by this
     * directly connected device
     */
    if (!iotcs_is_activated()) {
        if (iotcs_activate(device_urns) != IOTCS_RESULT_OK) {
            error("Sending activation request failed");
        }
    }
 
    /* get device model handle */
    if (iotcs_get_device_model_handle(device_urns[0], &device_model_handle) != IOTCS_RESULT_OK) {
        printf("iotcs_get_device_model_handle method failed\n");
        return IOTCS_RESULT_FAIL;
    }
 
    /* get device handle */
    if (iotcs_get_virtual_device_handle(iotcs_get_endpoint_id(), device_model_handle, &device_handle) != IOTCS_RESULT_OK) {
        printf("iotcs_get_device_handle method failed\n");
        return IOTCS_RESULT_FAIL;
    }
	
    printf( "Humidity and Temperature Program initializing...\n" );
	
    if ( wiringPiSetup() == -1 ) {
        exit( 1 );
    }

    while ( 1 ) {
        /* wait 1sec to refresh */
        delay( 1000 );
        sensor_work();
        if (current_humidity_value > 0 && current_temperature_value > 0) {
            iotcs_virtual_device_start_update(device_handle);

            /* set humidity value */
            rv = iotcs_virtual_device_set_float(device_handle, "humidity", current_humidity_value);

            if (rv != IOTCS_RESULT_OK) {
                error("iotcs_virtual_device_set_integer method failed\n");
            }

            /* set temperature value */
            rv = iotcs_virtual_device_set_float(device_handle, "temperature", current_temperature_value);

            if (rv != IOTCS_RESULT_OK) {
                error("iotcs_virtual_device_set_integer method failed\n");
            }

            iotcs_virtual_device_finish_update(device_handle);
        }
    }
	
    finalize_library();
    return EXIT_SUCCESS;
}

Execute the following commands to install the GPIO library:

sudo git clone git://git.drogon.net/wiringPi

cd wiringPi

sudo ./build

Compile the C program.

cd ..

gcc -g -I../include -I../lib/arm -o ./humidity_temperature.out ./humidity_temperature.c -Wl,-Bstatic -L../lib/arm -ldeviceclient -Wl,-Bdynamic -lssl -lcrypto -lm -lrt -lpthread -lwiringPi

Copy the provisioning file that was downloaded when you registered the device into that directory.

Create a new start_humidity_temperature.sh file and use the following code: (Note: File_Protection_Password is the same you used in the Oracle IoT Cloud Service to download the provisioning file.)

export IOTCS_OS_NAME="Raspbian GNU/Linux"
export IOTCS_OS_VERSION="8"
./humidity_temperature.out B8-27-EB-E6-8C-58.txt File_Protection_Password

Execute the following command to start the C program:

chmod +x start_humidity_temperature.sh

./start_humidity_temperature.sh

Now, you can monitor the humidity and temperature using Oracle IoT Cloud Service.

Resources:

Tweet about this on TwitterShare on Facebook0Share on LinkedIn25Share on Google+0

Author: Waslley Souza

Consultor Oracle com foco em tecnologias Oracle Fusion Middleware e SOA. Certificado Oracle WebCenter Portal, Oracle ADF e Java.

Leave a Reply

Your email address will not be published. Required fields are marked *