
¿Quieres aprender a montar una operación IoT en la nube totalmente administrada, con autoescalado y serverless?
En esta serie de tres entregas, IoT en GCP, recorremos un flujo de trabajo IoT completo: desde el registro de dispositivos hasta el streaming y el almacenamiento a largo plazo de los datos, junto con su análisis y visualización.
Mejores prácticas de IoT a escala productiva
Al terminar la Parte Uno, vas a saber cómo registrar de forma segura millones de dispositivos IoT que envían datos de telemetría a tu entorno de Google Cloud.
Esta es la primera de una serie de tres partes:
- El almacenamiento y la visualización de estos flujos de datos de alto throughput se cubren en la Parte Dos.
- La construcción de un modelo funcional de machine learning sobre datos IoT se cubre en la Parte Tres.
A lo largo de la serie usaremos GCP como proveedor de nube y dispositivos Raspberry Pi con sensores de temperatura como ejemplo de dispositivos IoT.
Panorama general
Esta guía se divide en las siguientes secciones:
- Configuración de software y hardware del Raspberry Pi
- Registro práctico de dispositivos y aprovisionamiento de credenciales
- Pruebas de conectividad y streaming de datos de temperatura
- Consideraciones sobre la funcionalidad de Google Cloud IoT
- Almacenamiento de datos en streaming (Parte Dos)
- Visualización de datos en streaming (Parte Dos)
- Construcción de un modelo eficaz de machine learning con datos IoT (Parte 3)
Para seguir este artículo solo necesitas experiencia con Bash y Python, además de un conocimiento básico de cómo moverte por la Google Cloud Console.
Configurar el software y el hardware del Raspberry Pi
Primero, pon en marcha varios Raspberry Pi: en mi caso usaré dispositivos Pi 3. Te recomiendo el Raspbian OS Imager para automatizar la instalación del SO en las tarjetas microSD.
Instalar los paquetes de Python
Una vez que llegues al escritorio y actualices el dispositivo, ejecuta el siguiente comando para instalar el SDK específico de Google Cloud IoT:
pip3 install -U pyjwt paho-mqttAntes de seguir, conviene entender por qué instalamos paho-mqtt en lugar del SDK de Python de propósito general google-api-python-client de Google Cloud. Tanto ese SDK de Python (el más común) como el CLI gcloud de GCP funcionan sobre HTTP. Ese protocolo es útil para ejecutar la mayoría de las acciones de forma rápida. Sin embargo, HTTP no es adecuado para enviar mensajes a través de conexiones de larga duración con alta probabilidad de conectividad intermitente, donde el tráfico de datos sale principalmente desde el dispositivo conectado.
MQTT es un protocolo usado en IoT, mediante paquetes como paho-mqtt, justamente porque está diseñado para que un dispositivo pueda publicar mensajes con frecuencia y recibirlos esporádicamente, incluso ante condiciones de conectividad complicadas.
Conectar un sensor de temperatura digital
Ahora que tu Raspberry Pi tiene los paquetes de Python necesarios, toca conectarle un sensor de temperatura digital. Te recomiendo este sensor DS18B20 si quieres seguir el artículo paso a paso.
También vas a necesitar lo siguiente para conectar el sensor al Raspberry Pi:
- Mini protoboards
- Cables jumper para protoboard
- Kit surtido de resistencias (necesitamos una de 4.7K Ohm)
Si tienes que esperar a que lleguen estos componentes, sigue avanzando con el artículo: más adelante encontrarás un script para enviar temperaturas simuladas en streaming.
Si ya tienes todo, los primeros cinco minutos de este tutorial te muestran cómo conectar el sensor al Raspberry Pi y verificar que recibe valores de temperatura.
Además del proceso del tutorial, te recomiendo agregar lo siguiente a /etc/modules para que los módulos onewire se carguen al arrancar y no tengas que ejecutar modprobe después de cada reinicio:
w1-gpiow1-thermRegistrar tus dispositivos IoT
A continuación verás un ejemplo completo y funcional de cómo configurar tu IoT Registry con dispositivos registrados de forma segura, desde los cuales enviaremos datos de temperatura en streaming a la plataforma Google Cloud IoT.
Crear un registro para tus dispositivos
En la Google Cloud Console:
- Crea un nuevo proyecto (por ejemplo, "IoTTempStreaming")
- Ve al servicio IoT Core para habilitar la API de IoT
- Haz clic en "Create registry" para crear un registro donde añadirás tus dispositivos IoT.
Los dispositivos IoT que envían datos en streaming a GCP solo pueden mandar mensajes al IoT Core si están validados como dispositivos con credenciales almacenadas en el IoT Registry, así que crear el registro es un primer paso esencial.
Un entorno IoT Core nuevo, listo para empezar a recibir mensajes
Crear un topic de Pub/Sub
Los mensajes que llegan al IoT Core —junto con metadatos críticos como el deviceId único del dispositivo— se reenvían internamente a un "topic" en Pub/Sub, el sistema de cola de mensajes totalmente administrado, con autoescalado y serverless de Google Cloud.
Por eso, también vamos a crear topics de Pub/Sub desde el propio asistente del IoT Registry, para que los datos de telemetría terminen llegando a Pub/Sub y puedan procesarse aguas abajo.
Sigue estos pasos para crear un topic de Pub/Sub desde el asistente del IoT registry:
- Llama a tu Registry ID "RaspberryPiDevices" en la región us-central1
- Crea un topic de Pub/Sub llamado "sensordata" donde llegarán por defecto los mensajes de telemetría IoT.
- En "Additional topics", crea un nuevo topic de Pub/Sub llamado "temperature", al que llegarán los mensajes publicados en una subcarpeta de topic IoT —también llamada "temperature".
Con esta configuración se garantiza que solo los mensajes de temperatura publicados en una subcarpeta IoT específica lleguen al topic temperature de Pub/Sub, mientras que el resto de eventos de telemetría (inesperados) caen en el topic "sensordata" por defecto.
También te recomendaría desplegar las opciones avanzadas y permitir únicamente el protocolo MQTT, desmarcando HTTP:
Configuración del IoT Core Registry para el streaming de datos del sensor de temperatura
Una vez creado, tu registro debería verse así:
Una configuración correcta del IoT Core Registry
Crear un dispositivo registrado
Ya que tenemos un registro de dispositivos, vamos a crear uno registrado.
Para empezar, vamos a necesitar (1) un par de claves pública-privada asociado al dispositivo y (2) el certificado raíz de Google.
Abajo se detallan los comandos a ejecutar en un Raspberry Pi para generar claves de Curva Elíptica y obtener el certificado raíz de Google (los comandos se basan en la documentación correspondiente de Google Cloud). Las claves EC ocupan menos espacio que las claves RSA tradicionales y ayudan a que los dispositivos IoT mantengan un throughput óptimo en zonas con conectividad limitada:
$ mkdir -p /home/pi/GCP/iot_keys/$ cd /home/pi/GCP/iot_keys/$ wget$ openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem$ openssl ec -in ec_private.pem -pubout -out ec_public.pem$ cat ec_public.pem$ cd ../Una vez ejecutados los comandos anteriores:
- Copia la clave pública mostrada en la terminal
- Ve al IoT Registry y entra a Devices
- Haz clic en Add Device
- Ponle un nombre al dispositivo (por ejemplo, "device1") y pega tu clave pública ES256 en Authentication, como se muestra abajo.
- Haz clic en Create
Registro de dispositivo IoT solicitando una clave de Curva Elíptica
Una vez creadas, las credenciales asociadas al dispositivo registrado en IoT Core ya están listas para usarse en un Raspberry Pi.
Anota el Numeric ID asignado al dispositivo, el Project ID y el Registry ID.
Con esos valores, junto con las claves y el certificado raíz de Google ya en el dispositivo, hay que crear un archivo de configuración llamado gcp_iot_config.txt. Este archivo define los detalles de autenticación y del endpoint IoT que usará un dispositivo concreto. Más adelante en el artículo se describe un script de Python que envía valores de temperatura en streaming aprovechando este archivo de configuración:
$ pwd/home/pi/GCP/$ cat gcp_iot_config.txt[SETTINGS]KEY_PATH = /home/pi/GCP/iot_keys/PRIVATE_KEY = ec_private.pemGOOGLE_ROOT_CERT = roots.pemREGISTRY_ID = <REGISTRY_ID>DEVICE_ID = <DEVICE_NUMERIC_ID>REGION = us-central1PROJECT_ID = <PROJECT_ID>¡Y listo! Tu dispositivo ya puede enviar de forma segura datos de telemetría en streaming a un topic de Pub/Sub mediante la plataforma de autenticación IoT Core de GCP. Repite el proceso para generar credenciales únicas y registrar cada nuevo dispositivo.
Probar la conectividad del dispositivo
Vamos a probar la conectividad del dispositivo ejecutando el siguiente script, llamado "publish_temps.py", que envía valores de temperatura reales del dispositivo o simulados, según tengas comentada la línea 107 o la 108.
(El script es una adaptación de dos scripts de ejemplo de Google Cloud: #1 y #2)
$ pwd/home/pi/GCP/$ ./publish_temps.pyhttps://gist.github.com/doit-mattporter/7e548158a5dc03b3674282cda19ef663
Aquí pasan bastantes cosas: te recomiendo encarecidamente revisar el código para entender mejor cómo se conecta y cómo envía los datos en streaming de forma segura.
Al ejecutar el script, deberías ver una salida parecida a esta:
Valores reales de temperatura llegando en streaming a GCP IoT Core mediante MQTT
Si lanzas el script al reiniciar mediante una tarea crontab (precedida por un sleep de 30 s para dar tiempo a que los módulos onewire se carguen al arrancar), tu dispositivo IoT retomará el streaming ante cualquier reinicio (in)esperado:
$ crontab -e@reboot sleep 30 && /home/pi/GCP/publish_temps.py -c /home/pi/GCP/gcp_iot_config.txt >> /home/pi/GCP/publish_temps.log 2>&1Repite los procesos de onboarding y streaming en todos los Raspberry Pi distribuidos por tu casa. ¡Vas por muy buen camino para trabajar con datos IoT a escala!
Verificar que los datos están llegando en streaming
Comprobemos rápidamente que los mensajes llegan a Google Cloud, revisando los datos de telemetría en Pub/Sub.
- Crea una suscripción de Pub/Sub al topic "temperature"
- Entra a la suscripción
- Haz clic en View Messages y selecciona el botón de radio Pull
Vas a ver los mensajes a medida que llegan, con la información de temperatura y el timestamp en el cuerpo del mensaje, además de los metadatos de atributos que identifican de manera única qué dispositivo está enviando esos valores. Estos metadatos no solo sirven para analítica y dashboards de usuario final, sino también para identificar y bloquear dispositivos abusivos o hackeados.
Creación de una suscripción de Pub/Sub para visualizar los mensajes de telemetría de temperatura entrantes
Así se ve una suscripción al topic temperature:
Visualización de mensajes en una suscripción de Pub/Sub al topic "temperature"
Al hacer clic en "PULL", deberías empezar a ver los mensajes y sus atributos:
Datos de temperatura llegando a un topic de Pub/Sub y a una suscripción de Pub/Sub: cuerpo del mensaje
Datos de temperatura llegando a un topic de Pub/Sub y a una suscripción de Pub/Sub: atributos identificadores únicos
Si llegaste hasta acá, ¡felicitaciones (en serio)! Aunque emociona ver datos reales de dispositivos IoT llegando a Pub/Sub, esto es apenas la punta del iceberg.
Para sacarle partido real a estos datos hay que transformarlos (de forma opcional), moverlos o cargarlos por lotes a un data warehouse y analizarlos. Todo eso debe ocurrir sobre un ecosistema de servicios de GCP que mantenga este flujo confiable, escalable y rentable en cada etapa del desarrollo, desde las pruebas iniciales hasta el uso en producción a escala de petabytes y más allá, con poco o ningún mantenimiento de infraestructura. Si quieres ver cómo se hace, no te pierdas las partes dos y tres.
Lo que viene: almacenamiento y visualización
No te pierdas la parte dos, donde hablaré de los servicios de ETL, almacenamiento y visualización adecuados que permiten, de forma relativamente sencilla, sacarle provecho real a datos IoT en streaming a gran escala.
Consideraciones sobre la funcionalidad de Google Cloud IoT
Mejor manejo del deviceId por parte de los servicios totalmente administrados de GCP
Quizás notaste que el script de Python envía un par clave:valor device_id en el cuerpo del mensaje, lo cual de hecho duplica el atributo deviceId presente en el mensaje de Pub/Sub, asignado por IoT Core a partir de la asociación del mensaje con el par clave-valor único del dispositivo emisor.
¿Por qué hacer que el script envíe un device_id que podría falsificarse fácilmente desde un dispositivo hackeado y terminar contaminando un data warehouse cuando estos mensajes pasen al almacenamiento a largo plazo?
Bueno, me estoy adelantando un poco, pero como veremos en la Parte Dos existe un flujo de trabajo cómodo, totalmente administrado, con autoescalado y mayormente serverless, que puede transformar y mover los mensajes de Pub/Sub a BigQuery usando Dataflow, la versión totalmente administrada de Apache Beam de Google Cloud.
Por desgracia, la plantilla "Pub/Sub-to-BigQuery" que GCP trae por defecto en Dataflow no permite mover los atributos del mensaje a BigQuery; solo se puede mover el contenido del cuerpo. Confirmé con varios ingenieros de GCP que tampoco se puede escribir una UDF de JavaScript personalizada para sus plantillas por defecto que añada los atributos del mensaje a sinks de Dataflow como BigQuery. La alternativa, escribir jobs de Dataflow en Java —desde cero o modificando las plantillas existentes de GCP—, requiere mucho tiempo y un mantenimiento continuo de la plantilla, algo que sospecho que la mayoría de clientes de GCP preferirá no asumir.
Por lo tanto, por defecto, no hay una forma simple y segura de asociar un mensaje IoT que llega a Pub/Sub y se reenvía a sinks de datos de destino con el deviceId de ese mensaje.
He planteado esta carencia a GCP y, desde entonces, abrieron una solicitud pública de funcionalidad para que las plantillas por defecto soporten el reenvío de estos valores —tan útiles como imprescindibles— para el caso de uso IoT. Actualizaré el artículo en cuanto se cumpla esa FR, pero hasta entonces, con fines de demostración, es mucho más sencillo probar el uso de device_id enviándolo en el cuerpo del mensaje que reescribir una plantilla de Dataflow que debería existir por defecto.
¿Cómo aprovisionaría idealmente credenciales únicas por dispositivo?
El proceso para registrar un único dispositivo IoT suele explicarse así:
- Crear un par de claves pública-privada asociado en GCP con permisos de IoT
- Aprovisionar y colocar estos archivos en el dispositivo durante la fabricación
- Hacer que la fábrica registre esas credenciales en el IoT Registry
- Habilitar el par de claves para realizar llamadas a la API de IoT que envíen datos en streaming a la nube.
Sin embargo, una configuración así, por sí sola, no es ideal: en el mundo real los casos de uso IoT involucran millones de dispositivos enviando datos en streaming a un entorno cloud. Cada dispositivo de una flota así debe tener un conjunto único de credenciales, de modo que si un dispositivo o sus credenciales de Google Cloud se ven comprometidos y se usan con fines ilegítimos, ese conjunto pueda deshabilitarse sin afectar al resto de la flota.
GCP ofrece esa funcionalidad y, como se vio en el script anterior, también permite restringir un dispositivo para que solo pueda publicar en un topic propio. Pero, dadas las metodologías disponibles para aprovisionar credenciales, coordinar la creación, el despliegue y el registro de claves para millones de dispositivos es todo un reto.
¿Cómo se puede simplificar al máximo la creación de credenciales específicas por dispositivo? ¿Se puede hacer sin generar millones de certificados por adelantado y coordinar su colocación única en cada dispositivo durante la fabricación? ¿Realmente quieres depender de un fabricante para que coloque estos archivos sin errores ni duplicaciones?
O bien, ¿se puede registrar y credencializar dispositivos sin que el fabricante tenga que llamar a la API de tu IoT Registry para crear nuevas credenciales bajo demanda cada vez que un dispositivo sale de la línea de producción para arrancarse con software y credenciales? ¿Qué pasa con la línea de producción si se cae la conexión con el API Gateway que da soporte al registro IoT?
Yo preferiría evitar estos métodos porque son más complejos, propensos a errores y suponen una carga innecesaria para el fabricante.
Un sistema seguro y razonablemente escalable de registro de dispositivos que me gustaría ver en GCP seguiría estas pautas:
- Se crea un único certificado IoT que se colocará en todos los dispositivos IoT. Ese certificado, llamado certificado "bootstrap", estaría asociado a una política de permisos que solo permite al dispositivo emitir una solicitud para (a) crear y obtener credenciales específicas del dispositivo si la solicitud se aprueba, y (b) añadirse al IoT Registry de dispositivos.
- La plataforma GCP IoT Core, al recibir y aprobar la solicitud de creación de credenciales, generaría un nuevo par de claves. Los permisos IoT asociados —como ya hace Google Cloud hoy— solo deberían permitir que el dispositivo publique mensajes en un topic propio.
- La autorización para crear credenciales únicas por dispositivo debería estar condicionada a un paso de validación. Sería una Cloud Function que tú mismo escribes y que exige que la solicitud incluya identificadores únicos para contrastarlos contra una whitelist (por ejemplo, una lista de números de serie fabricados o direcciones MAC usadas) o una blacklist (por ejemplo, números de serie asociados a dispositivos comprometidos, abusivos o ya registrados).
- Si el paso de validación aprueba la solicitud del certificado único por dispositivo, este se incorpora al IoT Registry y los nuevos archivos de credenciales se entregan al dispositivo para que los use en el streaming de datos.
Con este flujo, el fabricante de dispositivos IoT solo tendría que dotar a cada dispositivo del certificado bootstrap. El par de claves único por dispositivo que habilita el streaming podría crearse y obtenerse en el momento dentro de la planta de fabricación, si así se quiere, o más adelante, ya en manos del usuario final.
Sin importar cuándo se obtengan las credenciales, el fabricante simplemente cargaría en el dispositivo el software bootstrap que tú proporcionas, el cual ejecuta el proceso de creación del par de claves único basado en el certificado bootstrap cuando:
- El dispositivo arranca
- Hay conexión a Internet disponible, y
- Se detecta que falta el par de claves único del dispositivo
Lamentablemente, esa funcionalidad aún no existe. Pero, dejando de lado el registro masivo de dispositivos, la oferta de IoT de Google Cloud —combinada con servicios totalmente administrados de procesamiento de mensajes aguas abajo (Parte Dos)— constituye en conjunto una solución sólida, segura y fácilmente escalable respaldada por la nube en el ámbito IoT.