Send data from Raspberry Pi to Oracle IoT Cloud Service

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 Zero W 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 libssl1.0-dev -y

At this moment the last version of C POSIX Client Software Library is 18.1.5.0.0-18, 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-c-posix-bin-18.1.5.0.0-18.zip

Execute the following command to extract the content of the iotcs-csl-c-posix-bin-18.1.5.0.0-18.zip file.

unzip iotcs-csl-c-posix-bin-18.1.5.0.0-18.zip

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

#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(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(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_create_virtual_device_handle(iotcs_get_endpoint_id(), device_model_handle, &device_handle) != IOTCS_RESULT_OK) {
    printf("iotcs_create_virtual_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 -liotdeviceclient -Wl,-Bdynamic -lssl -lcrypto -lm -lrt -lpthread -lwiringPi -ldl

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 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:

Author: Waslley Souza

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

5 thoughts on “Send data from Raspberry Pi to Oracle IoT Cloud Service”

  1. Hello,

    Thanks for this tutorial. I have been working on the same project with the same configuration you have. I am working with a Mashreq Arabia firm and we are Oracle partners. And it was great find someone reached to a solution. I have been searching and working for two months. But following your way there is some issues I face while compiling using gcc. it says
    ” /usr/bin/ld: cannot find -ldeviceclient
    collect2: error: ld returned 1 exit status

    I have tried to search for solutions but this file is not at anywhere except Oracle and there is no details about those options. So can you help me please.

    1. Hi Ahmed! The “deviceclient” file was removed, now you have to use “iotdeviceclient” file.
      Use this new command: gcc -g -I../include -I../lib/arm -o ./humidity_temperature.out ./humidity_temperature.c -Wl,-Bstatic -L../lib/arm -liotdeviceclient -Wl,-Bdynamic -lssl -lcrypto -lm -lrt -lpthread -lwiringPi

      1. Hi Waslley, 🙂

        Thanks for your fast replay and. I didn’t check here. I have tried your new command but unfortunately. I have stumbled into new error which is.

        /usr/bin/ld: ../lib/arm/libiotdeviceclient.a(sqlite3.o): undefined reference to symbol ‘dlsym@@GLIBC_2.4’
        //lib/arm-linux-gnueabihf/libdl.so.2: error adding symbols: DSO missing from command line
        collect2: error: ld returned 1 exit status

        I really don’t get this error. This is my first trial on the IoT CS. Waiting for your reply
        Thanks.

        1. Hello,

          I have researched for the above error and reached a fix. the fix was to add -ldl when compiling so the new compiling line is:
          ” gcc -g -I../include -I../lib/arm -o ./humidity_temperature.out ./humidity_temperature.c -ldl -Wl,-Bstatic -L../lib/arm -liotdeviceclient -Wl,-Bdynamic -lssl -lcrypto -lm -lrt -lpthread -lwiringPi ”
          I have tried it but an error showed and this time I don’t get where is the problem. the error is
          ” /tmp/ccVQ1e6I.o: In function `finalize_library’:
          /home/pi/iotcs-cposix/iotcs/csl/posix/bin/./humidity_temperature.c:50: undefined reference to `iotcs_free_device_model_handle’
          /tmp/ccVQ1e6I.o: In function `main’:
          /home/pi/iotcs-cposix/iotcs/csl/posix/bin/./humidity_temperature.c:167: undefined reference to `iotcs_get_device_model_handle’
          /home/pi/iotcs-cposix/iotcs/csl/posix/bin/./humidity_temperature.c:173: undefined reference to `iotcs_get_virtual_device_handle’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_crypto.o): In function `iotcs_port_crypto_init’:
          iotcs_port_crypto.c:(.text+0x230): undefined reference to `OPENSSL_add_all_algorithms_noconf’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_crypto.o): In function `iotcs_port_crypto_finalize’:
          iotcs_port_crypto.c:(.text+0x248): undefined reference to `EVP_cleanup’
          iotcs_port_crypto.c:(.text+0x24c): undefined reference to `CRYPTO_cleanup_all_ex_data’
          iotcs_port_crypto.c:(.text+0x254): undefined reference to `ERR_free_strings’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_ssl.o): In function `ssl_init_locks’:
          iotcs_port_ssl.c:(.text+0xac): undefined reference to `CRYPTO_num_locks’
          iotcs_port_ssl.c:(.text+0x16c): undefined reference to `CRYPTO_num_locks’
          iotcs_port_ssl.c:(.text+0x18c): undefined reference to `CRYPTO_set_id_callback’
          iotcs_port_ssl.c:(.text+0x19c): undefined reference to `CRYPTO_set_locking_callback’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_ssl.o): In function `ssl_finit_locks’:
          iotcs_port_ssl.c:(.text+0x1f0): undefined reference to `CRYPTO_set_id_callback’
          iotcs_port_ssl.c:(.text+0x1f8): undefined reference to `CRYPTO_set_locking_callback’
          iotcs_port_ssl.c:(.text+0x238): undefined reference to `CRYPTO_num_locks’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_ssl.o): In function `iotcs_port_ssl_init’:
          iotcs_port_ssl.c:(.text+0x610): undefined reference to `SSL_library_init’
          iotcs_port_ssl.c:(.text+0x860): undefined reference to `SSLv23_client_method’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_ssl.o): In function `iotcs_port_ssl_finalize’:
          iotcs_port_ssl.c:(.text+0xb70): undefined reference to `sk_free’
          ../lib/arm/libiotdeviceclient.a(iotcs_hostname_verifier.o): In function `hostname_verifier_check_common_name’:
          iotcs_hostname_verifier.c:(.text+0x210): undefined reference to `sk_num’
          iotcs_hostname_verifier.c:(.text+0x238): undefined reference to `sk_value’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_tam.o): In function `iotcs_port_tam_decode_shared_secret’:
          iotcs_port_tam.c:(.text+0x6c8): undefined reference to `EVP_CIPHER_CTX_cleanup’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_tam.o): In function `iotcs_port_tam_check_file_signature’:
          iotcs_port_tam.c:(.text+0x764): undefined reference to `HMAC_CTX_init’
          iotcs_port_tam.c:(.text+0x82c): undefined reference to `HMAC_CTX_cleanup’
          ../lib/arm/libiotdeviceclient.a(iotcs_port_tam.o): In function `iotcs_port_tam_sign_with_private_key’:
          iotcs_port_tam.c:(.text+0x1cc0): undefined reference to `EVP_MD_CTX_init’
          iotcs_port_tam.c:(.text+0x1e70): undefined reference to `EVP_MD_CTX_cleanup’
          collect2: error: ld returned 1 exit status ”
          Thanks for your time and waiting for your reply.

          1. Ahmed, please read and execute the steps of my blog post again. I updated it with C POSIX Client Software Library 18.1.5.0.0-18. Now it is working again! =D

Leave a Reply

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