Hoy, os vamos a contar sobre el Azure IoT Hub y SDK de Azure para Python
1. Introducción
El propósito es investigar sobre la extracción de datos de un sistema SCADA en el que los dispositivos IoT recolectan información en tiempo real, todo ello mediante el uso de Microsoft Azure. Como no disponemos de dicho sistema SCADA físicamente, se utiliza el SDK de Azure IoT para Python con la finalidad de simular los datos de los sensores. Nos han ayudado nuestros amigos de Stratebi. Gracias!!
2. Entorno de azure
En este apartado vamos a levantar el entorno de Azure necesario para recoger los datos de los sensores y procesarlos para enviarlos a una base de datos en Azure, en este caso, Azure CosmosDB.
Primero de todo, necesitamos crear un recurso llamado Azure IoT Hub, que será el encargado de comunicarse con los dispositivos IoT (sensores). Como veremos esta comunicación es bidireccional, es decir, los dispositivos se podrán conectar al IoT Hub para enviar la telemetría, así como al contrario, el IoT Hub podrá enviar mensajes a los propios dispositivos. Esta última nos interesa sobre todo si en la red de dispositivos IoT existe algún tipo de backend capaz de manejar los dispositivos pues, en este caso, podremos enviar mensajes específicos desde el centro de control (IoT Hub) demandando que cierto dispositivo o incluso todos se actualicen o se reinicien.
Vamos a levantar el recurso de Azure IoT Hub, para ello nos vamos a Create a Resource, buscamos IoT Hub y lo seleccionamos:
Ahora pulsamos Create:
Y rellenamos los campos que nos piden, seleccionando un nombre para nuestro IoT Hub. Una vez terminado, pulsamos Review + Create:
Y otra vez pulsamos Create:
En este momento nuestro IoT Hub estará en proceso de creación, así que esperamos hasta que nos aparezca un mensaje de este tipo, que indicará que se ha creado correctamente:
Ahora vamos a crear un dispositivo de IoT en el Azure IoT Hub. Este dispositivo en sí es un objeto virtual que utiliza Azure, aunque apuntará a un dispositivo real del sistema SCADA por ejemplo. Para ello nos vamos a Devices, en el conjunto de opciones del IoT Hub, y pulsamos Add Device:
Rellenamos el campo de nombre y pulsamos save:
Si todo fue bien debería de aparecer el dispositivo que hemos creado de la siguiente manera:
La telemetría que vamos a recoger del dispositivo IoT la vamos a guardar en Azure CosmosDB, por ello vamos a crear este recurso:
Una vez pulsado Create, vamos a seleccionar la primera opción, puesto que queremos utilizar SQL para manejar la base de datos:
Rellenamos los datos que nos piden sin cambiar ninguna opción y pulsamos review+create:
Cuando haya finalizado el proceso de creación del recurso debería aparecernos accesible Azure CosmosDB:
En este momento tenemos un entorno en Azure que es capaz de captar los mensajes (Azure IoT Hub), también es capaz de almacenarlos (Azure CosmosDB) pero hace falta crear un flujo de datos desde la entrada a la salida. Para ello vamos a levantar el recurso Stream Analytics Job:
Ahora rellenamos Job name, así como la suscripción y el grupo de recursos a utilizar. Entonces pulsaremos create.
Cuando se haya creado, accedemos al Stream Analytics Job:
Nos vamos a la opción Inputs de la barra lateral izquierda y pulsamos Add stream input- IoT Hub:
Ahora rellenamos los campos que aparecen, seleccionando el IoT Hub que hemos creado anteriormente y pulsamos Save:
Debería de aparecernos esta entrada de la siguiente manera:
Aunque no es obligatorio, para chequear que este input apunta al IoT Hub de manera correcta se puede pulsar sobre el primer botón que aparece a la derecha del todo de la imagen anterior.
Ahora vamos a definir el output en el Stream analytics Job, para ello nos vamos a la opción Outputs del menú de la izquierda y pulsamos Add-Cosmos DB:
Ahora rellenamos las opciones de la salida de datos y pulsamos Save. En mi caso:
Ahora en el menú principal del Stream Analytics Job buscamos el apartado query y la relleamos con los nombres de la entrada y salida que acabamos de crear, en mi caso:
Con esto que acabamos de hacer, enviamos toda la telemetría que llega al IoT Hub hacia el CosmosDB. Lo único que falta es pulsar sobre Start, arriba a la izquierda, para poner en funcionamiento el job.
El entorno de Azure ya quedaría completamente configurado, por tanto ahora vamos a configurar el entorno de Python necesario para interconectar los dispositivos IoT con el IoT Hub de Azure.
3. Entorno de python
En mi caso voy a utilizar Visual Studio Code para desarrollar un programa en Python que sea capaz de generar telemetría (simulación de un sensor real) y enviarla al IoT Hub de Azure que hemos creado. Como tenemos el Stream Analytics Job corriendo, automáticamente se procesarán estos datos, almacenándose en el CosmosDB.
Además también abriremos la posibilidad de utilizar el IoT Hub de Azure para comunicarnos con los dispositivos, es decir, podremos mandar mensajes a los dispositivos. Todo esto gracias al programa de Python que vamos a crear.
Este programa se basa en el SDK de Azure IoT de Pyhton, que se encuentra en Github:
La librería que utilizaremos es azure-iot-device. Por tanto se puede instalar bajándola de github o simplemente corriendo el siguiente comando en nuestro entorno de Python:
pip install azure-iot-device
Una vez instalada, abrimos un script de Python e importamos las siguientes librerías:
Como he comentado anteriormente los mensajes serán bidireccionales entre dispositivo y IoT Hub. Por ello vamos a crear dos funciones, una para cada tipo de comunicación.
Para escuchar mensajes del IoT Hub desde el dispositivo definimos la siguiente función:
Esta función recibe un objeto de tipo cliente creado durante la conexión entre el dispositivo IoT y el IoT Hub. Entonces se pone el cliente a escuchar mensajes (el cliente es el dispositivo iot) y cuando llega alguno (se espera que sea tipo json) lo decodifica y lo muestra por pantalla. Aunque no parezca a simple vista que tenga mucha utilidad enviar mensajes a los dispositivos, es de gran utilidad. Supongamos que los dispositivos se encuentran en un sistema SCADA con un backend programado que es capaz de ordenar actualizar dichos dispositivos. Entonces desde nuestro centro de control (IoT Hub) podemos enviar un mensaje “especial” a los dispositivos proporcionándoles la url donde se encuentra el archivo de la actualización para que el backend ordene actualizarlos utilizando dicho software.
Para enviar la telemetría de los dispositivos iot al IoT Hub vamos a crear otra función:
Hemos supuesto que tenemos un sensor que mide la latitud, longitud y altitud terrestre. Por tanto se simula dicha telemetría y se codifica mediante la función Message. Una vez codificado se envía cada segundo al IoT Hub el mensaje simulado en dicho momento.
Una vez tenemos ambas funciones, creamos el main de nuestro programa en Python:
Lo primero de todo es establecer la connection_string, es decir, la clave que se utiliza para autenticarse con el IoT Hub como el dispositivo que hemos creado anteriormente, por tanto recogemos dicha clave (primary key) desde el IoT Hub en Azure, en el apartado del dispositivo que hemos creado y la ponemos en una variable de nuestro main:
El siguiente paso es lanzar un hilo que ejecute la función ReceiveMessage, para escuchar los mensajes que llegan al dispositivo iot desde el IoT Hub. También lanzaremos otro hilo que esté mandando la telemetría al IoT Hub cada segundo, mediante la función SendTelemetry.
4. Ejecución del programa
Ejecutamos el programa y debería empezar a mostrar por pantalla signos de que ese están enviando mensajes satisfactoriamente:
De hecho, si nos vamos a Azure CosmosDB y accedemos al Data Explorer, se habrá creado la base de datos y el contenedor llamado telemtetría. Allí podremos ver como se van almacenando los mensajes en tiempo real:
Se puede ver como, además de las variables que hemos simulado, se incluyen algunas otras aportando información acerca del envío de dichos datos. Por ejemplo, fijándonos en las variables “EventEnqueuedUtcTime” y “EventProcessedUtcTime”, (timestamp del momento en que el mensaje se pone en cola y timestamp del momento en que el mensaje es procesado y almacenado en CosmosDB) nos damos cuenta que los datos son procesados en cuestión de décimas de segundo.
Por otro lado, vamos a enviar un mensaje desde el IoT Hub al dispositivo en cuestión para comprobar que éste puede recibirlo sin problema alguno. Para ello nos vamos al IoT Hub, pichamos en Devices y seleccionamos el dispositivo que creamos anteriormente:
Ahora seleccionamos Message to Device:
Y vamos a escribir un mensaje manualmente para enviarlo, teniendo en cuenta que en nuestro programa en Python hemos supuesto que sería en formato json:
Pulsamos Send Message y nos vamos al entorno de Python, donde habrá aparecido en la consola el mensaje siguiente:
Es el mismo mensaje que hemos enviado, lo cuál indica que hemos captado el mensaje enviado al dispositivo iot.
5. Conclusión
Microsoft Azure nos brinda la posibilidad de crear un entorno de extracción de datos en tiempo real totalmente escalable y fácil de configurar. Además, gracias al SDK para Python, podemos utilizar código para automatizar procesos y hacer pruebas durante el desarrollo de la solución.
Aunque en nuestro caso hemos llevado a cabo las pruebas simulando los datos, en caso de disponer de un sistema SCADA real, sería tan fácil como alojar el programa de Python en la máquina donde se sitúa el PLC, y cambiar las líneas de código que simulan los datos por líneas que extraigan de la máquina local los datos que le llegan en tiempo real de los dispositivos iot.