IoT MQTT connect en la Onesait Platform

Hoy os traemos una de esas entradas a las que sacar mucho partido si os gusta enredar con cacharros IoT. A lo largo del workshop vamos a aprender los conocimientos básicos para poder a comenzar a trabajar con la Onesait Platform de manera completa, desde el campo (parte Edge) a la nube (parte Cloud).

Para ello, vamos a definir paso a paso la configuración de un dispositivo para el envío de información a la nube, donde posteriormente podremos tratarla y visualizarla.

Herramientas necesarias

Para realizar una integración completa end to end (E2E), vamos a necesitar de los siguientes sistemas para poder crear el flujo del dato completo.

1.- Dispositivo de campo

Para este workshop, vamos a utilizar un dispositivo de M5stack, concretamente el M5StickC. Este modelo nos ofrece un micro programable disponiendo de diferentes escudos que nos permiten ampliar sus funcionalidades. En esta entrada, vamos a hacer uso del dispositivo meteorológico y GPS de la propia marca.

2.- Entorno UIFlow

Este entorno de programación es una interfaz web mediante la cual vamos a poder programar nuestro módulo M5StickC.

UIFlow dispone de una interfaz muy amigable y sencilla para programar, del estilo de Scratch pero para microcontroladores, que es a la vez bastante potente y flexible. Respecto a los lenguajes de programación disponibles, cuenta con dos opciones:

  • Blockly: que es lenguaje tipo Scratch desarrollado por Google.
  • MicroPython: que es un Python adaptado para ejecutarse en una gran variedad de microcontroladores.

La Onesait Platform

La Onesait Platform es una plataforma digital que proporciona la flexibilidad para que los desarrolladores puedan construir sus propias soluciones de una manera sólida y ágil utilizando tecnologías Open Source, una arquitectura flexible y un enfoque innovador. 

Está basada, como decimos, en componentes Open Source, y cubre todo el ciclo de vida de la información, desde la ingesta hasta la visualización, pasando por su proceso y análisis.

Ofrece una consola web unificada para los perfiles de desarrollo y operación de las soluciones. 

Gracias a los diferentes asistentes y al encapsulado de las mejores prácticas, es posible desarrollar sistemas con arquitecturas complejas de forma sencilla, reduciendo costes y time to market (T2M). La Plataforma tiene una especialización para Edge y otra para Cloud:

Para este workshop vamos a hacer uso de ambas capas; de la Edge para recopilar nuestros datos, y de la Cloud para almacenarlos y mostrarlos en uno de esos flamantes Dashboards que tanto nos gustan.

Configuración del dispositivo

Como hemos dicho al principio de la entrada, vamos a utilizar de un M5StickC como dispositivo programable, donde podremos añadir diferentes entradas para ser procesadas y enviadas a la nube. Pero eso no significa que no podamos usar otras placas, como Arduino, Raspberry Pi o cualquier otra que tengamos a mano (previamente hemos usado un Arduino para algo similar).

En el caso del M5StickC, disponemos de un interfaz bastante amigable (el comentado UIFlow) que nos va a permitir trabajar con él aun si tener un conocimiento muy avanzado de programación.

Lo primero que hay que hacer antes de comenzar a trabajar con el dispositivo, es indicar qué escudos o sistemas vamos a incluir en el M5StickC. Para este ejemplo, vamos a trabajar como hemos dicho con dos: un escudo que recuperará información medioambiental, y un módulo GPS.

Para indicar el escudo de sensores medioambientales, pulsaremos en el botón de «Hat», y en el listado de escudos que se desplegará, seleccionaremos el de «ENV».

Seguidamente, para indicar que tenemos un GPS, pulsaremos en el botón de «Units», y en el listado que aparece elegimos «GPS».

Una vez que tenemos ambos seleccionados, podremos ver en el desplegable de acciones de ambos elementos añadidos, donde escogiendo cada uno de ellos podremos ver las acciones disponibles. Por ejemplo, si seleccionamos el GPS, nos aparecerá lo siguiente:

Una vez realizada la configuración inicial del dispositivo, estamos preparados para darle de alta en el IoTHub, que es el sistema global de gestión de toda la infraestructura Edge, motivo por el que es frecuente desplegarlo en Cloud u on-premise dentro de un centro de operación y control.

Siendo el componente global de gestión de nodos distribuidos, nos permite:

  • Gestionar altas y bajas de dispositivos y la gestión por proyectos y entornos.
  • Comunicación segura con los nodos y dispositivos, incluida la atestación de estos.
  • La gestión de un repositorio de configuración de los Edge Engine remotos.
  • La realización de operaciones de actualización y/o configuraciones de aplicaciones desplegadas.
  • La gestión remota con consola de operación SSH.

Por tanto, desde aquí, vamos a poder mantener un control del dispositivo cubriendo la comunicación con la seguridad necesaria. Para dar de alta al dispositivo, necesitamos disponer de la dirección MAC del mismo, para poder identificarlo.

Para obtener dicha información, vamos a cargar el siguiente código en el M5StickC para que nos muestre la dirección por pantalla:

from m5stack import * 
from m5ui import *
from uiflow import *
import espnow

macAddr = None

espnow.init()

label0 = M5TextBox(78, 0, "Text", lcd.FONT_Default, 0xFFFFFF, rotate=90)

macAddr = str((espnow.get_mac_addr()))
macAddr = macAddr.replace(':', '').upper()

label0.setText(str(macAddr))

Para realizar la carga, conectaremos el dispositivo mediante USB al ordenador, seleccionaremos el COM correspondiente y el dispositivo que estamos utilizando.

Posteriormente lanzaremos la carga al dispositivo:

Una vez que se haya terminado la carga, deberíamos visualizar en la pantalla del dispositivo la dirección MAC del mismo. Pues nos la apuntamos y procedemos a dar de alta el dispositivo en el IoTHub de la Plataforma.

Proyecto IoT

Para empezar, introduciremos nuestro usuario y contraseña en el entorno de la Plataforma Edge, y una vez dentro, navegaremos al menú de «Proyectos», y crearemos un Nuevo Proyecto.

En el modal que aparece, indicaremos un nombre para nuestro proyecto y le daremos a guardar.

Una vez creado el proyecto, veremos que aparece en el listado lateral. Seleccionándolo, podremos ver que se ha generado un entorno llamado «DEV».

Seguidamente vamos a dar de alta el dispositivo, y a enlazarlo con nuestro proyecto. Esto lo haremos desde el menú Landscape > Dispositivos de campo.

En la pantalla de dispositivos de campo, seleccionaremos la opción de «Añadir Dispositivo», y completaremos la información necesaria para nuestro M5StickC.

  • MAC: aquí introduciremos la dirección MAC de nuestro.
  • Longitud, Latitud y Elevación: estos campos hacer referencia a la localización geoespacial de nuestro dispositivo. Como contamos con un GPS, no hace falta indicar ningún valor.
  • Descripción: un pequeño texto que describa la funcionalidad de nuestro dispositivo, o lo que sea.
  • Protocolo: la forma en la que se conectará a internet. En este caso, vía WiFi.
  • Producto: nuestro dispositivo.
  • Proyecto: el que hemos creado en el paso anterior.
  • Compañía: el nombre que le damos a nuestra organización, si es que tenemos.
  • Entorno: el asociado al Proyecto, que en este caso es «DEV».

Una vez dado de alta, podremos conocer el estado del dispositivo desde el proyecto generado previamente, y desde el cual podríamos añadir nuevos dispositivos directamente.

En este caso, el dispositivo se encuentra apagado y no envía información, por lo que aparece como «desconectado» en la imagen.

Una vez configurado nuestro dispositivo, el IotHub va a ser el encargado de definir sus conexiones e implantarle un token de autenticación. Para obtener dicha información, volveremos al listado de los dispositivos (menú Landscape > Dispositivos de campo), y pulsaremos sobre los tres puntos que hay en nuestro dispositivo.

Una vez que pulsemos, nos aparecerá un modal con la información del token de autenticación asociado, y los canales de conexión MQTT que nos van a permitir interactuar completamente con el dispositivo.

Para el token, veremos un modal como este:

Y para las conexiones MQTT, otro como este:

Finalmente y con toda la seguridad sobre el dispositivo ya lista, vamos a dar de alta un conector para terminar de securizar toda la comunicación. Para ello, nos iremos a conectores y pulsaremos en «crear un nuevo conector».

Una vez generado, el conector se asociará a un proyecto y un entorno, ofreciéndonos tanto los tópicos definidos para MQTT y la autenticación necesaria para dicho conector, que posteriormente utilizaremos en la configuración de conexión desde el FlowEngine.

Envío de información a la nube

Una vez determinado los puntos de acceso a nuestro sistema, generaremos el código para el envío de información. Esto lo vamos a hacer en lenguaje de MicroPython, generando tanto la comunicación con la nube como las trazas a enviar.

A continuación se muestra el código generado para la carga en el dispositivo, donde se definen dos funciones, tanto de para enviar información como recibir comandos desde la nube. Esto será lo que cargaremos en el M5StickC.

En primer lugar, se inicializa el código, se carga las librerías necesarias y se definen las variables a utilizar:

#######Carga de librerías######
from m5stack import * 
from m5ui import *
from uiflow import *
import wifiCfg
import espnow
from m5mqtt import M5mqtt
import hat
import json
import unit
import machine
import urequests
import machine
from micropython import const
import ntptime

#####Definición de variables globales#####
setScreenColor(0x111111)
macAddr = None
id_client_control = None
id_client_business = None
business_topic_p = None
business_topic_s = None
sensorData = None
mensaje = None
ssid = "<wifi_network>" #configuración conexión wifi
password_wifi = "<password>"
wifiCfg.wlan_sta.active(True)
wifiCfg.doConnect(ssid, password_wifi) # Inicialización conexión wifi

Después, se inicia el código y se realiza la conexión a la red WiFi predefinida, adquiriendo la zona horaria e iniciando la recogida de datos por parte del GPS.

espnow.init()

while (not wifiCfg.wlan_sta.isconnected()):
    wifiCfg.doConnect(ssid, password_wifi)

ntp = ntptime.client(host='es.pool.ntp.org', timezone=1) #Selección de zona horaria.
rtc.setTime((ntp.year()), (ntp.month()), (ntp.day()), (ntp.hour()), (ntp.minute()), (ntp.second()))

hat_env0 = hat.get(hat.ENV)
gps0 = unit.get(unit.GPS,unit.PORTA)
pir0 = unit.get(unit.PIR, (21,22))

Una vez iniciado el sistema, vamos a proceder a definir la información que queremos que se muestre en la pantalla, y la definición de comunicación MQTT: definiendo el punto de acceso, puerto y token autenticación (el id_client_business siempre estará definido como «b_<macAddr>», manteniendo un control de la finalidad del mensaje generado).

espnow.init()
####Definición y creación de posición de textos en la pantalla del dispositivo####
label0 = M5TextBox(78, 0, "Text", lcd.FONT_Default, 0xFFFFFF, rotate=90)
label1 = M5TextBox(61, 0, "Text", lcd.FONT_Default, 0xFFFFFF, rotate=90)
label2 = M5TextBox(44, 0, "Text", lcd.FONT_Default, 0xFFFFFF, rotate=90)
label3 = M5TextBox(26, 0, "Text", lcd.FONT_Default, 0xFFFFFF, rotate=90)

macAddr = str((espnow.get_mac_addr()))  # Recuperación de la MAC del dispositivo
macAddr = macAddr.replace(':', '').upper()
id_client_control = macAddr
id_client_business = "b_"+id_client_control  # id cliente de negocio.
frec=1 // Valor inicial de frecuencia de envío
business_topic_p = "business/INNOVATORS_TEAM_0/DEV/server" # tópico de subida
business_topic_s = "business/INNOVATORS_TEAM_0/DEV/device/"+id_client_business #tópico de bajada
label0.setText(str(macAddr))
label1.setText(str(id_client_business))
label3.setText('Hello GPS')
label0.setText(str(business_topic_p))
wait(3)

label0.setText('Inicio Envío')
label1.setText(str(str(macAddr)))
label3.setText('Searching for Sats')
wait(3)

m5mqtt = M5mqtt(str(id_client_business), 'iothub02.onesaitplatform.com', 8883, str(id_client_control), 'rY2kOwXZ', 30, ssl = True) # Inicialización de comunicación MQTT 

Seguidamente se define la función de envío device to Cloud para el envío de información, y Cloud to device para recibir el mensaje desde la nube, donde enviaremos el nuevo valor para la frecuencia de envío.

def fun_business_c2d_(topic_data):   # Función Cloud to device. Para la recepción MQTT 
  global m5mqtt,business_topic_p,gps0,macAddr,frec
  #Proceso del comando Cloud-2-Device
  label1.setText(str(topic_data))
  wait(0.5)
  jsonTopic_data=json.loads(topic_data)
  frec=jsonTopic_data["frec"]
   #Ejemplo, función de Echo del mensaje mandado
  mensaje_echo = {'deviceId':macAddr,'latitude':(gps0.latitude),'longitude':(gps0.longitude),'timestamp':ntp.formatDatetime('-', ':'),'payload':jsonTopic_data}
  wait(0.2)
  m5mqtt.publish(str(business_topic_p),json.dumps(mensaje_echo))

def fun_business_d2c_(topic_data):   #Función device to Cloud, para el envío por MQTT
  global m5mqtt,business_topic_p
  #Proceso del comando Cloud-2-Device
  label1.setText(str(topic_data))  
  m5mqtt.publish(str(business_topic_p),str((json.dumps(topic_data))))

Finalmente, iniciaremos la comunicación MQTT y el envío continuo del mensaje generado, a partir de la frecuencia definida inicialmente (0,5 segundos), o por la enviada desde la nube.

m5mqtt.subscribe(business_topic_s, fun_business_c2d_) # Suscripción a tópico MQTT para recepción de mensajes desde la nube. Activando la función c2d al momento de la recepción. 
m5mqtt.start() # Inicio MQTT
while True:
    sensorData = {'hum':(hat_env0.humidity),'temp':(hat_env0.temperature),'press':(hat_env0.pressure),'light':(pir0.state)}
    label2.setText(str(id_client_business))
    label3.setText(str(business_topic_p))
    mensaje = {'deviceId':macAddr,'latitude':(gps0.latitude),'longitude':(gps0.longitude),'timestamp':ntp.getTimestamp()}
    mensaje.update(sensorData)
    #Proceso del envio de datos Device-2-Cloud
    fun_business_d2c_(mensaje) 
    label0.setText('Publicando...')
    M5Led.on()
    wait(0.5)
    M5Led.off()
    mensaje.clear()

sensorData.clear()
    wait(frec)
    while (not wifiCfg.wlan_sta.isconnected()):
        wifiCfg.doConnect(ssid, password_wifi)

Podéis descargaros todo el código al completo desde este enlace.

Configuración Cloud

Una vez que tenemos configurado y gestionado nuestro dispositivo, vamos a generar el modelo de datos de la información en la Plataforma, y a la adquisición y almacenamiento de la misma. Todo ello mientras definimos el envío de comandos al dispositivo.

Para ello, vamos a hacer uso del entorno CloudLab de la Onesait Platform, que como su nombre indica corresponde a la capa Cloud de la Plataforma. Este entorno es abierto y gratuito, el cual usamos para que todo el mundo pueda probar las funcionalidades y la potencia de la Plataforma.

Una vez que accedamos con nuestro usuario, navegaremos al menú Desarrollo> Mis Ontologías.

Aquí, crearemos una nueva ontología paso a paso, definiendo la información necesaria.

Respecto a la plantilla a utilizar, haremos uso de una plantilla vacía, creando seguidamente todos los campos que queramos recuperar de nuestro dispositivo.

Una vez declarados los campos, generaremos una instancia de prueba, para ver si el registro es tal como queremos, y crearemos la nueva ontología.

Para ingestar esta ontología con los datos del dispositivo, vamos a crear un flujo mediante Flow Engine, al cual podemos acceder desde el menú Desarrollo > Mis Flujos.

La comunicación a realizar será mediante MQTT, gestionando dicha comunicación mediante el IoTHub y los tópicos generados para nuestro proyecto. Para ello, creamos un flujo de escucha al tópico device to Cloud y modelaremos el mensaje entrante para almacenarlo directamente en nuestro repositorio.

A partir del módulo MQTT ofrecido por Node-Red, definiremos el broker MQTT y la entrada al flujo.

Completaremos la información del nuevo broker MQTT con la información previamente generada en el IoTHub y mediante una comunicación segura por el puerto 8883.

Del mismo modo, completaremos la comunicación mediante el tópico device to Cloud.

Configurada la entrada de la información, nos queda por modelar el mensaje entrante para insertarlo en la ontología seleccionada.

Para el envío de trazas Cloud to device, se procede a desarrollar un API en FlowEngine, la cual nos va a servir como entrada para el envío por MQTT desde la nube al dispositivo. En este ejemplo, enviaremos la nueva frecuencia de envío.

Finalizados ambos flujos de información, disponemos de dos sistemas para recibir y enviar información al M5StickC.

Podéis descargaros todo el código al completo desde este enlace, que podréis importar directamente a vuestro flujo.

Puesta en marcha del sistema

Una vez conectado el dispositivo y cargado el programa creado en el UiFLow, comenzará a enviar información cada segundo de manera inicial. Podremos comprobar dicha ingesta de datos tanto en el flujo generado previamente, como consultas a la ontología generada.

Para esto último, usaremos a la herramienta de consultas de la Plataforma, la cual es accesible desde el menú Tools>Query Tools. Aquí consultaremos nuestro ontología, para confirmar que efectivamente está almacenando las trazas generadas por nuestro dispositivo.

En el momento que estemos ingestando información en la ontología y el M5StickC esté en funcionamiento, podremos observar que en el IoTHub nos aparece como funcionando.

Visualización de los datos

Bueno, pues una vez que tenemos el dispositivo enviado datos y la ontología almacenándolos, nos queda visualizar los datos de una manera gráfica. Así que hemos creado un pequeño Dashboard que muestra la información en tablas, gráficos y hasta con un mapita de localización:

Aunque el Dashboard parezca complejo, la Plataforma nos facilita su creación mediante asistentes guiados de los diferentes gadgets, y además nos permite la creación de plantillas para generar gadgets a medida.

Ya hemos tratado previamente cómo generar un Dashboard (en el Portal del desarrollador contamos con diferentes guías). Sin embargo, para este workshop vamos a comentar con mayor detalle un Gadget en concreto, que nos va a permitir invocar el API que previamente hemos generado en Flow Engine, y donde podremos enviar un valor que definirá la nueva frecuencia de envío del dispositivo.

Para crear este Gadget, navegaremos al menú de Visualization & GIS > Mis Gadgets.

Aquí crearemos una nueva plantilla de Gadgets, e implementaremos el código HTML y JavaScript para poder generar un inbox numérico en donde introducir nuestra nueva frecuencia de recepción de datos, y un botón que ejecutará la llamada al API generada, enviando el valor seleccionado.

El código de la plantilla HTML la podéis descargar desde este enlace, y la de JavaScript desde este otro enlace.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *