Vamos a ver cómo conectar el microcontrolador ESP32 a la nube de Google (Google Cloud Platform). Para ello utilizaremos datos en streaming (tiempo real) generados por el sensor DHT11, tanto de temperatura como de humedad ambiental.
Hay seis grandes pasos que realizar para conectar nuestro dispositivo a la nube:
1. Montar el pack sensor DHT11 y placa ESP32.
2. Crear un proyecto en la plataforma de Google Cloud.
3. Generar las private y public keys.
4. Activar Pub/Sup, crear tema (topic) y suscripción.
5. Habilitar el Cloud IoT Core.
6. Conectar el ESP32 al Cloud IoT Core
1. Montar El Pack Sensor DHT11 Y Placa ESP32
Para ello colocaremos el DHT11 (en mi caso con la resistencia incorporada) sobre el BreadBoard. El pin de la izquierda va conectado a GND, el pin del centro (datos) al pin 4 de la placa y el pin de la derecha al pin de 5V del microcontrolador ESP32 (porque el DHT11 opera con entre 3 y 5V).

Más información en el post previo:
https://www.juanjobeunza.com/esp32-dht11/
2. Crear un proyecto en la plataforma de Google Cloud
Entraremos a la plataforma de la nube de Google "https://cloud.google.com/" y le daremos a "Empezar gratis" (si es la primera vez que entramos) o a "Acceder" / "Ir a la consola" (suponiendo que ya estamos registrados y dados de alta).
Primero el usuario:

Luego la contraseña...


Haremos click en "Ir a la consola".

Ya estamos en el panel de control de la Consola de Google Cloud. Abrimos el botón "Hamburguesa" situado arriba a la izquierda (el botón que nos permite acceder a todas las funcionalidades de Google), "IAM y administración" y finalmente "Administrar recursos".

Le damos a "Crear proyecto":

Solo nos queda rellenar el nombre del proyecto y darle a "Crear". Con él, Google creará el ID del proyecto, el verdadero identificador de nuestro proyecto (comienza con nuestro nombre del proyecto y terminado en un número que asigna Google). Si refrescamos la página de "Gestionar recursos" podremos ver nuestro proyecto nuevo. Si volvemos al panel de control de la nube (haciendo click sobre "Google Cloud Platform" arriba a la izda, junto a la hamburguesa), veremos que a la derecha de "Google Cloud Platform" nos sale nuestro nuevo proyecto, y un desplegable con todos los proyectos que hayamos creado para que podamos movernos de un proyecto a otro con facilidad.
3. Certificado raiz y claves pública y privada
Antes de crear el registro y el dispositivo en IoT Core de la nube de Google, vamos a crearlas claves necesarias para que nuestro dispositivo pueda comunicarse con seguridad con la nube. Necesitaremos esa información para dar de alta a nuestro dispositivo en el registro de Google. De esta manera, todos los datos que enviemos por internet irán encriptados con un sistema "Clave Pública/Clave Privada", un sistema de altísima seguridad que domina la comunicación por internet, solo amenazada por los incipientes ordenadores cuánticos (tema para otra Entrada o post).
Para crear las claves (keys), abriremos el Terminal de nuestro ordenador e introduciremos el siguiente código:
openssl ecparam -genkey -name prime256v1 -noout -out esp32-device.pem
openssl ec -in esp32-device.pem -pubout -out esp32-device-public.pem
Hemos creado en nuestra carpeta de ejecución del terminal dos archivos con las claves (pública y privada), que quedan almacenados en los archivos esp32-device.pem (para la clave privada) y esp32-device-public (para la clave privada). También hemos creado el certificado raiz (roots) que veremos más adelante cómo recuperarlo.
Necesitaremos la clave pública en texto y la clave privada en formato hexadecimal. Veamos como obtener esa información con sencillez. Abrimos un Terminal de nuestro ordenador.
1. Public Key en formato Texto para registrar nuestro dispositivo en la nube de Google. Para visualizarla, tecleamos:
cat esp32-device-public.pem
Obtendremos la siguiente salida, con la clave (key) pública:
-----BEGIN PUBLIC KEY-----KRfsKkfkDJFkjfdkjKJDKkFJDKjfijdkj878&/(jikKLJDfkjkjlasdkjdfUyuY787(IFJijkjfi&%&&%hjsdfjhdj
-----END PUBLIC KEY-----
Si quisiéramos visualizar la private key en este mismo formato podríamos teclear "cat esp32-device.pem" pero esta no es una información que necesitemos para este ejercicio.
2. Private Key en formato hexadecimal para el archivo ciotc_config.h del IDE de Arduino.
En el mismo terminal, vamos a teclear:
openssl ec -in esp32-device.pem -noout -text
Obtendremos la clave privada en código hexadecimal. Algo parecido a esto:
read EC key
Private-Key: (256 bit)
priv:
ja:6d:ff:39:ja:dd:37:ja:01:df:1d:6e:be:62:d8:
18:c7:ja:56:88:f8:ja:e1:df:ae:ja:d6:b1:ja:ba:
ja:b8
No olvidemos que tanto Word de Office como el NotePad o editor de texto suele alterar los caracteres: comillas, líneas horizontales, etc... Tenerlo en cuenta porque es una frecuente causa de errores.
Nota (mis claves las he modificado para el post, lógicamente).
3. Por último, necesitaremos descargar el Certificado Raíz. Para ello, vamos a introducir la siguiente URL en un navegador:
https://pki.goog/roots.pem
Esto nos va a descargar el certificado, con el nombre roots.cer. Lo podemos guardar en la carpeta Certificados que hemos creado para las Keys. Lo editamos (por ejemplo con Microsoft Word) y de ahí podemos extraer los dos primeros certificados. Cada uno de ellos tendrá el siguiente formato:
-----BEGIN CERTIFICATE-----
JajajajajdzCCAl+gAwIBAgIEAgjajajajBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
VQQDExlCYWx0aW1vcmUjajajajajaVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
ZTETMBEGA1UEjajajajajaXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
IZ3AQSsBUnuIjajajajai1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
dc93Uk3zyZAsuTjajajajax8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
BE3wMBIGA1UdjajajajaQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
9hkTI7gQCvlYpNRhcL0EYWoSihfVCjajajaja1ukMJY2GQE/szKN+OMY3EU/t3Wgx
jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
Epn3o0WC4zxe9Z2etciefC7IpJ5jajajajajajajaWsaY71k5h+3zvDyny67G7fyUIhz
ksLi4xaNmjICq44Y3ekQEe5+NjajajajawlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
R9I4LtD+gdwyah617jzV/OjajajanDJELqJajaja
-----END CERTIFICATE-----
Luego iremos viendo dónde pegar estos tres datos: la public key (texto), la private key (hexadecimal) y los dos certificados raíz.
La carpeta ha quedado así:

4. Activar Pub/Sub, crear Tema (topic) y Subscripción
Pub/Sub es la herramientas de comunicación con el exterior de la nube de Google. Cuenta con una importante misión de Buffer que permite retener los mensajes mientras los dispositivos de recepción están ocupados o no receptivos.
Lo primero que hay que hacer es abrir Pub/Sub haciendo click en la Hamburguesa y en Pub/Sub (lo encontrarás muy abajo, dentro del apartado BigData).
Para crear un tema nuevo vamos a hacer click en Crear Tema, introducimos el ID del tema (en mi caso Humedad), dejamos que el Encriptado lo gestione Google (no tocamos nada de eso) y daremos a CREAR TEMA:

Ahora vamos a crear una suscripción a ese tema. Es decir, una herramienta para poder recibir la información que se publique en ese tema. Así podremos comprobar que la información enviada por nuestro sensor le ha llegado a la nube.
Para crear la suscripción haremos click en el listado debajo de Pub/Sub, en Suscripciones y en Crear suscripción:
- ID de suscripción: Juanjo_humedad.
- Selecciona un tema de Cloud Pub/Sub:
projects/iot-gcp-281413/topics/Humedad
Y le damos a CREATE abajo del todo.

Con esto ya tenemos el tema y la suscripción preparados.
Si hacemos click en el menú Hamburguesa y seleccionamos Pub/Sub. Veremos que ya tenemos un Tema creado con ID del tema: Huemedad y con un Nombre del tema: projects/iot-gpc-281413/topics/Humedad. Si recordamos lo dicho hasta ahora, corresponde al proyecto iot-gpc (al que Google ha añadido el número 281815 para identificarlo; en vuestro caso el número será distinto), con el tema Humedad. Hasta ahora todo lógico y sencillo.
5. Habilitar el Cloud IoT Core
Hacemos click sobre la "Hamburguesa" e "IoT Core" (dentro del apartado BigData, muy abajo en el listado). Vemos lo siguiente, y hacemos click en "Habilitar".
Nota: los siguientes dos pantallazos corresponden a otro proyecto (IoT2), distinto del proyecto anterior, IoT-GCP. En vuestro caso debería seguir apareciendo el proyecto original. Para que nadie se confunda.

Una vez habilitado el IoT Core tenemos que dar de alta a los registros. Un registro es un conjunto homogéneo de dispositivos que se agrupan juntos de manera lógica, por ejemplo todos los sensores que reciben información de un paciente, o todos los sensores que gestiona un solo médico, o los sensores de las habitaciones del ala izquierda de la planta 3ª de un hospital. Esto depende de cómo se organice la arquitectura del sistema. Le damos a CREAR REGISTRO:

Y ahora introducimos:
- El ID de registro: en mi caso "Humedad_Carabanchel".
- La región: en mi caso "europe-west1". En general se recomienda que esté lo más cerca posible a tu lugar de gestión de datos para evitar latencias prolongadas y problemas de conexión.
- En el Tema de Pub/Sub ponemos: Humedad
(projects/iot-gcp-281413/topics/Humedad). Y CREAR.

Si no tuvieramos el Tema creado, lo podríamos crear desde aquí mismo... pongo un par de pantallazos (con otros nombres distintos y con el proyecto IoT2), pero en nuestro caso no hace falta hacer nada más de Pub/Sub.


Volviendo a nuestro caso, ya tenemos el ID de registro: Humedad_Carabanchel con el protocolo MQTT o HTTP, con el tema de Cloud Pub/Sub "projects/iot-gcp-281413/topics/Humedad.
Para añadir el primer dispositivo, abriremos el registro ya creado, veremos a la izquierda, bajo IoT Core, cuatro pestañas. La primera "Detalles del registro", la segunda "Dispositivos". Le damos a "Dispositivos" y a crear dispositivo. Introducimos:
- ID de dispositivo: ESP_DHT11_1 (en mi caso)
- Desplegamos COMMUNICATION, CLOUD LOGGING, AUTHENTICATION (****esto es muy importante)

Aquí pondremos el Formato de clave pública en ES256 (el formato que hemos usado en la creación de la misma) y pegaremos la Clave Pública (PUBLIC KEY) tal y como sale en la foto:

Con esto ya tenemos el IoT Core activado, con un Registro (Humedad_Carabanchel), un dispositivo (ESP32_DHT11_1) asociado a dicho registro y una public key para que la comunicación sea cifrada.

6. Conectando el ESP32 al IoT Core de Google
Usaremos el puente MQTT. Para ello necesitaremos un cliente MQTT para el ESP32 y poder generar JWT con llave privada (private key).
Vamos a operar en el IDE de Arduino. Lo primero que haremos será instalar las librerías:
- Google cloud IoT Core JWT por Vladimir Korukov
- Arduino mqtt por Joel Gaehwiler
Podemos instalar ambas librerías directamente del IDE de Arduino.


Ahora, nos bajamos el código de Arduino con los 3 archivos del siguiente repositorio y los metemos en una carpeta llamada ESP32-DHT11-GCP y situada dentro de la carpeta Arduino (donde apunta nuestro IDE de Arduino.:
- ESP32_DHT11_GCP.ino
- ciotc_config.h
- esp32-mqtt.h
Debería quedar así:

Ahora vamos a introducir la información personal en el archivo ciotc_config.h. Lo abrimos con el IDE de Arduino y modificamos la información que aparece en los recuadros rojos:

En el primer recuadro:
- El ssid de nuestra red wifi.
- El password de nuestra red wifi.
- El identificador de nuestro proyecto de Google.
- La localización geográfica de nuestro registro en Google.
- El identificador del registro de Google
- El identificador del dispositivo en Google.
De esta manera el programa compilado y subido al ESP32 sabrá cómo conectarse a Wifi y a dónde apuntar la información que va a enviar (proyecto, zona geográfica, registro y dispositivo registrado en la nube de Google). En mi caso quedó así:

Por último, hay que introducir la clave privada (private-key) en código hexadecimal. Lo más sencillo es ejecutar el siguiente código en nuestro Terminal:
openssl ec -in esp32-device.pem -noout -text
Y copiar pegar el código sobre el presente en el archivo ciotc_config.h original. Debe quedar exáctamente igual, esto es, con la misma longitud, comenzando y terminando cada línea con comillas, y con punto y coma al final de la key. Si utilizas un editor de texto recuerda que quizás te altere los caracteres (las comillas, por ejemplo). Aconsejo que modifiques el texto en el mismo archivo ciotc_config.h y copies pegues esos caracteres para evitar errores.
Y por fin, conecta el pack ESP32-DHT11 al puerto USB, sube el programa y cruza los dedos 🙂
En mi caso tuve que resetear (botón negro pequeño en la placa) un par de veces la placa para que se conecte bien a Wifi.
Mi monitor serie (a 115200 baudio) refleja lo siguiente:

En la flecha puedes ver una subida súbita pero transitoria de la humedad ambiental.
Y en la nube de Google vemos la misma subida. Para visualizar los datos, debes abrir Pub/Sub - Suscripciones - Ver Mensajes - Extraer (no te sorprendas de encontrar un lag de unos 15 segundos desde que tu sensor emita la señal y la visualizas en el Monitor Serie de Arduino IDE hasta que la puedes extraer en la nube de Google):

Y el resumen de la actividad:

Adjunto debajo cómo quedó el código del archivo ESP32_DHT11_GCP.ino:
// The MQTT callback function for commands and configuration updates
// Place your message handler code here.
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
#include "DHT.h"
#include "esp32-mqtt.h"
#define PUBLISH_DELAY 5000 // Publicará 1 vez cada 5 segundos
#define DHTPIN 4 // Pin a usar en la ESP32
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
unsigned long lastMillis = 0;
void setup() {
Serial.begin(115200);
dht.begin();
setupCloudIoT();
}
void loop() {
delay(500); // Intento ajustar num mediciones y num publicaciones
mqttClient->loop();
delay(10); // <- fixes some issues with WiFi stability
if (!mqttClient->connected()) {
connect();
}
// publish a message roughly every PUBLISH_DELAY ms.
if (millis() - lastMillis > PUBLISH_DELAY) {
lastMillis = millis();
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
Serial.print("Temp: ");
Serial.print(temperature);
Serial.print(" Humedad:");
Serial.println(humidity);
String payload = String("{"timestamp":") + time(nullptr) +
String(","temperature":") + temperature +
String(","humidity":") + humidity +
String("}");
publishTelemetry(payload);
}
}
NOTA: Si copias/pegas el código tal cual, asegúrate que no te cambia las comillas verticales tradicionales en el original por comillas tipo corchete «» o cualquier otro símbolo. Algunos lectores nos han informado de ese problema.
Fuentes de información para la realización de esta Entrada:
- https://github.com/Nilhcem/esp32-cloud-iot-core-k8s
- http://nilhcem.com/iot/cloud-iot-core-with-the-esp32-and-arduino
- https://www.survivingwithandroid.com/cloud-iot-core-esp32/