Enviar dados do Raspberry Pi para o Oracle IoT Cloud Service

Hoje estamos experimentando a transformação causada pela Internet das coisas (IoT) e é comum ver projetos simples de IoT, como monitoramento de umidade e temperatura ou projetos complexos, como carros conectados. Os projetos mais simples estão usando plataformas de baixo custo como Arduino ou Raspberry Pi e qualquer um pode iniciar seu próprio projeto IoT com facilidade.

Neste post, aprenderemos como enviar dados de umidade e temperatura do Raspberry Pi para o Oracle Internet of Things Cloud Service.
Vou usar meu Raspberry Pi 3 Model B e um sensor DHT11.

Para este projeto, usarei a linguagem C e o C Posix SDK fornecido pela Oracle, mas você tem outras opções de linguagem de programação.

Vá para a sua instância do Iot Cloud Service e crie uma nova aplicação. Nomeie-o como “Humidity and Temperature” e clique no botão Create.

Clique no aplicativo “Humidity and Temperature” e crie um novo Device Model. Nomeie-o como “Humidity and Temperature Sensor” e configure a URN como “urn:com:oracle:iot:device:humidity_temperature”.

Adicione dois Custom Attributes, humidity e temperature.
Defina ambos os atributos como tipo Number.

Clique no botão Save.
Vá para a página Registration e clique no botão Register Single Device.

Preencha o formulário e clique no botão Register.

Para gerar o arquivo de provisionamento do dispositivo, especifique uma senha e clique no botão Download Provisioning File.

Faça login no seu Raspberry Pi e execute o seguinte comando:

sudo apt-get install libssl-dev -y

Neste momento, a última versão do C POSIX Client Software Library é 17.2.5.0.0-5, mas recomendo que você verifique a versão atual aqui: Oracle IoT Cloud Service Client Software Library downloads page.
Execute o seguinte comando para criar uma nova pasta “iotcs-cposix” e baixe o arquivo binário 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 o seguinte comando para extrair o conteúdo do arquivo iotcs-csl-posix-bin-17.2.5.0.0-5.zip.

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

No diretório bin (/home/pi/iotcs-cposix/iotcs/csl/posix/bin), crie um novo arquivo humidity_temperature.c e use o seguinte código:

/*
 * 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 os seguintes comandos para instalar a biblioteca GPIO:

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

cd wiringPi

sudo ./build

Compile o programa C.

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

Copie o arquivo de provisionamento que foi baixado quando você registrou o dispositivo, nesse diretório.

Crie um novo arquivo start_humidity_temperature.sh e use o seguinte código: (Nota: File_Protection_Password é o mesmo que você usou no Oracle IoT Cloud Service para baixar o arquivo de provisionamento.)

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 o seguinte comando para iniciar o programa C:

chmod +x start_humidity_temperature.sh

./start_humidity_temperature.sh

Agora, você pode monitorar a umidade e a temperatura usando o Oracle IoT Cloud Service.

Fontes:

Waslley Souza

Autor: Waslley Souza

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

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *